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/ConfigDescription.h" 28 #include "androidfw/StringPiece.h" 29 #include "utils/JenkinsHash.h" 30 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 70 // Not a parsed type. It is only used when loading resource tables that may have modified type 71 // names 72 kUnknown, 73 74 kXml, 75 }; 76 77 android::StringPiece to_string(ResourceType type); 78 79 /** 80 * Returns a pointer to a valid ResourceType, or nullptr if the string was invalid. 81 */ 82 const ResourceType* ParseResourceType(const android::StringPiece& str); 83 84 /** 85 * A resource's name. This can uniquely identify 86 * a resource in the ResourceTable. 87 */ 88 struct ResourceName { 89 std::string package; 90 ResourceType type = ResourceType::kRaw; 91 std::string entry; 92 93 ResourceName() = default; 94 ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); 95 96 int compare(const ResourceName& other) const; 97 98 bool is_valid() const; 99 std::string to_string() const; 100 }; 101 102 /** 103 * Same as ResourceName, but uses StringPieces instead. 104 * Use this if you need to avoid copying and know that 105 * the lifetime of this object is shorter than that 106 * of the original string. 107 */ 108 struct ResourceNameRef { 109 android::StringPiece package; 110 ResourceType type = ResourceType::kRaw; 111 android::StringPiece entry; 112 113 ResourceNameRef() = default; 114 ResourceNameRef(const ResourceNameRef&) = default; 115 ResourceNameRef(ResourceNameRef&&) = default; 116 ResourceNameRef(const ResourceName& rhs); // NOLINT(google-explicit-constructor) 117 ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); 118 ResourceNameRef& operator=(const ResourceNameRef& rhs) = default; 119 ResourceNameRef& operator=(ResourceNameRef&& rhs) = default; 120 ResourceNameRef& operator=(const ResourceName& rhs); 121 122 bool is_valid() const; 123 124 ResourceName ToResourceName() const; 125 std::string to_string() const; 126 }; 127 128 constexpr const uint8_t kAppPackageId = 0x7fu; 129 constexpr const uint8_t kFrameworkPackageId = 0x01u; 130 131 /** 132 * A binary identifier representing a resource. Internally it 133 * is a 32bit integer split as follows: 134 * 135 * 0xPPTTEEEE 136 * 137 * PP: 8 bit package identifier. 0x01 is reserved for system 138 * and 0x7f is reserved for the running app. 139 * TT: 8 bit type identifier. 0x00 is invalid. 140 * EEEE: 16 bit entry identifier. 141 */ 142 struct ResourceId { 143 uint32_t id; 144 145 ResourceId(); 146 ResourceId(const ResourceId& rhs); 147 ResourceId(uint32_t res_id); // NOLINT(google-explicit-constructor) 148 ResourceId(uint8_t p, uint8_t t, uint16_t e); 149 150 bool is_valid() const; 151 152 // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0). 153 bool is_valid_dynamic() const; 154 155 uint8_t package_id() const; 156 uint8_t type_id() const; 157 uint16_t entry_id() const; 158 159 std::string to_string() const; 160 }; 161 162 struct SourcedResourceName { 163 ResourceName name; 164 size_t line; 165 }; 166 167 struct ResourceFile { 168 enum class Type { 169 kUnknown, 170 kPng, 171 kBinaryXml, 172 kProtoXml, 173 }; 174 175 // Name 176 ResourceName name; 177 178 // Configuration 179 android::ConfigDescription config; 180 181 // Type 182 Type type; 183 184 // Source 185 Source source; 186 187 // Exported symbols 188 std::vector<SourcedResourceName> exported_symbols; 189 }; 190 191 /** 192 * Useful struct used as a key to represent a unique resource in associative 193 * containers. 194 */ 195 struct ResourceKey { 196 ResourceName name; 197 android::ConfigDescription config; 198 }; 199 200 bool operator<(const ResourceKey& a, const ResourceKey& b); 201 202 /** 203 * Useful struct used as a key to represent a unique resource in associative 204 * containers. 205 * Holds a reference to the name, so that name better live longer than this key! 206 */ 207 struct ResourceKeyRef { 208 ResourceNameRef name; 209 android::ConfigDescription config; 210 211 ResourceKeyRef() = default; 212 ResourceKeyRef(const ResourceNameRef& n, const android::ConfigDescription& c) 213 : name(n), config(c) {} 214 215 /** 216 * Prevent taking a reference to a temporary. This is bad. 217 */ 218 ResourceKeyRef(ResourceName&& n, const android::ConfigDescription& c) = delete; 219 }; 220 221 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b); 222 223 // 224 // ResourceId implementation. 225 // 226 227 inline ResourceId::ResourceId() : id(0) {} 228 229 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {} 230 231 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {} 232 233 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e) 234 : id((p << 24) | (t << 16) | e) {} 235 236 inline bool ResourceId::is_valid() const { 237 return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0; 238 } 239 240 inline bool ResourceId::is_valid_dynamic() const { 241 return (id & 0x00ff0000u) != 0; 242 } 243 244 inline uint8_t ResourceId::package_id() const { 245 return static_cast<uint8_t>(id >> 24); 246 } 247 248 inline uint8_t ResourceId::type_id() const { 249 return static_cast<uint8_t>(id >> 16); 250 } 251 252 inline uint16_t ResourceId::entry_id() const { 253 return static_cast<uint16_t>(id); 254 } 255 256 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) { 257 return lhs.id < rhs.id; 258 } 259 260 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) { 261 return lhs.id > rhs.id; 262 } 263 264 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) { 265 return lhs.id == rhs.id; 266 } 267 268 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) { 269 return lhs.id != rhs.id; 270 } 271 272 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& res_id) { 273 return out << res_id.to_string(); 274 } 275 276 // For generic code to call 'using std::to_string; to_string(T);'. 277 inline std::string to_string(const ResourceId& id) { 278 return id.to_string(); 279 } 280 281 // 282 // ResourceType implementation. 283 // 284 285 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) { 286 return out << to_string(val); 287 } 288 289 // 290 // ResourceName implementation. 291 // 292 293 inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t, 294 const android::StringPiece& e) 295 : package(p.to_string()), type(t), entry(e.to_string()) {} 296 297 inline int ResourceName::compare(const ResourceName& other) const { 298 int cmp = package.compare(other.package); 299 if (cmp != 0) return cmp; 300 cmp = static_cast<int>(type) - static_cast<int>(other.type); 301 if (cmp != 0) return cmp; 302 cmp = entry.compare(other.entry); 303 return cmp; 304 } 305 306 inline bool ResourceName::is_valid() const { 307 return !package.empty() && !entry.empty(); 308 } 309 310 inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) { 311 return std::tie(lhs.package, lhs.type, lhs.entry) < 312 std::tie(rhs.package, rhs.type, rhs.entry); 313 } 314 315 inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) { 316 return std::tie(lhs.package, lhs.type, lhs.entry) == 317 std::tie(rhs.package, rhs.type, rhs.entry); 318 } 319 320 inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) { 321 return std::tie(lhs.package, lhs.type, lhs.entry) != 322 std::tie(rhs.package, rhs.type, rhs.entry); 323 } 324 325 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) { 326 return out << name.to_string(); 327 } 328 329 // 330 // ResourceNameRef implementation. 331 // 332 333 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) 334 : package(rhs.package), type(rhs.type), entry(rhs.entry) {} 335 336 inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t, 337 const android::StringPiece& e) 338 : package(p), type(t), entry(e) {} 339 340 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { 341 package = rhs.package; 342 type = rhs.type; 343 entry = rhs.entry; 344 return *this; 345 } 346 347 inline ResourceName ResourceNameRef::ToResourceName() const { 348 return ResourceName(package, type, entry); 349 } 350 351 inline bool ResourceNameRef::is_valid() const { 352 return !package.empty() && !entry.empty(); 353 } 354 355 inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 356 return std::tie(lhs.package, lhs.type, lhs.entry) < 357 std::tie(rhs.package, rhs.type, rhs.entry); 358 } 359 360 inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 361 return std::tie(lhs.package, lhs.type, lhs.entry) == 362 std::tie(rhs.package, rhs.type, rhs.entry); 363 } 364 365 inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 366 return std::tie(lhs.package, lhs.type, lhs.entry) != 367 std::tie(rhs.package, rhs.type, rhs.entry); 368 } 369 370 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) { 371 return out << name.to_string(); 372 } 373 374 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) { 375 return ResourceNameRef(lhs) < b; 376 } 377 378 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) { 379 return ResourceNameRef(lhs) != rhs; 380 } 381 382 inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) { 383 return lhs.name == rhs.name && lhs.line == rhs.line; 384 } 385 386 } // namespace aapt 387 388 namespace std { 389 390 template <> 391 struct hash<aapt::ResourceName> { 392 size_t operator()(const aapt::ResourceName& name) const { 393 android::hash_t h = 0; 394 h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package))); 395 h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type)); 396 h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry))); 397 return static_cast<size_t>(h); 398 } 399 }; 400 401 template <> 402 struct hash<aapt::ResourceId> { 403 size_t operator()(const aapt::ResourceId& id) const { 404 return id.id; 405 } 406 }; 407 408 } // namespace std 409 410 #endif // AAPT_RESOURCE_H 411