1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _ANDROID_STRING_POOL_H 18 #define _ANDROID_STRING_POOL_H 19 20 #include <functional> 21 #include <memory> 22 #include <string> 23 #include <unordered_map> 24 #include <vector> 25 26 #include "BigBuffer.h" 27 #include "IDiagnostics.h" 28 #include "android-base/macros.h" 29 #include "androidfw/ConfigDescription.h" 30 #include "androidfw/StringPiece.h" 31 32 namespace android { 33 34 struct Span { 35 std::string name; 36 uint32_t first_char; 37 uint32_t last_char; 38 39 bool operator==(const Span& right) const { 40 return name == right.name && first_char == right.first_char && last_char == right.last_char; 41 } 42 }; 43 44 struct StyleString { 45 std::string str; 46 std::vector<Span> spans; 47 }; 48 49 // A StringPool for storing the value of String and StyledString resources. 50 // Styles and Strings are stored separately, since the runtime variant of this 51 // class -- ResStringPool -- requires that styled strings *always* appear first, since their 52 // style data is stored as an array indexed by the same indices as the main string pool array. 53 // Otherwise, the style data array would have to be sparse and take up more space. 54 class StringPool { 55 public: 56 using size_type = size_t; 57 58 class Context { 59 public: 60 enum : uint32_t { 61 kHighPriority = 1u, 62 kNormalPriority = 0x7fffffffu, 63 kLowPriority = 0xffffffffu, 64 }; 65 uint32_t priority = kNormalPriority; 66 android::ConfigDescription config; 67 68 Context() = default; Context(uint32_t p,const android::ConfigDescription & c)69 Context(uint32_t p, const android::ConfigDescription& c) : priority(p), config(c) { 70 } Context(uint32_t p)71 explicit Context(uint32_t p) : priority(p) { 72 } Context(const android::ConfigDescription & c)73 explicit Context(const android::ConfigDescription& c) : priority(kNormalPriority), config(c) { 74 } 75 }; 76 77 class Entry; 78 79 class Ref { 80 public: 81 Ref(); 82 Ref(const Ref&); 83 ~Ref(); 84 85 Ref& operator=(const Ref& rhs); 86 bool operator==(const Ref& rhs) const; 87 bool operator!=(const Ref& rhs) const; 88 const std::string* operator->() const; 89 const std::string& operator*() const; 90 91 size_t index() const; 92 const Context& GetContext() const; 93 94 private: 95 friend class StringPool; 96 97 explicit Ref(Entry* entry); 98 99 Entry* entry_; 100 }; 101 102 class StyleEntry; 103 104 class StyleRef { 105 public: 106 StyleRef(); 107 StyleRef(const StyleRef&); 108 ~StyleRef(); 109 110 StyleRef& operator=(const StyleRef& rhs); 111 bool operator==(const StyleRef& rhs) const; 112 bool operator!=(const StyleRef& rhs) const; 113 const StyleEntry* operator->() const; 114 const StyleEntry& operator*() const; 115 116 size_t index() const; 117 const Context& GetContext() const; 118 119 private: 120 friend class StringPool; 121 122 explicit StyleRef(StyleEntry* entry); 123 124 StyleEntry* entry_; 125 }; 126 127 class Entry { 128 public: 129 std::string value; 130 Context context; 131 132 private: 133 friend class StringPool; 134 friend class Ref; 135 136 size_t index_; 137 int ref_; 138 const StringPool* pool_; 139 }; 140 141 struct Span { 142 Ref name; 143 uint32_t first_char; 144 uint32_t last_char; 145 }; 146 147 class StyleEntry { 148 public: 149 std::string value; 150 Context context; 151 std::vector<Span> spans; 152 153 private: 154 friend class StringPool; 155 friend class StyleRef; 156 157 size_t index_; 158 int ref_; 159 }; 160 161 static bool FlattenUtf8(BigBuffer* out, const StringPool& pool, IDiagnostics* diag); 162 static bool FlattenUtf16(BigBuffer* out, const StringPool& pool, IDiagnostics* diag); 163 164 StringPool() = default; 165 StringPool(StringPool&&) = default; 166 StringPool& operator=(StringPool&&) = default; 167 168 // Adds a string to the pool, unless it already exists. Returns a reference to the string in the 169 // pool. 170 Ref MakeRef(android::StringPiece str); 171 172 // Adds a string to the pool, unless it already exists, with a context object that can be used 173 // when sorting the string pool. Returns a reference to the string in the pool. 174 Ref MakeRef(android::StringPiece str, const Context& context); 175 176 // Adds a string from another string pool. Returns a reference to the string in the string pool. 177 Ref MakeRef(const Ref& ref); 178 179 // Adds a style to the string pool and returns a reference to it. 180 StyleRef MakeRef(const StyleString& str); 181 182 // Adds a style to the string pool with a context object that can be used when sorting the string 183 // pool. Returns a reference to the style in the string pool. 184 StyleRef MakeRef(const StyleString& str, const Context& context); 185 186 // Adds a style from another string pool. Returns a reference to the style in the string pool. 187 StyleRef MakeRef(const StyleRef& ref); 188 189 // Moves pool into this one without coalescing strings. When this function returns, pool will be 190 // empty. 191 void Merge(StringPool&& pool); 192 strings()193 inline const std::vector<std::unique_ptr<Entry>>& strings() const { 194 return strings_; 195 } 196 197 // Returns the number of strings in the table. size()198 inline size_t size() const { 199 return styles_.size() + strings_.size(); 200 } 201 202 // Reserves space for strings and styles as an optimization. 203 void HintWillAdd(size_t string_count, size_t style_count); 204 205 // Sorts the strings according to their Context using some comparison function. 206 // Equal Contexts are further sorted by string value, lexicographically. 207 // If no comparison function is provided, values are only sorted lexicographically. 208 void Sort(const std::function<int(const Context&, const Context&)>& cmp = nullptr); 209 210 // Removes any strings that have no references. 211 void Prune(); 212 213 private: 214 DISALLOW_COPY_AND_ASSIGN(StringPool); 215 216 static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8, IDiagnostics* diag); 217 218 Ref MakeRefImpl(android::StringPiece str, const Context& context, bool unique); 219 void ReAssignIndices(); 220 221 std::vector<std::unique_ptr<Entry>> strings_; 222 std::vector<std::unique_ptr<StyleEntry>> styles_; 223 std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_; 224 }; 225 226 } // namespace android 227 228 #endif // _ANDROID_STRING_POOL_H 229