Home | History | Annotate | Download | only in aapt2
      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 to_string(ResourceType type);
     73 
     74 /**
     75  * Returns a pointer to a valid ResourceType, or nullptr if 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 to_string() 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   bool is_valid() const;
    118 
    119   ResourceName ToResourceName() const;
    120   std::string to_string() const;
    121 };
    122 
    123 constexpr const uint8_t kAppPackageId = 0x7fu;
    124 constexpr const uint8_t kFrameworkPackageId = 0x01u;
    125 
    126 /**
    127  * A binary identifier representing a resource. Internally it
    128  * is a 32bit integer split as follows:
    129  *
    130  * 0xPPTTEEEE
    131  *
    132  * PP: 8 bit package identifier. 0x01 is reserved for system
    133  *     and 0x7f is reserved for the running app.
    134  * TT: 8 bit type identifier. 0x00 is invalid.
    135  * EEEE: 16 bit entry identifier.
    136  */
    137 struct ResourceId {
    138   uint32_t id;
    139 
    140   ResourceId();
    141   ResourceId(const ResourceId& rhs);
    142   ResourceId(uint32_t res_id);  // NOLINT(implicit)
    143   ResourceId(uint8_t p, uint8_t t, uint16_t e);
    144 
    145   bool is_valid() const;
    146 
    147   // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
    148   bool is_valid_dynamic() const;
    149 
    150   uint8_t package_id() const;
    151   uint8_t type_id() const;
    152   uint16_t entry_id() const;
    153 
    154   std::string to_string() const;
    155 };
    156 
    157 struct SourcedResourceName {
    158   ResourceName name;
    159   size_t line;
    160 };
    161 
    162 struct ResourceFile {
    163   enum class Type {
    164     kUnknown,
    165     kPng,
    166     kBinaryXml,
    167     kProtoXml,
    168   };
    169 
    170   // Name
    171   ResourceName name;
    172 
    173   // Configuration
    174   ConfigDescription config;
    175 
    176   // Type
    177   Type type;
    178 
    179   // Source
    180   Source source;
    181 
    182   // Exported symbols
    183   std::vector<SourcedResourceName> exported_symbols;
    184 };
    185 
    186 /**
    187  * Useful struct used as a key to represent a unique resource in associative
    188  * containers.
    189  */
    190 struct ResourceKey {
    191   ResourceName name;
    192   ConfigDescription config;
    193 };
    194 
    195 bool operator<(const ResourceKey& a, const ResourceKey& b);
    196 
    197 /**
    198  * Useful struct used as a key to represent a unique resource in associative
    199  * containers.
    200  * Holds a reference to the name, so that name better live longer than this key!
    201  */
    202 struct ResourceKeyRef {
    203   ResourceNameRef name;
    204   ConfigDescription config;
    205 
    206   ResourceKeyRef() = default;
    207   ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c)
    208       : name(n), config(c) {}
    209 
    210   /**
    211    * Prevent taking a reference to a temporary. This is bad.
    212    */
    213   ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete;
    214 };
    215 
    216 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
    217 
    218 //
    219 // ResourceId implementation.
    220 //
    221 
    222 inline ResourceId::ResourceId() : id(0) {}
    223 
    224 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
    225 
    226 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
    227 
    228 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
    229     : id((p << 24) | (t << 16) | e) {}
    230 
    231 inline bool ResourceId::is_valid() const {
    232   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
    233 }
    234 
    235 inline bool ResourceId::is_valid_dynamic() const {
    236   return (id & 0x00ff0000u) != 0;
    237 }
    238 
    239 inline uint8_t ResourceId::package_id() const {
    240   return static_cast<uint8_t>(id >> 24);
    241 }
    242 
    243 inline uint8_t ResourceId::type_id() const {
    244   return static_cast<uint8_t>(id >> 16);
    245 }
    246 
    247 inline uint16_t ResourceId::entry_id() const {
    248   return static_cast<uint16_t>(id);
    249 }
    250 
    251 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
    252   return lhs.id < rhs.id;
    253 }
    254 
    255 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
    256   return lhs.id > rhs.id;
    257 }
    258 
    259 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
    260   return lhs.id == rhs.id;
    261 }
    262 
    263 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
    264   return lhs.id != rhs.id;
    265 }
    266 
    267 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& res_id) {
    268   return out << res_id.to_string();
    269 }
    270 
    271 // For generic code to call 'using std::to_string; to_string(T);'.
    272 inline std::string to_string(const ResourceId& id) {
    273   return id.to_string();
    274 }
    275 
    276 //
    277 // ResourceType implementation.
    278 //
    279 
    280 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) {
    281   return out << to_string(val);
    282 }
    283 
    284 //
    285 // ResourceName implementation.
    286 //
    287 
    288 inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
    289                                   const android::StringPiece& e)
    290     : package(p.to_string()), type(t), entry(e.to_string()) {}
    291 
    292 inline int ResourceName::compare(const ResourceName& other) const {
    293   int cmp = package.compare(other.package);
    294   if (cmp != 0) return cmp;
    295   cmp = static_cast<int>(type) - static_cast<int>(other.type);
    296   if (cmp != 0) return cmp;
    297   cmp = entry.compare(other.entry);
    298   return cmp;
    299 }
    300 
    301 inline bool ResourceName::is_valid() const {
    302   return !package.empty() && !entry.empty();
    303 }
    304 
    305 inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
    306   return std::tie(lhs.package, lhs.type, lhs.entry) <
    307          std::tie(rhs.package, rhs.type, rhs.entry);
    308 }
    309 
    310 inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
    311   return std::tie(lhs.package, lhs.type, lhs.entry) ==
    312          std::tie(rhs.package, rhs.type, rhs.entry);
    313 }
    314 
    315 inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
    316   return std::tie(lhs.package, lhs.type, lhs.entry) !=
    317          std::tie(rhs.package, rhs.type, rhs.entry);
    318 }
    319 
    320 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) {
    321   return out << name.to_string();
    322 }
    323 
    324 //
    325 // ResourceNameRef implementation.
    326 //
    327 
    328 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
    329     : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
    330 
    331 inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
    332                                         const android::StringPiece& e)
    333     : package(p), type(t), entry(e) {}
    334 
    335 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
    336   package = rhs.package;
    337   type = rhs.type;
    338   entry = rhs.entry;
    339   return *this;
    340 }
    341 
    342 inline ResourceName ResourceNameRef::ToResourceName() const {
    343   return ResourceName(package, type, entry);
    344 }
    345 
    346 inline bool ResourceNameRef::is_valid() const {
    347   return !package.empty() && !entry.empty();
    348 }
    349 
    350 inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
    351   return std::tie(lhs.package, lhs.type, lhs.entry) <
    352          std::tie(rhs.package, rhs.type, rhs.entry);
    353 }
    354 
    355 inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
    356   return std::tie(lhs.package, lhs.type, lhs.entry) ==
    357          std::tie(rhs.package, rhs.type, rhs.entry);
    358 }
    359 
    360 inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
    361   return std::tie(lhs.package, lhs.type, lhs.entry) !=
    362          std::tie(rhs.package, rhs.type, rhs.entry);
    363 }
    364 
    365 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) {
    366   return out << name.to_string();
    367 }
    368 
    369 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
    370   return ResourceNameRef(lhs) < b;
    371 }
    372 
    373 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
    374   return ResourceNameRef(lhs) != rhs;
    375 }
    376 
    377 inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) {
    378   return lhs.name == rhs.name && lhs.line == rhs.line;
    379 }
    380 
    381 }  // namespace aapt
    382 
    383 namespace std {
    384 
    385 template <>
    386 struct hash<aapt::ResourceName> {
    387   size_t operator()(const aapt::ResourceName& name) const {
    388     android::hash_t h = 0;
    389     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package)));
    390     h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
    391     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry)));
    392     return static_cast<size_t>(h);
    393   }
    394 };
    395 
    396 template <>
    397 struct hash<aapt::ResourceId> {
    398   size_t operator()(const aapt::ResourceId& id) const {
    399     return id.id;
    400   }
    401 };
    402 
    403 }  // namespace std
    404 
    405 #endif  // AAPT_RESOURCE_H
    406