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