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 "util/BigBuffer.h"
21 #include "ConfigDescription.h"
22 #include "util/StringPiece.h"
23 
24 #include <functional>
25 #include <map>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 namespace aapt {
31 
32 struct Span {
33     std::u16string name;
34     uint32_t firstChar;
35     uint32_t lastChar;
36 };
37 
38 struct StyleString {
39     std::u16string str;
40     std::vector<Span> spans;
41 };
42 
43 class StringPool {
44 public:
45     struct Context {
46         uint32_t priority;
47         ConfigDescription config;
48     };
49 
50     class Entry;
51 
52     class Ref {
53     public:
54         Ref();
55         Ref(const Ref&);
56         ~Ref();
57 
58         Ref& operator=(const Ref& rhs);
59         const std::u16string* operator->() const;
60         const std::u16string& operator*() const;
61 
62         size_t getIndex() const;
63         const Context& getContext() const;
64 
65     private:
66         friend class StringPool;
67 
68         Ref(Entry* entry);
69 
70         Entry* mEntry;
71     };
72 
73     class StyleEntry;
74 
75     class StyleRef {
76     public:
77         StyleRef();
78         StyleRef(const StyleRef&);
79         ~StyleRef();
80 
81         StyleRef& operator=(const StyleRef& rhs);
82         const StyleEntry* operator->() const;
83         const StyleEntry& operator*() const;
84 
85         size_t getIndex() const;
86         const Context& getContext() const;
87 
88     private:
89         friend class StringPool;
90 
91         StyleRef(StyleEntry* entry);
92 
93         StyleEntry* mEntry;
94     };
95 
96     class Entry {
97     public:
98         std::u16string value;
99         Context context;
100         size_t index;
101 
102     private:
103         friend class StringPool;
104         friend class Ref;
105 
106         int ref;
107     };
108 
109     struct Span {
110         Ref name;
111         uint32_t firstChar;
112         uint32_t lastChar;
113     };
114 
115     class StyleEntry {
116     public:
117         Ref str;
118         std::vector<Span> spans;
119 
120     private:
121         friend class StringPool;
122         friend class StyleRef;
123 
124         int ref;
125     };
126 
127     using const_iterator = std::vector<std::unique_ptr<Entry>>::const_iterator;
128 
129     static bool flattenUtf8(BigBuffer* out, const StringPool& pool);
130     static bool flattenUtf16(BigBuffer* out, const StringPool& pool);
131 
132     StringPool() = default;
133     StringPool(const StringPool&) = delete;
134 
135     /**
136      * Adds a string to the pool, unless it already exists. Returns
137      * a reference to the string in the pool.
138      */
139     Ref makeRef(const StringPiece16& str);
140 
141     /**
142      * Adds a string to the pool, unless it already exists, with a context
143      * object that can be used when sorting the string pool. Returns
144      * a reference to the string in the pool.
145      */
146     Ref makeRef(const StringPiece16& str, const Context& context);
147 
148     /**
149      * Adds a style to the string pool and returns a reference to it.
150      */
151     StyleRef makeRef(const StyleString& str);
152 
153     /**
154      * Adds a style to the string pool with a context object that
155      * can be used when sorting the string pool. Returns a reference
156      * to the style in the string pool.
157      */
158     StyleRef makeRef(const StyleString& str, const Context& context);
159 
160     /**
161      * Adds a style from another string pool. Returns a reference to the
162      * style in the string pool.
163      */
164     StyleRef makeRef(const StyleRef& ref);
165 
166     /**
167      * Moves pool into this one without coalescing strings. When this
168      * function returns, pool will be empty.
169      */
170     void merge(StringPool&& pool);
171 
172     /**
173      * Retuns the number of strings in the table.
174      */
175     inline size_t size() const;
176 
177     /**
178      * Reserves space for strings and styles as an optimization.
179      */
180     void hintWillAdd(size_t stringCount, size_t styleCount);
181 
182     /**
183      * Sorts the strings according to some comparison function.
184      */
185     void sort(const std::function<bool(const Entry&, const Entry&)>& cmp);
186 
187     /**
188      * Removes any strings that have no references.
189      */
190     void prune();
191 
192 private:
193     friend const_iterator begin(const StringPool& pool);
194     friend const_iterator end(const StringPool& pool);
195 
196     static bool flatten(BigBuffer* out, const StringPool& pool, bool utf8);
197 
198     Ref makeRefImpl(const StringPiece16& str, const Context& context, bool unique);
199 
200     std::vector<std::unique_ptr<Entry>> mStrings;
201     std::vector<std::unique_ptr<StyleEntry>> mStyles;
202     std::multimap<StringPiece16, Entry*> mIndexedStrings;
203 };
204 
205 //
206 // Inline implementation
207 //
208 
size()209 inline size_t StringPool::size() const {
210     return mStrings.size();
211 }
212 
begin(const StringPool & pool)213 inline StringPool::const_iterator begin(const StringPool& pool) {
214     return pool.mStrings.begin();
215 }
216 
end(const StringPool & pool)217 inline StringPool::const_iterator end(const StringPool& pool) {
218     return pool.mStrings.end();
219 }
220 
221 } // namespace aapt
222 
223 #endif // AAPT_STRING_POOL_H
224