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