Resource.h revision 3b84124edcd05f8aa61357165cb4a7ffd0c2e9b9
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
33namespace aapt {
34
35/**
36 * The various types of resource types available. Corresponds
37 * to the 'type' in package:type/entry.
38 */
39enum 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
72android::StringPiece ToString(ResourceType type);
73
74/**
75 * Returns a pointer to a valid ResourceType, or nullptr if
76 * the string was invalid.
77 */
78const ResourceType* ParseResourceType(const android::StringPiece& str);
79
80/**
81 * A resource's name. This can uniquely identify
82 * a resource in the ResourceTable.
83 */
84struct 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 */
104struct 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
122constexpr const uint8_t kAppPackageId = 0x7fu;
123constexpr 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 */
136struct 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
154struct SourcedResourceName {
155  ResourceName name;
156  size_t line;
157};
158
159struct 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 */
177struct ResourceKey {
178  ResourceName name;
179  ConfigDescription config;
180};
181
182bool 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 */
189struct ResourceKeyRef {
190  ResourceNameRef name;
191  ConfigDescription config;
192
193  ResourceKeyRef() = default;
194  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
203bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
204
205//
206// ResourceId implementation.
207//
208
209inline ResourceId::ResourceId() : id(0) {}
210
211inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
212
213inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
214
215inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
216    : id((p << 24) | (t << 16) | e) {}
217
218inline bool ResourceId::is_valid() const {
219  return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
220}
221
222inline bool ResourceId::is_valid_dynamic() const { return (id & 0x00ff0000u) != 0; }
223
224inline uint8_t ResourceId::package_id() const {
225  return static_cast<uint8_t>(id >> 24);
226}
227
228inline uint8_t ResourceId::type_id() const {
229  return static_cast<uint8_t>(id >> 16);
230}
231
232inline uint16_t ResourceId::entry_id() const {
233  return static_cast<uint16_t>(id);
234}
235
236inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
237  return lhs.id < rhs.id;
238}
239
240inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
241  return lhs.id > rhs.id;
242}
243
244inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
245  return lhs.id == rhs.id;
246}
247
248inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
249  return lhs.id != rhs.id;
250}
251
252inline ::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
267inline ::std::ostream& operator<<(::std::ostream& out,
268                                  const ResourceType& val) {
269  return out << ToString(val);
270}
271
272//
273// ResourceName implementation.
274//
275
276inline 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
280inline 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
289inline bool ResourceName::is_valid() const {
290  return !package.empty() && !entry.empty();
291}
292
293inline 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
298inline 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
303inline 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
308inline ::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
316inline std::string ResourceName::ToString() const {
317  std::stringstream stream;
318  stream << *this;
319  return stream.str();
320}
321
322//
323// ResourceNameRef implementation.
324//
325
326inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
327    : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
328
329inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
330                                        const android::StringPiece& e)
331    : package(p), type(t), entry(e) {}
332
333inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
334  package = rhs.package;
335  type = rhs.type;
336  entry = rhs.entry;
337  return *this;
338}
339
340inline ResourceName ResourceNameRef::ToResourceName() const {
341  return ResourceName(package, type, entry);
342}
343
344inline bool ResourceNameRef::is_valid() const {
345  return !package.empty() && !entry.empty();
346}
347
348inline 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
353inline 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
358inline 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
363inline ::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
371inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
372  return ResourceNameRef(lhs) < b;
373}
374
375inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
376  return ResourceNameRef(lhs) != rhs;
377}
378
379inline 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
386namespace std {
387
388template <>
389struct 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
399template <>
400struct 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