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