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 "ConfigDescription.h" 21#include "Source.h" 22 23#include "util/StringPiece.h" 24 25#include <iomanip> 26#include <limits> 27#include <string> 28#include <tuple> 29#include <vector> 30 31namespace aapt { 32 33/** 34 * The various types of resource types available. Corresponds 35 * to the 'type' in package:type/entry. 36 */ 37enum class ResourceType { 38 kAnim, 39 kAnimator, 40 kArray, 41 kAttr, 42 kAttrPrivate, 43 kBool, 44 kColor, 45 kDimen, 46 kDrawable, 47 kFraction, 48 kId, 49 kInteger, 50 kInterpolator, 51 kLayout, 52 kMenu, 53 kMipmap, 54 kPlurals, 55 kRaw, 56 kString, 57 kStyle, 58 kStyleable, 59 kTransition, 60 kXml, 61}; 62 63StringPiece16 toString(ResourceType type); 64 65/** 66 * Returns a pointer to a valid ResourceType, or nullptr if 67 * the string was invalid. 68 */ 69const ResourceType* parseResourceType(const StringPiece16& str); 70 71/** 72 * A resource's name. This can uniquely identify 73 * a resource in the ResourceTable. 74 */ 75struct ResourceName { 76 std::u16string package; 77 ResourceType type; 78 std::u16string entry; 79 80 ResourceName() : type(ResourceType::kRaw) {} 81 ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e); 82 83 bool isValid() const; 84 std::u16string toString() const; 85}; 86 87/** 88 * Same as ResourceName, but uses StringPieces instead. 89 * Use this if you need to avoid copying and know that 90 * the lifetime of this object is shorter than that 91 * of the original string. 92 */ 93struct ResourceNameRef { 94 StringPiece16 package; 95 ResourceType type; 96 StringPiece16 entry; 97 98 ResourceNameRef() = default; 99 ResourceNameRef(const ResourceNameRef&) = default; 100 ResourceNameRef(ResourceNameRef&&) = default; 101 ResourceNameRef(const ResourceName& rhs); 102 ResourceNameRef(const StringPiece16& p, ResourceType t, const StringPiece16& e); 103 ResourceNameRef& operator=(const ResourceNameRef& rhs) = default; 104 ResourceNameRef& operator=(ResourceNameRef&& rhs) = default; 105 ResourceNameRef& operator=(const ResourceName& rhs); 106 107 ResourceName toResourceName() const; 108 bool isValid() 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 */ 122struct ResourceId { 123 uint32_t id; 124 125 ResourceId(); 126 ResourceId(const ResourceId& rhs); 127 ResourceId(uint32_t resId); 128 ResourceId(uint8_t p, uint8_t t, uint16_t e); 129 130 bool isValid() const; 131 uint8_t packageId() const; 132 uint8_t typeId() const; 133 uint16_t entryId() const; 134}; 135 136struct SourcedResourceName { 137 ResourceName name; 138 size_t line; 139}; 140 141struct ResourceFile { 142 // Name 143 ResourceName name; 144 145 // Configuration 146 ConfigDescription config; 147 148 // Source 149 Source source; 150 151 // Exported symbols 152 std::vector<SourcedResourceName> exportedSymbols; 153}; 154 155/** 156 * Useful struct used as a key to represent a unique resource in associative containers. 157 */ 158struct ResourceKey { 159 ResourceName name; 160 ConfigDescription config; 161}; 162 163bool operator<(const ResourceKey& a, const ResourceKey& b); 164 165/** 166 * Useful struct used as a key to represent a unique resource in associative containers. 167 * Holds a reference to the name, so that name better live longer than this key! 168 */ 169struct ResourceKeyRef { 170 ResourceNameRef name; 171 ConfigDescription config; 172 173 ResourceKeyRef() = default; 174 ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c) : name(n), config(c) { 175 } 176 177 /** 178 * Prevent taking a reference to a temporary. This is bad. 179 */ 180 ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete; 181}; 182 183bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b); 184 185// 186// ResourceId implementation. 187// 188 189inline ResourceId::ResourceId() : id(0) { 190} 191 192inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) { 193} 194 195inline ResourceId::ResourceId(uint32_t resId) : id(resId) { 196} 197 198inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e) : id((p << 24) | (t << 16) | e) { 199} 200 201inline bool ResourceId::isValid() const { 202 return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0; 203} 204 205inline uint8_t ResourceId::packageId() const { 206 return static_cast<uint8_t>(id >> 24); 207} 208 209inline uint8_t ResourceId::typeId() const { 210 return static_cast<uint8_t>(id >> 16); 211} 212 213inline uint16_t ResourceId::entryId() const { 214 return static_cast<uint16_t>(id); 215} 216 217inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) { 218 return lhs.id < rhs.id; 219} 220 221inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) { 222 return lhs.id > rhs.id; 223} 224 225inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) { 226 return lhs.id == rhs.id; 227} 228 229inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) { 230 return lhs.id != rhs.id; 231} 232 233inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& resId) { 234 std::ios_base::fmtflags oldFlags = out.flags(); 235 char oldFill = out.fill(); 236 out << "0x" << std::internal << std::setfill('0') << std::setw(8) 237 << std::hex << resId.id; 238 out.flags(oldFlags); 239 out.fill(oldFill); 240 return out; 241} 242 243// 244// ResourceType implementation. 245// 246 247inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) { 248 return out << toString(val); 249} 250 251// 252// ResourceName implementation. 253// 254 255inline ResourceName::ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e) : 256 package(p.toString()), type(t), entry(e.toString()) { 257} 258 259inline bool ResourceName::isValid() const { 260 return !package.empty() && !entry.empty(); 261} 262 263inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) { 264 return std::tie(lhs.package, lhs.type, lhs.entry) 265 < std::tie(rhs.package, rhs.type, rhs.entry); 266} 267 268inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) { 269 return std::tie(lhs.package, lhs.type, lhs.entry) 270 == std::tie(rhs.package, rhs.type, rhs.entry); 271} 272 273inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) { 274 return std::tie(lhs.package, lhs.type, lhs.entry) 275 != std::tie(rhs.package, rhs.type, rhs.entry); 276} 277 278inline std::u16string ResourceName::toString() const { 279 std::u16string result; 280 if (!package.empty()) { 281 result = package + u":"; 282 } 283 return result + aapt::toString(type).toString() + u"/" + entry; 284} 285 286inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) { 287 if (!name.package.empty()) { 288 out << name.package << ":"; 289 } 290 return out << name.type << "/" << name.entry; 291} 292 293 294// 295// ResourceNameRef implementation. 296// 297 298inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) : 299 package(rhs.package), type(rhs.type), entry(rhs.entry) { 300} 301 302inline ResourceNameRef::ResourceNameRef(const StringPiece16& p, ResourceType t, 303 const StringPiece16& e) : 304 package(p), type(t), entry(e) { 305} 306 307inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { 308 package = rhs.package; 309 type = rhs.type; 310 entry = rhs.entry; 311 return *this; 312} 313 314inline ResourceName ResourceNameRef::toResourceName() const { 315 return { package.toString(), type, entry.toString() }; 316} 317 318inline bool ResourceNameRef::isValid() const { 319 return !package.empty() && !entry.empty(); 320} 321 322inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 323 return std::tie(lhs.package, lhs.type, lhs.entry) 324 < std::tie(rhs.package, rhs.type, rhs.entry); 325} 326 327inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 328 return std::tie(lhs.package, lhs.type, lhs.entry) 329 == std::tie(rhs.package, rhs.type, rhs.entry); 330} 331 332inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 333 return std::tie(lhs.package, lhs.type, lhs.entry) 334 != std::tie(rhs.package, rhs.type, rhs.entry); 335} 336 337inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) { 338 if (!name.package.empty()) { 339 out << name.package << ":"; 340 } 341 return out << name.type << "/" << name.entry; 342} 343 344inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) { 345 return ResourceNameRef(lhs) < b; 346} 347 348inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) { 349 return ResourceNameRef(lhs) != rhs; 350} 351 352inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) { 353 return lhs.name == rhs.name && lhs.line == rhs.line; 354} 355 356} // namespace aapt 357 358#endif // AAPT_RESOURCE_H 359