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