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