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