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 "StringPiece.h"
     21 
     22 #include <iomanip>
     23 #include <limits>
     24 #include <string>
     25 #include <tuple>
     26 
     27 namespace aapt {
     28 
     29 /**
     30  * The various types of resource types available. Corresponds
     31  * to the 'type' in package:type/entry.
     32  */
     33 enum class ResourceType {
     34     kAnim,
     35     kAnimator,
     36     kArray,
     37     kAttr,
     38     kAttrPrivate,
     39     kBool,
     40     kColor,
     41     kDimen,
     42     kDrawable,
     43     kFraction,
     44     kId,
     45     kInteger,
     46     kIntegerArray,
     47     kInterpolator,
     48     kLayout,
     49     kMenu,
     50     kMipmap,
     51     kPlurals,
     52     kRaw,
     53     kString,
     54     kStyle,
     55     kStyleable,
     56     kTransition,
     57     kXml,
     58 };
     59 
     60 StringPiece16 toString(ResourceType type);
     61 
     62 /**
     63  * Returns a pointer to a valid ResourceType, or nullptr if
     64  * the string was invalid.
     65  */
     66 const ResourceType* parseResourceType(const StringPiece16& str);
     67 
     68 /**
     69  * A resource's name. This can uniquely identify
     70  * a resource in the ResourceTable.
     71  */
     72 struct ResourceName {
     73     std::u16string package;
     74     ResourceType type;
     75     std::u16string entry;
     76 
     77     bool isValid() const;
     78     bool operator<(const ResourceName& rhs) const;
     79     bool operator==(const ResourceName& rhs) const;
     80     bool operator!=(const ResourceName& rhs) const;
     81 };
     82 
     83 /**
     84  * Same as ResourceName, but uses StringPieces instead.
     85  * Use this if you need to avoid copying and know that
     86  * the lifetime of this object is shorter than that
     87  * of the original string.
     88  */
     89 struct ResourceNameRef {
     90     StringPiece16 package;
     91     ResourceType type;
     92     StringPiece16 entry;
     93 
     94     ResourceNameRef() = default;
     95     ResourceNameRef(const ResourceNameRef&) = default;
     96     ResourceNameRef(ResourceNameRef&&) = default;
     97     ResourceNameRef(const ResourceName& rhs);
     98     ResourceNameRef(const StringPiece16& p, ResourceType t, const StringPiece16& e);
     99     ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
    100     ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
    101     ResourceNameRef& operator=(const ResourceName& rhs);
    102 
    103     ResourceName toResourceName() const;
    104     bool isValid() const;
    105 
    106     bool operator<(const ResourceNameRef& rhs) const;
    107     bool operator==(const ResourceNameRef& rhs) const;
    108     bool operator!=(const ResourceNameRef& rhs) const;
    109 };
    110 
    111 /**
    112  * A binary identifier representing a resource. Internally it
    113  * is a 32bit integer split as follows:
    114  *
    115  * 0xPPTTEEEE
    116  *
    117  * PP: 8 bit package identifier. 0x01 is reserved for system
    118  *     and 0x7f is reserved for the running app.
    119  * TT: 8 bit type identifier. 0x00 is invalid.
    120  * EEEE: 16 bit entry identifier.
    121  */
    122 struct ResourceId {
    123     uint32_t id;
    124 
    125     ResourceId();
    126     ResourceId(const ResourceId& rhs);
    127     ResourceId(uint32_t resId);
    128     ResourceId(size_t p, size_t t, size_t e);
    129 
    130     bool isValid() const;
    131     uint8_t packageId() const;
    132     uint8_t typeId() const;
    133     uint16_t entryId() const;
    134     bool operator<(const ResourceId& rhs) const;
    135     bool operator==(const ResourceId& rhs) const;
    136 };
    137 
    138 //
    139 // ResourceId implementation.
    140 //
    141 
    142 inline ResourceId::ResourceId() : id(0) {
    143 }
    144 
    145 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {
    146 }
    147 
    148 inline ResourceId::ResourceId(uint32_t resId) : id(resId) {
    149 }
    150 
    151 inline ResourceId::ResourceId(size_t p, size_t t, size_t e) : id(0) {
    152     if (p > std::numeric_limits<uint8_t>::max() ||
    153             t > std::numeric_limits<uint8_t>::max() ||
    154             e > std::numeric_limits<uint16_t>::max()) {
    155         // This will leave the ResourceId in an invalid state.
    156         return;
    157     }
    158 
    159     id = (static_cast<uint8_t>(p) << 24) |
    160          (static_cast<uint8_t>(t) << 16) |
    161          static_cast<uint16_t>(e);
    162 }
    163 
    164 inline bool ResourceId::isValid() const {
    165     return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
    166 }
    167 
    168 inline uint8_t ResourceId::packageId() const {
    169     return static_cast<uint8_t>(id >> 24);
    170 }
    171 
    172 inline uint8_t ResourceId::typeId() const {
    173     return static_cast<uint8_t>(id >> 16);
    174 }
    175 
    176 inline uint16_t ResourceId::entryId() const {
    177     return static_cast<uint16_t>(id);
    178 }
    179 
    180 inline bool ResourceId::operator<(const ResourceId& rhs) const {
    181     return id < rhs.id;
    182 }
    183 
    184 inline bool ResourceId::operator==(const ResourceId& rhs) const {
    185     return id == rhs.id;
    186 }
    187 
    188 inline ::std::ostream& operator<<(::std::ostream& out,
    189         const ResourceId& resId) {
    190     std::ios_base::fmtflags oldFlags = out.flags();
    191     char oldFill = out.fill();
    192     out << "0x" << std::internal << std::setfill('0') << std::setw(8)
    193         << std::hex << resId.id;
    194     out.flags(oldFlags);
    195     out.fill(oldFill);
    196     return out;
    197 }
    198 
    199 //
    200 // ResourceType implementation.
    201 //
    202 
    203 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) {
    204     return out << toString(val);
    205 }
    206 
    207 //
    208 // ResourceName implementation.
    209 //
    210 
    211 inline bool ResourceName::isValid() const {
    212     return !package.empty() && !entry.empty();
    213 }
    214 
    215 inline bool ResourceName::operator<(const ResourceName& rhs) const {
    216     return std::tie(package, type, entry)
    217             < std::tie(rhs.package, rhs.type, rhs.entry);
    218 }
    219 
    220 inline bool ResourceName::operator==(const ResourceName& rhs) const {
    221     return std::tie(package, type, entry)
    222             == std::tie(rhs.package, rhs.type, rhs.entry);
    223 }
    224 
    225 inline bool ResourceName::operator!=(const ResourceName& rhs) const {
    226     return std::tie(package, type, entry)
    227             != std::tie(rhs.package, rhs.type, rhs.entry);
    228 }
    229 
    230 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) {
    231     if (!name.package.empty()) {
    232         out << name.package << ":";
    233     }
    234     return out << name.type << "/" << name.entry;
    235 }
    236 
    237 
    238 //
    239 // ResourceNameRef implementation.
    240 //
    241 
    242 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) :
    243         package(rhs.package), type(rhs.type), entry(rhs.entry) {
    244 }
    245 
    246 inline ResourceNameRef::ResourceNameRef(const StringPiece16& p, ResourceType t,
    247                                         const StringPiece16& e) :
    248         package(p), type(t), entry(e) {
    249 }
    250 
    251 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
    252     package = rhs.package;
    253     type = rhs.type;
    254     entry = rhs.entry;
    255     return *this;
    256 }
    257 
    258 inline ResourceName ResourceNameRef::toResourceName() const {
    259     return { package.toString(), type, entry.toString() };
    260 }
    261 
    262 inline bool ResourceNameRef::isValid() const {
    263     return !package.empty() && !entry.empty();
    264 }
    265 
    266 inline bool ResourceNameRef::operator<(const ResourceNameRef& rhs) const {
    267     return std::tie(package, type, entry)
    268             < std::tie(rhs.package, rhs.type, rhs.entry);
    269 }
    270 
    271 inline bool ResourceNameRef::operator==(const ResourceNameRef& rhs) const {
    272     return std::tie(package, type, entry)
    273             == std::tie(rhs.package, rhs.type, rhs.entry);
    274 }
    275 
    276 inline bool ResourceNameRef::operator!=(const ResourceNameRef& rhs) const {
    277     return std::tie(package, type, entry)
    278             != std::tie(rhs.package, rhs.type, rhs.entry);
    279 }
    280 
    281 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) {
    282     if (!name.package.empty()) {
    283         out << name.package << ":";
    284     }
    285     return out << name.type << "/" << name.entry;
    286 }
    287 
    288 } // namespace aapt
    289 
    290 #endif // AAPT_RESOURCE_H
    291