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_RESOURCE_TABLE_H
18 #define AAPT_RESOURCE_TABLE_H
19 
20 #include "ConfigDescription.h"
21 #include "Resource.h"
22 #include "ResourceValues.h"
23 #include "Source.h"
24 #include "StringPool.h"
25 
26 #include <memory>
27 #include <string>
28 #include <tuple>
29 #include <vector>
30 
31 namespace aapt {
32 
33 /**
34  * The Public status of a resource.
35  */
36 struct Public {
37     bool isPublic = false;
38     SourceLine source;
39     std::u16string comment;
40 };
41 
42 /**
43  * The resource value for a specific configuration.
44  */
45 struct ResourceConfigValue {
46     ConfigDescription config;
47     SourceLine source;
48     std::u16string comment;
49     std::unique_ptr<Value> value;
50 };
51 
52 /**
53  * Represents a resource entry, which may have
54  * varying values for each defined configuration.
55  */
56 struct ResourceEntry {
57     enum {
58         kUnsetEntryId = 0xffffffffu
59     };
60 
61     /**
62      * The name of the resource. Immutable, as
63      * this determines the order of this resource
64      * when doing lookups.
65      */
66     const std::u16string name;
67 
68     /**
69      * The entry ID for this resource.
70      */
71     size_t entryId;
72 
73     /**
74      * Whether this resource is public (and must maintain the same
75      * entry ID across builds).
76      */
77     Public publicStatus;
78 
79     /**
80      * The resource's values for each configuration.
81      */
82     std::vector<ResourceConfigValue> values;
83 
84     inline ResourceEntry(const StringPiece16& _name);
85     inline ResourceEntry(const ResourceEntry* rhs);
86 };
87 
88 /**
89  * Represents a resource type, which holds entries defined
90  * for this type.
91  */
92 struct ResourceTableType {
93     enum {
94         kUnsetTypeId = 0xffffffffu
95     };
96 
97     /**
98      * The logical type of resource (string, drawable, layout, etc.).
99      */
100     const ResourceType type;
101 
102     /**
103      * The type ID for this resource.
104      */
105     size_t typeId;
106 
107     /**
108      * Whether this type is public (and must maintain the same
109      * type ID across builds).
110      */
111     Public publicStatus;
112 
113     /**
114      * List of resources for this type.
115      */
116     std::vector<std::unique_ptr<ResourceEntry>> entries;
117 
118     ResourceTableType(const ResourceType _type);
119     ResourceTableType(const ResourceTableType* rhs);
120 };
121 
122 /**
123  * The container and index for all resources defined for an app. This gets
124  * flattened into a binary resource table (resources.arsc).
125  */
126 class ResourceTable {
127 public:
128     using iterator = std::vector<std::unique_ptr<ResourceTableType>>::iterator;
129     using const_iterator = std::vector<std::unique_ptr<ResourceTableType>>::const_iterator;
130 
131     enum {
132         kUnsetPackageId = 0xffffffff
133     };
134 
135     ResourceTable();
136 
137     size_t getPackageId() const;
138     void setPackageId(size_t packageId);
139 
140     const std::u16string& getPackage() const;
141     void setPackage(const StringPiece16& package);
142 
143     bool addResource(const ResourceNameRef& name, const ConfigDescription& config,
144                      const SourceLine& source, std::unique_ptr<Value> value);
145 
146     /**
147      * Same as addResource, but doesn't verify the validity of the name. This is used
148      * when loading resources from an existing binary resource table that may have mangled
149      * names.
150      */
151     bool addResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
152                                  const SourceLine& source, std::unique_ptr<Value> value);
153 
154     bool addResource(const ResourceNameRef& name, const ResourceId resId,
155                      const ConfigDescription& config, const SourceLine& source,
156                      std::unique_ptr<Value> value);
157 
158     bool markPublic(const ResourceNameRef& name, const ResourceId resId, const SourceLine& source);
159     bool markPublicAllowMangled(const ResourceNameRef& name, const ResourceId resId,
160                                 const SourceLine& source);
161 
162     /*
163      * Merges the resources from `other` into this table, mangling the names of the resources
164      * if `other` has a different package name.
165      */
166     bool merge(ResourceTable&& other);
167 
168     /**
169      * Returns the string pool used by this ResourceTable.
170      * Values that reference strings should use this pool to create
171      * their strings.
172      */
173     StringPool& getValueStringPool();
174     const StringPool& getValueStringPool() const;
175 
176     std::tuple<const ResourceTableType*, const ResourceEntry*>
177     findResource(const ResourceNameRef& name) const;
178 
179     iterator begin();
180     iterator end();
181     const_iterator begin() const;
182     const_iterator end() const;
183 
184 private:
185     std::unique_ptr<ResourceTableType>& findOrCreateType(ResourceType type);
186     std::unique_ptr<ResourceEntry>& findOrCreateEntry(std::unique_ptr<ResourceTableType>& type,
187                                                       const StringPiece16& name);
188 
189     bool addResourceImpl(const ResourceNameRef& name, const ResourceId resId,
190                          const ConfigDescription& config, const SourceLine& source,
191                          std::unique_ptr<Value> value, const char16_t* validChars);
192     bool markPublicImpl(const ResourceNameRef& name, const ResourceId resId,
193                         const SourceLine& source, const char16_t* validChars);
194 
195     std::u16string mPackage;
196     size_t mPackageId;
197 
198     // StringPool must come before mTypes so that it is destroyed after.
199     // When StringPool references are destroyed (as they will be when mTypes
200     // is destroyed), they decrement a refCount, which would cause invalid
201     // memory access if the pool was already destroyed.
202     StringPool mValuePool;
203 
204     std::vector<std::unique_ptr<ResourceTableType>> mTypes;
205 };
206 
207 //
208 // ResourceEntry implementation.
209 //
210 
ResourceEntry(const StringPiece16 & _name)211 inline ResourceEntry::ResourceEntry(const StringPiece16& _name) :
212         name(_name.toString()), entryId(kUnsetEntryId) {
213 }
214 
ResourceEntry(const ResourceEntry * rhs)215 inline ResourceEntry::ResourceEntry(const ResourceEntry* rhs) :
216         name(rhs->name), entryId(rhs->entryId), publicStatus(rhs->publicStatus) {
217 }
218 
219 //
220 // ResourceTableType implementation.
221 //
222 
ResourceTableType(const ResourceType _type)223 inline ResourceTableType::ResourceTableType(const ResourceType _type) :
224         type(_type), typeId(kUnsetTypeId) {
225 }
226 
ResourceTableType(const ResourceTableType * rhs)227 inline ResourceTableType::ResourceTableType(const ResourceTableType* rhs) :
228         type(rhs->type), typeId(rhs->typeId), publicStatus(rhs->publicStatus) {
229 }
230 
231 //
232 // ResourceTable implementation.
233 //
234 
getValueStringPool()235 inline StringPool& ResourceTable::getValueStringPool() {
236     return mValuePool;
237 }
238 
getValueStringPool()239 inline const StringPool& ResourceTable::getValueStringPool() const {
240     return mValuePool;
241 }
242 
begin()243 inline ResourceTable::iterator ResourceTable::begin() {
244     return mTypes.begin();
245 }
246 
end()247 inline ResourceTable::iterator ResourceTable::end() {
248     return mTypes.end();
249 }
250 
begin()251 inline ResourceTable::const_iterator ResourceTable::begin() const {
252     return mTypes.begin();
253 }
254 
end()255 inline ResourceTable::const_iterator ResourceTable::end() const {
256     return mTypes.end();
257 }
258 
getPackage()259 inline const std::u16string& ResourceTable::getPackage() const {
260     return mPackage;
261 }
262 
getPackageId()263 inline size_t ResourceTable::getPackageId() const {
264     return mPackageId;
265 }
266 
setPackage(const StringPiece16 & package)267 inline void ResourceTable::setPackage(const StringPiece16& package) {
268     mPackage = package.toString();
269 }
270 
setPackageId(size_t packageId)271 inline void ResourceTable::setPackageId(size_t packageId) {
272     mPackageId = packageId;
273 }
274 
275 } // namespace aapt
276 
277 #endif // AAPT_RESOURCE_TABLE_H
278