blob: d1232a29b5aa923196dd1d6f37abf9c906797649 [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080020#include <functional>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080021#include <memory>
22#include <string>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070023#include <unordered_map>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080024#include <vector>
25
Adam Lesinskid0f492d2017-04-03 18:12:45 -070026#include "android-base/macros.h"
Adam Lesinskid5083f62017-01-16 15:07:21 -080027#include "androidfw/StringPiece.h"
28
Adam Lesinskice5e56e2016-10-21 17:56:45 -070029#include "ConfigDescription.h"
30#include "util/BigBuffer.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070031
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080032namespace aapt {
33
34struct Span {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 std::string name;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036 uint32_t first_char;
37 uint32_t last_char;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080038};
39
40struct StyleString {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070041 std::string str;
42 std::vector<Span> spans;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080043};
44
45class StringPool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070046 public:
Adam Lesinskib54ef102016-10-21 13:38:42 -070047 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;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 ConfigDescription config;
Adam Lesinskib54ef102016-10-21 13:38:42 -070057
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) {}
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 class Entry;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080066
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 class Ref {
68 public:
69 Ref();
70 Ref(const Ref&);
71 ~Ref();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080072
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073 Ref& operator=(const Ref& rhs);
Adam Lesinski75421622017-01-06 15:20:04 -080074 bool operator==(const Ref& rhs) const;
75 bool operator!=(const Ref& rhs) const;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 const std::string* operator->() const;
77 const std::string& operator*() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 size_t index() const;
80 const Context& GetContext() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080081
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 private:
83 friend class StringPool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080084
Adam Lesinskicacb28f2016-10-19 12:18:14 -070085 explicit Ref(Entry* entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080086
Adam Lesinskice5e56e2016-10-21 17:56:45 -070087 Entry* entry_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 class StyleEntry;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080091
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 class StyleRef {
93 public:
94 StyleRef();
95 StyleRef(const StyleRef&);
96 ~StyleRef();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080097
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 StyleRef& operator=(const StyleRef& rhs);
Adam Lesinski75421622017-01-06 15:20:04 -080099 bool operator==(const StyleRef& rhs) const;
100 bool operator!=(const StyleRef& rhs) const;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 const StyleEntry* operator->() const;
102 const StyleEntry& operator*() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 size_t index() const;
105 const Context& GetContext() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800106
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700107 private:
108 friend class StringPool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800109
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 explicit StyleRef(StyleEntry* entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800111
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 StyleEntry* entry_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800114
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 class Entry {
116 public:
117 std::string value;
118 Context context;
119 size_t index;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800120
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121 private:
122 friend class StringPool;
123 friend class Ref;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800124
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 int ref_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800127
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 struct Span {
129 Ref name;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 uint32_t first_char;
131 uint32_t last_char;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800133
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 class StyleEntry {
135 public:
136 Ref str;
137 std::vector<Span> spans;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800138
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 private:
140 friend class StringPool;
141 friend class StyleRef;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800142
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 int ref_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800145
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 using const_iterator = std::vector<std::unique_ptr<Entry>>::const_iterator;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800147
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148 static bool FlattenUtf8(BigBuffer* out, const StringPool& pool);
149 static bool FlattenUtf16(BigBuffer* out, const StringPool& pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800150
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700151 StringPool() = default;
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700152 StringPool(StringPool&&) = default;
153 StringPool& operator=(StringPool&&) = default;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800154
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 /**
156 * Adds a string to the pool, unless it already exists. Returns
157 * a reference to the string in the pool.
158 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800159 Ref MakeRef(const android::StringPiece& str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800160
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161 /**
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 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800166 Ref MakeRef(const android::StringPiece& str, const Context& context);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800167
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 /**
169 * Adds a style to the string pool and returns a reference to it.
170 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 StyleRef MakeRef(const StyleString& str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800172
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700173 /**
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 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178 StyleRef MakeRef(const StyleString& str, const Context& context);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800179
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700180 /**
181 * Adds a style from another string pool. Returns a reference to the
182 * style in the string pool.
183 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 StyleRef MakeRef(const StyleRef& ref);
Adam Lesinski769de982015-04-10 19:43:55 -0700185
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 /**
187 * Moves pool into this one without coalescing strings. When this
188 * function returns, pool will be empty.
189 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700190 void Merge(StringPool&& pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800191
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 /**
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 * Returns the number of strings in the table.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700194 */
195 inline size_t size() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800196
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700197 /**
198 * Reserves space for strings and styles as an optimization.
199 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700200 void HintWillAdd(size_t string_count, size_t style_count);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800201
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700202 /**
203 * Sorts the strings according to some comparison function.
204 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700205 void Sort(const std::function<bool(const Entry&, const Entry&)>& cmp);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800206
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700207 /**
208 * Removes any strings that have no references.
209 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700210 void Prune();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800211
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 private:
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700213 DISALLOW_COPY_AND_ASSIGN(StringPool);
214
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700215 friend const_iterator begin(const StringPool& pool);
216 friend const_iterator end(const StringPool& pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800217
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700218 static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8);
Adam Lesinski24aad162015-04-24 19:19:30 -0700219
Adam Lesinskid5083f62017-01-16 15:07:21 -0800220 Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800221
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700222 std::vector<std::unique_ptr<Entry>> strings_;
223 std::vector<std::unique_ptr<StyleEntry>> styles_;
Adam Lesinskid5083f62017-01-16 15:07:21 -0800224 std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225};
226
227//
228// Inline implementation
229//
230
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231inline size_t StringPool::size() const { return strings_.size(); }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800232
233inline StringPool::const_iterator begin(const StringPool& pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 return pool.strings_.begin();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800235}
236
237inline StringPool::const_iterator end(const StringPool& pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700238 return pool.strings_.end();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800239}
240
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800242
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700243#endif // AAPT_STRING_POOL_H