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