LineBreakCache.h (3097B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_intl_LineBreakCache_h__ 7 #define mozilla_intl_LineBreakCache_h__ 8 9 #include "nsIObserver.h" 10 #include "nsString.h" 11 #include "nsTArray.h" 12 #include "nsThreadUtils.h" 13 #include "mozilla/MruCache.h" 14 #include "mozilla/StaticPtr.h" 15 #include "mozilla/intl/Segmenter.h" 16 17 namespace mozilla { 18 namespace intl { 19 20 namespace detail { 21 struct LBCacheKey { 22 const char16_t* mText; 23 uint32_t mLength; 24 // ICU4X segmenter results depend on these flags, so they need to be part 25 // of the cache key. (Legacy ComplexBreaker just leaves them as default.) 26 WordBreakRule mWordBreak = WordBreakRule::Normal; 27 LineBreakRule mLineBreak = LineBreakRule::Auto; 28 bool mIsChineseOrJapanese = false; 29 }; 30 31 struct LBCacheEntry { 32 nsString mText; 33 nsTArray<uint8_t> mBreaks; 34 WordBreakRule mWordBreak = WordBreakRule::Normal; 35 LineBreakRule mLineBreak = LineBreakRule::Auto; 36 bool mIsChineseOrJapanese = false; 37 }; 38 } // namespace detail 39 40 // Most-recently-used cache for line-break results, because finding line- 41 // breaks may be slow for complex writing systems (e.g. Thai, Khmer). 42 // The MruCache size should be a prime number that is slightly less than a 43 // power of two. 44 class LineBreakCache : public MruCache<detail::LBCacheKey, detail::LBCacheEntry, 45 LineBreakCache, 4093> { 46 public: 47 static void Initialize(); 48 static void Shutdown(); 49 50 using KeyType = detail::LBCacheKey; 51 using EntryType = detail::LBCacheEntry; 52 53 static LineBreakCache* Cache() { 54 if (!sBreakCache) { 55 sBreakCache = new LineBreakCache(); 56 } 57 return sBreakCache; 58 } 59 60 static HashNumber Hash(const KeyType& aKey) { 61 HashNumber h = HashString(aKey.mText, aKey.mLength); 62 h = AddToHash(h, aKey.mWordBreak); 63 h = AddToHash(h, aKey.mLineBreak); 64 h = AddToHash(h, aKey.mIsChineseOrJapanese); 65 return h; 66 } 67 68 static bool Match(const KeyType& aKey, const EntryType& aEntry) { 69 return nsDependentSubstring(aKey.mText, aKey.mLength) 70 .Equals(aEntry.mText) && 71 aKey.mWordBreak == aEntry.mWordBreak && 72 aKey.mLineBreak == aEntry.mLineBreak && 73 aKey.mIsChineseOrJapanese == aEntry.mIsChineseOrJapanese; 74 } 75 76 static void CopyAndFill(const nsTArray<uint8_t>& aCachedBreakBefore, 77 uint8_t* aBreakBefore, uint8_t* aEndBreakBefore) { 78 auto* startFill = std::copy(aCachedBreakBefore.begin(), 79 aCachedBreakBefore.end(), aBreakBefore); 80 std::fill(startFill, aEndBreakBefore, false); 81 } 82 83 class Observer final : public nsIObserver { 84 ~Observer() = default; 85 86 public: 87 NS_DECL_ISUPPORTS 88 NS_DECL_NSIOBSERVER 89 }; 90 91 private: 92 static StaticAutoPtr<LineBreakCache> sBreakCache; 93 }; 94 95 } // namespace intl 96 } // namespace mozilla 97 98 #endif /* mozilla_intl_LineBreakCache_h__ */