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 kNavigation, 63 kPlurals, 64 kRaw, 65 kString, 66 kStyle, 67 kStyleable, 68 kTransition, 69 kXml, 70 }; 71 72 android::StringPiece to_string(ResourceType type); 73 74 /** 75 * Returns a pointer to a valid ResourceType, or nullptr if 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 to_string() 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 bool is_valid() const; 118 119 ResourceName ToResourceName() const; 120 std::string to_string() const; 121 }; 122 123 constexpr const uint8_t kAppPackageId = 0x7fu; 124 constexpr const uint8_t kFrameworkPackageId = 0x01u; 125 126 /** 127 * A binary identifier representing a resource. Internally it 128 * is a 32bit integer split as follows: 129 * 130 * 0xPPTTEEEE 131 * 132 * PP: 8 bit package identifier. 0x01 is reserved for system 133 * and 0x7f is reserved for the running app. 134 * TT: 8 bit type identifier. 0x00 is invalid. 135 * EEEE: 16 bit entry identifier. 136 */ 137 struct ResourceId { 138 uint32_t id; 139 140 ResourceId(); 141 ResourceId(const ResourceId& rhs); 142 ResourceId(uint32_t res_id); // NOLINT(implicit) 143 ResourceId(uint8_t p, uint8_t t, uint16_t e); 144 145 bool is_valid() const; 146 147 // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0). 148 bool is_valid_dynamic() const; 149 150 uint8_t package_id() const; 151 uint8_t type_id() const; 152 uint16_t entry_id() const; 153 154 std::string to_string() const; 155 }; 156 157 struct SourcedResourceName { 158 ResourceName name; 159 size_t line; 160 }; 161 162 struct ResourceFile { 163 enum class Type { 164 kUnknown, 165 kPng, 166 kBinaryXml, 167 kProtoXml, 168 }; 169 170 // Name 171 ResourceName name; 172 173 // Configuration 174 ConfigDescription config; 175 176 // Type 177 Type type; 178 179 // Source 180 Source source; 181 182 // Exported symbols 183 std::vector<SourcedResourceName> exported_symbols; 184 }; 185 186 /** 187 * Useful struct used as a key to represent a unique resource in associative 188 * containers. 189 */ 190 struct ResourceKey { 191 ResourceName name; 192 ConfigDescription config; 193 }; 194 195 bool operator<(const ResourceKey& a, const ResourceKey& b); 196 197 /** 198 * Useful struct used as a key to represent a unique resource in associative 199 * containers. 200 * Holds a reference to the name, so that name better live longer than this key! 201 */ 202 struct ResourceKeyRef { 203 ResourceNameRef name; 204 ConfigDescription config; 205 206 ResourceKeyRef() = default; 207 ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c) 208 : name(n), config(c) {} 209 210 /** 211 * Prevent taking a reference to a temporary. This is bad. 212 */ 213 ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete; 214 }; 215 216 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b); 217 218 // 219 // ResourceId implementation. 220 // 221 222 inline ResourceId::ResourceId() : id(0) {} 223 224 inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {} 225 226 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {} 227 228 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e) 229 : id((p << 24) | (t << 16) | e) {} 230 231 inline bool ResourceId::is_valid() const { 232 return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0; 233 } 234 235 inline bool ResourceId::is_valid_dynamic() const { 236 return (id & 0x00ff0000u) != 0; 237 } 238 239 inline uint8_t ResourceId::package_id() const { 240 return static_cast<uint8_t>(id >> 24); 241 } 242 243 inline uint8_t ResourceId::type_id() const { 244 return static_cast<uint8_t>(id >> 16); 245 } 246 247 inline uint16_t ResourceId::entry_id() const { 248 return static_cast<uint16_t>(id); 249 } 250 251 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) { 252 return lhs.id < rhs.id; 253 } 254 255 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) { 256 return lhs.id > rhs.id; 257 } 258 259 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) { 260 return lhs.id == rhs.id; 261 } 262 263 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) { 264 return lhs.id != rhs.id; 265 } 266 267 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& res_id) { 268 return out << res_id.to_string(); 269 } 270 271 // For generic code to call 'using std::to_string; to_string(T);'. 272 inline std::string to_string(const ResourceId& id) { 273 return id.to_string(); 274 } 275 276 // 277 // ResourceType implementation. 278 // 279 280 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) { 281 return out << to_string(val); 282 } 283 284 // 285 // ResourceName implementation. 286 // 287 288 inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t, 289 const android::StringPiece& e) 290 : package(p.to_string()), type(t), entry(e.to_string()) {} 291 292 inline int ResourceName::compare(const ResourceName& other) const { 293 int cmp = package.compare(other.package); 294 if (cmp != 0) return cmp; 295 cmp = static_cast<int>(type) - static_cast<int>(other.type); 296 if (cmp != 0) return cmp; 297 cmp = entry.compare(other.entry); 298 return cmp; 299 } 300 301 inline bool ResourceName::is_valid() const { 302 return !package.empty() && !entry.empty(); 303 } 304 305 inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) { 306 return std::tie(lhs.package, lhs.type, lhs.entry) < 307 std::tie(rhs.package, rhs.type, rhs.entry); 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 ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) { 321 return out << name.to_string(); 322 } 323 324 // 325 // ResourceNameRef implementation. 326 // 327 328 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) 329 : package(rhs.package), type(rhs.type), entry(rhs.entry) {} 330 331 inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t, 332 const android::StringPiece& e) 333 : package(p), type(t), entry(e) {} 334 335 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { 336 package = rhs.package; 337 type = rhs.type; 338 entry = rhs.entry; 339 return *this; 340 } 341 342 inline ResourceName ResourceNameRef::ToResourceName() const { 343 return ResourceName(package, type, entry); 344 } 345 346 inline bool ResourceNameRef::is_valid() const { 347 return !package.empty() && !entry.empty(); 348 } 349 350 inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) { 351 return std::tie(lhs.package, lhs.type, lhs.entry) < 352 std::tie(rhs.package, rhs.type, rhs.entry); 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 ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) { 366 return out << name.to_string(); 367 } 368 369 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) { 370 return ResourceNameRef(lhs) < b; 371 } 372 373 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) { 374 return ResourceNameRef(lhs) != rhs; 375 } 376 377 inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) { 378 return lhs.name == rhs.name && lhs.line == rhs.line; 379 } 380 381 } // namespace aapt 382 383 namespace std { 384 385 template <> 386 struct hash<aapt::ResourceName> { 387 size_t operator()(const aapt::ResourceName& name) const { 388 android::hash_t h = 0; 389 h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package))); 390 h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type)); 391 h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry))); 392 return static_cast<size_t>(h); 393 } 394 }; 395 396 template <> 397 struct hash<aapt::ResourceId> { 398 size_t operator()(const aapt::ResourceId& id) const { 399 return id.id; 400 } 401 }; 402 403 } // namespace std 404 405 #endif // AAPT_RESOURCE_H 406