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