/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_intl_LineBreakCache_h__ #define mozilla_intl_LineBreakCache_h__ #include "nsIObserver.h" #include "nsString.h" #include "nsTArray.h" #include "nsThreadUtils.h" #include "mozilla/ArrayUtils.h" #include "mozilla/MruCache.h" #include "mozilla/StaticPtr.h" #include "mozilla/intl/Segmenter.h" namespace mozilla { namespace intl { namespace detail { struct LBCacheKey { const char16_t* mText; uint32_t mLength; // ICU4X segmenter results depend on these flags, so they need to be part // of the cache key. (Legacy ComplexBreaker just leaves them as default.) WordBreakRule mWordBreak = WordBreakRule::Normal; LineBreakRule mLineBreak = LineBreakRule::Auto; bool mIsChineseOrJapanese = false; }; struct LBCacheEntry { nsString mText; nsTArray mBreaks; WordBreakRule mWordBreak = WordBreakRule::Normal; LineBreakRule mLineBreak = LineBreakRule::Auto; bool mIsChineseOrJapanese = false; }; } // namespace detail // Most-recently-used cache for line-break results, because finding line- // breaks may be slow for complex writing systems (e.g. Thai, Khmer). // The MruCache size should be a prime number that is slightly less than a // power of two. class LineBreakCache : public MruCache { public: static void Initialize(); static void Shutdown(); using KeyType = detail::LBCacheKey; using EntryType = detail::LBCacheEntry; static LineBreakCache* Cache() { if (!sBreakCache) { sBreakCache = new LineBreakCache(); } return sBreakCache; } static HashNumber Hash(const KeyType& aKey) { HashNumber h = HashString(aKey.mText, aKey.mLength); h = AddToHash(h, aKey.mWordBreak); h = AddToHash(h, aKey.mLineBreak); h = AddToHash(h, aKey.mIsChineseOrJapanese); return h; } static bool Match(const KeyType& aKey, const EntryType& aEntry) { return nsDependentSubstring(aKey.mText, aKey.mLength) .Equals(aEntry.mText) && aKey.mWordBreak == aEntry.mWordBreak && aKey.mLineBreak == aEntry.mLineBreak && aKey.mIsChineseOrJapanese == aEntry.mIsChineseOrJapanese; } static void CopyAndFill(const nsTArray& aCachedBreakBefore, uint8_t* aBreakBefore, uint8_t* aEndBreakBefore) { auto* startFill = std::copy(aCachedBreakBefore.begin(), aCachedBreakBefore.end(), aBreakBefore); std::fill(startFill, aEndBreakBefore, false); } class Observer final : public nsIObserver { ~Observer() = default; public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER }; private: static StaticAutoPtr sBreakCache; }; } // namespace intl } // namespace mozilla #endif /* mozilla_intl_LineBreakCache_h__ */