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