• 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_RESOURCE_H
18 #define AAPT_RESOURCE_H
19 
20 #include <iomanip>
21 #include <limits>
22 #include <sstream>
23 #include <string>
24 #include <tuple>
25 #include <vector>
26 
27 #include "androidfw/StringPiece.h"
28 #include "utils/JenkinsHash.h"
29 
30 #include "ConfigDescription.h"
31 #include "Source.h"
32 
33 namespace aapt {
34 
35 /**
36  * The various types of resource types available. Corresponds
37  * to the 'type' in package:type/entry.
38  */
39 enum class ResourceType {
40   kAnim,
41   kAnimator,
42   kArray,
43   kAttr,
44   kAttrPrivate,
45   kBool,
46   kColor,
47 
48   // Not really a type, but it shows up in some CTS tests and
49   // we need to continue respecting it.
50   kConfigVarying,
51 
52   kDimen,
53   kDrawable,
54   kFont,
55   kFraction,
56   kId,
57   kInteger,
58   kInterpolator,
59   kLayout,
60   kMenu,
61   kMipmap,
62   kNavigation,
63   kPlurals,
64   kRaw,
65   kString,
66   kStyle,
67   kStyleable,
68   kTransition,
69   kXml,
70 };
71 
72 android::StringPiece ToString(ResourceType type);
73 
74 /**
75  * Returns a pointer to a valid ResourceType, or nullptr if
76  * the string was invalid.
77  */
78 const ResourceType* ParseResourceType(const android::StringPiece& str);
79 
80 /**
81  * A resource's name. This can uniquely identify
82  * a resource in the ResourceTable.
83  */
84 struct ResourceName {
85   std::string package;
86   ResourceType type = ResourceType::kRaw;
87   std::string entry;
88 
89   ResourceName() = default;
90   ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
91 
92   int compare(const ResourceName& other) const;
93 
94   bool is_valid() const;
95   std::string ToString() const;
96 };
97 
98 /**
99  * Same as ResourceName, but uses StringPieces instead.
100  * Use this if you need to avoid copying and know that
101  * the lifetime of this object is shorter than that
102  * of the original string.
103  */
104 struct ResourceNameRef {
105   android::StringPiece package;
106   ResourceType type = ResourceType::kRaw;
107   android::StringPiece entry;
108 
109   ResourceNameRef() = default;
110   ResourceNameRef(const ResourceNameRef&) = default;
111   ResourceNameRef(ResourceNameRef&&) = default;
112   ResourceNameRef(const ResourceName& rhs);  // NOLINT(implicit)
113   ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
114   ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
115   ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
116   ResourceNameRef& operator=(const ResourceName& rhs);
117 
118   ResourceName ToResourceName() const;
119   bool is_valid() const;
120 };
121 
122 constexpr const uint8_t kAppPackageId = 0x7fu;
123 constexpr const uint8_t kFrameworkPackageId = 0x01u;
124 
125 /**
126  * A binary identifier representing a resource. Internally it
127  * is a 32bit integer split as follows:
128  *
129  * 0xPPTTEEEE
130  *
131  * PP: 8 bit package identifier. 0x01 is reserved for system
132  *     and 0x7f is reserved for the running app.
133  * TT: 8 bit type identifier. 0x00 is invalid.
134  * EEEE: 16 bit entry identifier.
135  */
136 struct ResourceId {
137   uint32_t id;
138 
139   ResourceId();
140   ResourceId(const ResourceId& rhs);
141   ResourceId(uint32_t res_id);  // NOLINT(implicit)
142   ResourceId(uint8_t p, uint8_t t, uint16_t e);
143 
144   bool is_valid() const;
145 
146   // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
147   bool is_valid_dynamic() const;
148 
149   uint8_t package_id() const;
150   uint8_t type_id() const;
151   uint16_t entry_id() const;
152 };
153 
154 struct SourcedResourceName {
155   ResourceName name;
156   size_t line;
157 };
158 
159 struct ResourceFile {
160   // Name
161   ResourceName name;
162 
163   // Configuration
164   ConfigDescription config;
165 
166   // Source
167   Source source;
168 
169   // Exported symbols
170   std::vector<SourcedResourceName> exported_symbols;
171 };
172 
173 /**
174  * Useful struct used as a key to represent a unique resource in associative
175  * containers.
176  */
177 struct ResourceKey {
178   ResourceName name;
179   ConfigDescription config;
180 };
181 
182 bool operator<(const ResourceKey& a, const ResourceKey& b);
183 
184 /**
185  * Useful struct used as a key to represent a unique resource in associative
186  * containers.
187  * Holds a reference to the name, so that name better live longer than this key!
188  */
189 struct ResourceKeyRef {
190   ResourceNameRef name;
191   ConfigDescription config;
192 
193   ResourceKeyRef() = default;
ResourceKeyRefResourceKeyRef194   ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c)
195       : name(n), config(c) {}
196 
197   /**
198    * Prevent taking a reference to a temporary. This is bad.
199    */
200   ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete;
201 };
202 
203 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
204 
205 //
206 // ResourceId implementation.
207 //
208 
ResourceId()209 inline ResourceId::ResourceId() : id(0) {}
210 
ResourceId(const ResourceId & rhs)211 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
212 
ResourceId(uint32_t res_id)213 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
214 
ResourceId(uint8_t p,uint8_t t,uint16_t e)215 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
216     : id((p << 24) | (t << 16) | e) {}
217 
is_valid()218 inline bool ResourceId::is_valid() const {
219   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
220 }
221 
is_valid_dynamic()222 inline bool ResourceId::is_valid_dynamic() const { return (id & 0x00ff0000u) != 0; }
223 
package_id()224 inline uint8_t ResourceId::package_id() const {
225   return static_cast<uint8_t>(id >> 24);
226 }
227 
type_id()228 inline uint8_t ResourceId::type_id() const {
229   return static_cast<uint8_t>(id >> 16);
230 }
231 
entry_id()232 inline uint16_t ResourceId::entry_id() const {
233   return static_cast<uint16_t>(id);
234 }
235 
236 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
237   return lhs.id < rhs.id;
238 }
239 
240 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
241   return lhs.id > rhs.id;
242 }
243 
244 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
245   return lhs.id == rhs.id;
246 }
247 
248 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
249   return lhs.id != rhs.id;
250 }
251 
252 inline ::std::ostream& operator<<(::std::ostream& out,
253                                   const ResourceId& res_id) {
254   std::ios_base::fmtflags old_flags = out.flags();
255   char old_fill = out.fill();
256   out << "0x" << std::internal << std::setfill('0') << std::setw(8) << std::hex
257       << res_id.id;
258   out.flags(old_flags);
259   out.fill(old_fill);
260   return out;
261 }
262 
263 //
264 // ResourceType implementation.
265 //
266 
267 inline ::std::ostream& operator<<(::std::ostream& out,
268                                   const ResourceType& val) {
269   return out << ToString(val);
270 }
271 
272 //
273 // ResourceName implementation.
274 //
275 
ResourceName(const android::StringPiece & p,ResourceType t,const android::StringPiece & e)276 inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
277                                   const android::StringPiece& e)
278     : package(p.to_string()), type(t), entry(e.to_string()) {}
279 
compare(const ResourceName & other)280 inline int ResourceName::compare(const ResourceName& other) const {
281   int cmp = package.compare(other.package);
282   if (cmp != 0) return cmp;
283   cmp = static_cast<int>(type) - static_cast<int>(other.type);
284   if (cmp != 0) return cmp;
285   cmp = entry.compare(other.entry);
286   return cmp;
287 }
288 
is_valid()289 inline bool ResourceName::is_valid() const {
290   return !package.empty() && !entry.empty();
291 }
292 
293 inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
294   return std::tie(lhs.package, lhs.type, lhs.entry) <
295          std::tie(rhs.package, rhs.type, rhs.entry);
296 }
297 
298 inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
299   return std::tie(lhs.package, lhs.type, lhs.entry) ==
300          std::tie(rhs.package, rhs.type, rhs.entry);
301 }
302 
303 inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
304   return std::tie(lhs.package, lhs.type, lhs.entry) !=
305          std::tie(rhs.package, rhs.type, rhs.entry);
306 }
307 
308 inline ::std::ostream& operator<<(::std::ostream& out,
309                                   const ResourceName& name) {
310   if (!name.package.empty()) {
311     out << name.package << ":";
312   }
313   return out << name.type << "/" << name.entry;
314 }
315 
ToString()316 inline std::string ResourceName::ToString() const {
317   std::stringstream stream;
318   stream << *this;
319   return stream.str();
320 }
321 
322 //
323 // ResourceNameRef implementation.
324 //
325 
ResourceNameRef(const ResourceName & rhs)326 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
327     : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
328 
ResourceNameRef(const android::StringPiece & p,ResourceType t,const android::StringPiece & e)329 inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
330                                         const android::StringPiece& e)
331     : package(p), type(t), entry(e) {}
332 
333 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
334   package = rhs.package;
335   type = rhs.type;
336   entry = rhs.entry;
337   return *this;
338 }
339 
ToResourceName()340 inline ResourceName ResourceNameRef::ToResourceName() const {
341   return ResourceName(package, type, entry);
342 }
343 
is_valid()344 inline bool ResourceNameRef::is_valid() const {
345   return !package.empty() && !entry.empty();
346 }
347 
348 inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
349   return std::tie(lhs.package, lhs.type, lhs.entry) <
350          std::tie(rhs.package, rhs.type, rhs.entry);
351 }
352 
353 inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
354   return std::tie(lhs.package, lhs.type, lhs.entry) ==
355          std::tie(rhs.package, rhs.type, rhs.entry);
356 }
357 
358 inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
359   return std::tie(lhs.package, lhs.type, lhs.entry) !=
360          std::tie(rhs.package, rhs.type, rhs.entry);
361 }
362 
363 inline ::std::ostream& operator<<(::std::ostream& out,
364                                   const ResourceNameRef& name) {
365   if (!name.package.empty()) {
366     out << name.package << ":";
367   }
368   return out << name.type << "/" << name.entry;
369 }
370 
371 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
372   return ResourceNameRef(lhs) < b;
373 }
374 
375 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
376   return ResourceNameRef(lhs) != rhs;
377 }
378 
379 inline bool operator==(const SourcedResourceName& lhs,
380                        const SourcedResourceName& rhs) {
381   return lhs.name == rhs.name && lhs.line == rhs.line;
382 }
383 
384 }  // namespace aapt
385 
386 namespace std {
387 
388 template <>
389 struct hash<aapt::ResourceName> {
390   size_t operator()(const aapt::ResourceName& name) const {
391     android::hash_t h = 0;
392     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package)));
393     h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
394     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry)));
395     return static_cast<size_t>(h);
396   }
397 };
398 
399 template <>
400 struct hash<aapt::ResourceId> {
401   size_t operator()(const aapt::ResourceId& id) const {
402     return id.id;
403   }
404 };
405 
406 }  // namespace std
407 
408 #endif  // AAPT_RESOURCE_H
409