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