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