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 31 namespace aapt { 32 33 /** 34 * The various types of resource types available. Corresponds 35 * to the 'type' in package:type/entry. 36 */ 37 enum 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 63 StringPiece16 toString(ResourceType type); 64 65 /** 66 * Returns a pointer to a valid ResourceType, or nullptr if 67 * the string was invalid. 68 */ 69 const ResourceType* parseResourceType(const StringPiece16& str); 70 71 /** 72 * A resource's name. This can uniquely identify 73 * a resource in the ResourceTable. 74 */ 75 struct 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 */ 93 struct 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 */ 122 struct 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 136 struct SourcedResourceName { 137 ResourceName name; 138 size_t line; 139 }; 140 141 struct 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 */ 158 struct ResourceKey { 159 ResourceName name; 160 ConfigDescription config; 161 }; 162 163 bool 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 */ 169 struct 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 183 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b); 184 185 // 186 // ResourceId implementation. 187 // 188 189 inline ResourceId::ResourceId() : id(0) { 190 } 191 192 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) { 193 } 194 195 inline ResourceId::ResourceId(uint32_t resId) : id(resId) { 196 } 197 198 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e) : id((p << 24) | (t << 16) | e) { 199 } 200 201 inline bool ResourceId::isValid() const { 202 return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0; 203 } 204 205 inline uint8_t ResourceId::packageId() const { 206 return static_cast<uint8_t>(id >> 24); 207 } 208 209 inline uint8_t ResourceId::typeId() const { 210 return static_cast<uint8_t>(id >> 16); 211 } 212 213 inline uint16_t ResourceId::entryId() const { 214 return static_cast<uint16_t>(id); 215 } 216 217 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) { 218 return lhs.id < rhs.id; 219 } 220 221 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) { 222 return lhs.id > rhs.id; 223 } 224 225 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) { 226 return lhs.id == rhs.id; 227 } 228 229 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) { 230 return lhs.id != rhs.id; 231 } 232 233 inline ::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 247 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) { 248 return out << toString(val); 249 } 250 251 // 252 // ResourceName implementation. 253 // 254 255 inline ResourceName::ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e) : 256 package(p.toString()), type(t), entry(e.toString()) { 257 } 258 259 inline bool ResourceName::isValid() const { 260 return !package.empty() && !entry.empty(); 261 } 262 263 inline 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 268 inline 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 273 inline 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 278 inline 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 286 inline ::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 298 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) : 299 package(rhs.package), type(rhs.type), entry(rhs.entry) { 300 } 301 302 inline ResourceNameRef::ResourceNameRef(const StringPiece16& p, ResourceType t, 303 const StringPiece16& e) : 304 package(p), type(t), entry(e) { 305 } 306 307 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { 308 package = rhs.package; 309 type = rhs.type; 310 entry = rhs.entry; 311 return *this; 312 } 313 314 inline ResourceName ResourceNameRef::toResourceName() const { 315 return { package.toString(), type, entry.toString() }; 316 } 317 318 inline bool ResourceNameRef::isValid() const { 319 return !package.empty() && !entry.empty(); 320 } 321 322 inline 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 327 inline 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 332 inline 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 337 inline ::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 344 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) { 345 return ResourceNameRef(lhs) < b; 346 } 347 348 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) { 349 return ResourceNameRef(lhs) != rhs; 350 } 351 352 inline 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