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