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 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;
    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 
    203 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
    204 
    205 //
    206 // ResourceId implementation.
    207 //
    208 
    209 inline ResourceId::ResourceId() : id(0) {}
    210 
    211 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
    212 
    213 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
    214 
    215 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
    216     : id((p << 24) | (t << 16) | e) {}
    217 
    218 inline bool ResourceId::is_valid() const {
    219   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
    220 }
    221 
    222 inline bool ResourceId::is_valid_dynamic() const { return (id & 0x00ff0000u) != 0; }
    223 
    224 inline uint8_t ResourceId::package_id() const {
    225   return static_cast<uint8_t>(id >> 24);
    226 }
    227 
    228 inline uint8_t ResourceId::type_id() const {
    229   return static_cast<uint8_t>(id >> 16);
    230 }
    231 
    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 
    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 
    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 
    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 
    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 
    326 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
    327     : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
    328 
    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 
    340 inline ResourceName ResourceNameRef::ToResourceName() const {
    341   return ResourceName(package, type, entry);
    342 }
    343 
    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