blob: 30739db543d3dd25ba2653b177f2fbcfd9cc152f [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "ConfigDescription.h"
21#include "Source.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070022#include "util/StringPiece.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080023
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -070024#include <utils/JenkinsHash.h>
25
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080026#include <iomanip>
Adam Lesinskica2fc352015-04-03 12:08:26 -070027#include <limits>
Adam Lesinskid0f116b2016-07-08 15:00:32 -070028#include <sstream>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080029#include <string>
30#include <tuple>
Adam Lesinski1ab598f2015-08-14 14:26:04 -070031#include <vector>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080032
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 {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070040 kAnim,
41 kAnimator,
42 kArray,
43 kAttr,
44 kAttrPrivate,
45 kBool,
46 kColor,
47 kDimen,
48 kDrawable,
49 kFraction,
50 kId,
51 kInteger,
52 kInterpolator,
53 kLayout,
54 kMenu,
55 kMipmap,
56 kPlurals,
57 kRaw,
58 kString,
59 kStyle,
60 kStyleable,
61 kTransition,
62 kXml,
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080063};
64
Adam Lesinskid0f116b2016-07-08 15:00:32 -070065StringPiece toString(ResourceType type);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080066
67/**
68 * Returns a pointer to a valid ResourceType, or nullptr if
69 * the string was invalid.
70 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070071const ResourceType* parseResourceType(const StringPiece& str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080072
73/**
74 * A resource's name. This can uniquely identify
75 * a resource in the ResourceTable.
76 */
77struct ResourceName {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070078 std::string package;
79 ResourceType type;
80 std::string entry;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080081
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 ResourceName() : type(ResourceType::kRaw) {}
83 ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e);
Adam Lesinski9ba47d82015-10-13 11:37:10 -070084
Adam Lesinskicacb28f2016-10-19 12:18:14 -070085 int compare(const ResourceName& other) const;
Adam Lesinski8197cc462016-08-19 12:16:49 -070086
Adam Lesinskicacb28f2016-10-19 12:18:14 -070087 bool isValid() const;
88 std::string toString() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089};
90
91/**
92 * Same as ResourceName, but uses StringPieces instead.
93 * Use this if you need to avoid copying and know that
94 * the lifetime of this object is shorter than that
95 * of the original string.
96 */
97struct ResourceNameRef {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 StringPiece package;
99 ResourceType type;
100 StringPiece entry;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800101
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 ResourceNameRef() = default;
103 ResourceNameRef(const ResourceNameRef&) = default;
104 ResourceNameRef(ResourceNameRef&&) = default;
105 ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit)
106 ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
107 ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
108 ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
109 ResourceNameRef& operator=(const ResourceName& rhs);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800110
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 ResourceName toResourceName() const;
112 bool isValid() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800113};
114
115/**
116 * A binary identifier representing a resource. Internally it
117 * is a 32bit integer split as follows:
118 *
119 * 0xPPTTEEEE
120 *
121 * PP: 8 bit package identifier. 0x01 is reserved for system
122 * and 0x7f is reserved for the running app.
123 * TT: 8 bit type identifier. 0x00 is invalid.
124 * EEEE: 16 bit entry identifier.
125 */
126struct ResourceId {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 uint32_t id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800128
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 ResourceId();
130 ResourceId(const ResourceId& rhs);
131 ResourceId(uint32_t resId); // NOLINT(implicit)
132 ResourceId(uint8_t p, uint8_t t, uint16_t e);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800133
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 bool isValid() const;
135 uint8_t packageId() const;
136 uint8_t typeId() const;
137 uint16_t entryId() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800138};
139
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700140struct SourcedResourceName {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 ResourceName name;
142 size_t line;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700143};
144
145struct ResourceFile {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 // Name
147 ResourceName name;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700148
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 // Configuration
150 ConfigDescription config;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700151
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 // Source
153 Source source;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700154
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 // Exported symbols
156 std::vector<SourcedResourceName> exportedSymbols;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700157};
158
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800159/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 * Useful struct used as a key to represent a unique resource in associative
161 * containers.
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800162 */
163struct ResourceKey {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164 ResourceName name;
165 ConfigDescription config;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800166};
167
168bool operator<(const ResourceKey& a, const ResourceKey& b);
169
170/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171 * Useful struct used as a key to represent a unique resource in associative
172 * containers.
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800173 * Holds a reference to the name, so that name better live longer than this key!
174 */
175struct ResourceKeyRef {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 ResourceNameRef name;
177 ConfigDescription config;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800178
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 ResourceKeyRef() = default;
180 ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c)
181 : name(n), config(c) {}
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800182
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 /**
184 * Prevent taking a reference to a temporary. This is bad.
185 */
186 ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800187};
188
189bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
190
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800191//
192// ResourceId implementation.
193//
194
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700195inline ResourceId::ResourceId() : id(0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800196
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700197inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800198
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199inline ResourceId::ResourceId(uint32_t resId) : id(resId) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800200
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
202 : id((p << 24) | (t << 16) | e) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800203
204inline bool ResourceId::isValid() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700205 return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800206}
207
208inline uint8_t ResourceId::packageId() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700209 return static_cast<uint8_t>(id >> 24);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800210}
211
212inline uint8_t ResourceId::typeId() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700213 return static_cast<uint8_t>(id >> 16);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800214}
215
216inline uint16_t ResourceId::entryId() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 return static_cast<uint16_t>(id);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800218}
219
Adam Lesinski74605cd2016-03-03 15:39:50 -0800220inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221 return lhs.id < rhs.id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800222}
223
Adam Lesinski74605cd2016-03-03 15:39:50 -0800224inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700225 return lhs.id > rhs.id;
Adam Lesinski24aad162015-04-24 19:19:30 -0700226}
227
Adam Lesinski74605cd2016-03-03 15:39:50 -0800228inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 return lhs.id == rhs.id;
Adam Lesinski74605cd2016-03-03 15:39:50 -0800230}
231
232inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 return lhs.id != rhs.id;
Adam Lesinski74605cd2016-03-03 15:39:50 -0800234}
235
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700236inline ::std::ostream& operator<<(::std::ostream& out,
237 const ResourceId& resId) {
238 std::ios_base::fmtflags oldFlags = out.flags();
239 char oldFill = out.fill();
240 out << "0x" << std::internal << std::setfill('0') << std::setw(8) << std::hex
241 << resId.id;
242 out.flags(oldFlags);
243 out.fill(oldFill);
244 return out;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800245}
246
247//
248// ResourceType implementation.
249//
250
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700251inline ::std::ostream& operator<<(::std::ostream& out,
252 const ResourceType& val) {
253 return out << toString(val);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800254}
255
256//
257// ResourceName implementation.
258//
259
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260inline ResourceName::ResourceName(const StringPiece& p, ResourceType t,
261 const StringPiece& e)
262 : package(p.toString()), type(t), entry(e.toString()) {}
Adam Lesinski9ba47d82015-10-13 11:37:10 -0700263
Adam Lesinski8197cc462016-08-19 12:16:49 -0700264inline int ResourceName::compare(const ResourceName& other) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700265 int cmp = package.compare(other.package);
266 if (cmp != 0) return cmp;
267 cmp = static_cast<int>(type) - static_cast<int>(other.type);
268 if (cmp != 0) return cmp;
269 cmp = entry.compare(other.entry);
270 return cmp;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700271}
272
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800273inline bool ResourceName::isValid() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700274 return !package.empty() && !entry.empty();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800275}
276
Adam Lesinski74605cd2016-03-03 15:39:50 -0800277inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 return std::tie(lhs.package, lhs.type, lhs.entry) <
279 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800280}
281
Adam Lesinski74605cd2016-03-03 15:39:50 -0800282inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700283 return std::tie(lhs.package, lhs.type, lhs.entry) ==
284 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800285}
286
Adam Lesinski74605cd2016-03-03 15:39:50 -0800287inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288 return std::tie(lhs.package, lhs.type, lhs.entry) !=
289 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800290}
291
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700292inline ::std::ostream& operator<<(::std::ostream& out,
293 const ResourceName& name) {
294 if (!name.package.empty()) {
295 out << name.package << ":";
296 }
297 return out << name.type << "/" << name.entry;
Adam Lesinski769de982015-04-10 19:43:55 -0700298}
299
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700300inline std::string ResourceName::toString() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700301 std::stringstream stream;
302 stream << *this;
303 return stream.str();
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700304}
Adam Lesinski769de982015-04-10 19:43:55 -0700305
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800306//
307// ResourceNameRef implementation.
308//
309
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700310inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
311 : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800312
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700313inline ResourceNameRef::ResourceNameRef(const StringPiece& p, ResourceType t,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700314 const StringPiece& e)
315 : package(p), type(t), entry(e) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800316
317inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700318 package = rhs.package;
319 type = rhs.type;
320 entry = rhs.entry;
321 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800322}
323
324inline ResourceName ResourceNameRef::toResourceName() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700325 return ResourceName(package, type, entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800326}
327
328inline bool ResourceNameRef::isValid() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700329 return !package.empty() && !entry.empty();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800330}
331
Adam Lesinski74605cd2016-03-03 15:39:50 -0800332inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333 return std::tie(lhs.package, lhs.type, lhs.entry) <
334 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800335}
336
Adam Lesinski74605cd2016-03-03 15:39:50 -0800337inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700338 return std::tie(lhs.package, lhs.type, lhs.entry) ==
339 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800340}
341
Adam Lesinski74605cd2016-03-03 15:39:50 -0800342inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700343 return std::tie(lhs.package, lhs.type, lhs.entry) !=
344 std::tie(rhs.package, rhs.type, rhs.entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800345}
346
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700347inline ::std::ostream& operator<<(::std::ostream& out,
348 const ResourceNameRef& name) {
349 if (!name.package.empty()) {
350 out << name.package << ":";
351 }
352 return out << name.type << "/" << name.entry;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800353}
354
Adam Lesinski74605cd2016-03-03 15:39:50 -0800355inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700356 return ResourceNameRef(lhs) < b;
Adam Lesinski74605cd2016-03-03 15:39:50 -0800357}
358
359inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700360 return ResourceNameRef(lhs) != rhs;
Adam Lesinski74605cd2016-03-03 15:39:50 -0800361}
362
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700363inline bool operator==(const SourcedResourceName& lhs,
364 const SourcedResourceName& rhs) {
365 return lhs.name == rhs.name && lhs.line == rhs.line;
Adam Lesinski74605cd2016-03-03 15:39:50 -0800366}
367
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700368} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800369
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700370namespace std {
371
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700372template <>
373struct hash<aapt::ResourceName> {
374 size_t operator()(const aapt::ResourceName& name) const {
375 android::hash_t h = 0;
376 h = android::JenkinsHashMix(h, hash<string>()(name.package));
377 h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
378 h = android::JenkinsHashMix(h, hash<string>()(name.entry));
379 return static_cast<size_t>(h);
380 }
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700381};
382
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700383} // namespace std
Adam Lesinskibf0bd0f2016-06-01 15:31:50 -0700384
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700385#endif // AAPT_RESOURCE_H