blob: e0137290f5ee7ed995ddb3a3a875da3d874ee4d1 [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
Adam Lesinskicacb28f2016-10-19 12:18:14 -070017#include "ResourceValues.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include <algorithm>
20#include <limits>
21#include <set>
22
23#include "androidfw/ResourceTypes.h"
24
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080025#include "Resource.h"
Adam Lesinskia5870652015-11-20 15:32:30 -080026#include "ResourceUtils.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070027#include "ValueVisitor.h"
Adam Lesinskie78fd612015-10-22 12:48:43 -070028#include "util/Util.h"
Adam Lesinskie78fd612015-10-22 12:48:43 -070029
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080030namespace aapt {
31
Adam Lesinski5924d8c2017-05-30 15:15:58 -070032std::ostream& operator<<(std::ostream& out, const Value& value) {
33 value.Print(&out);
34 return out;
35}
36
Adam Lesinski1ab598f2015-08-14 14:26:04 -070037template <typename Derived>
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070038void BaseValue<Derived>::Accept(ValueVisitor* visitor) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070039 visitor->Visit(static_cast<Derived*>(this));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040}
41
42template <typename Derived>
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070043void BaseValue<Derived>::Accept(ConstValueVisitor* visitor) const {
44 visitor->Visit(static_cast<const Derived*>(this));
45}
46
47template <typename Derived>
48void BaseItem<Derived>::Accept(ValueVisitor* visitor) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049 visitor->Visit(static_cast<Derived*>(this));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070050}
51
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070052template <typename Derived>
53void BaseItem<Derived>::Accept(ConstValueVisitor* visitor) const {
54 visitor->Visit(static_cast<const Derived*>(this));
55}
56
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057RawString::RawString(const StringPool::Ref& ref) : value(ref) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080058
Adam Lesinskice5e56e2016-10-21 17:56:45 -070059bool RawString::Equals(const Value* value) const {
60 const RawString* other = ValueCast<RawString>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070061 if (!other) {
62 return false;
63 }
64 return *this->value == *other->value;
Adam Lesinski458b8772016-04-25 14:20:21 -070065}
66
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067RawString* RawString::Clone(StringPool* new_pool) const {
68 RawString* rs = new RawString(new_pool->MakeRef(*value));
69 rs->comment_ = comment_;
70 rs->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070071 return rs;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080072}
73
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074bool RawString::Flatten(android::Res_value* out_value) const {
75 out_value->dataType = android::Res_value::TYPE_STRING;
76 out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078}
79
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080void RawString::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070081 *out << "(raw string) " << *value;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080082}
83
Adam Lesinskice5e56e2016-10-21 17:56:45 -070084Reference::Reference() : reference_type(Type::kResource) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080085
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086Reference::Reference(const ResourceNameRef& n, Type t)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070087 : name(n.ToResourceName()), reference_type(t) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080088
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089Reference::Reference(const ResourceId& i, Type type)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 : id(i), reference_type(type) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080091
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092Reference::Reference(const ResourceNameRef& n, const ResourceId& i)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 : name(n.ToResourceName()), id(i), reference_type(Type::kResource) {}
Adam Lesinski5c3464c2016-08-24 16:03:48 -070094
Adam Lesinskice5e56e2016-10-21 17:56:45 -070095bool Reference::Equals(const Value* value) const {
96 const Reference* other = ValueCast<Reference>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 if (!other) {
98 return false;
99 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700100 return reference_type == other->reference_type &&
101 private_reference == other->private_reference && id == other->id &&
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 name == other->name;
Adam Lesinski458b8772016-04-25 14:20:21 -0700103}
104
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700105bool Reference::Flatten(android::Res_value* out_value) const {
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800106 const ResourceId resid = id.value_or_default(ResourceId(0));
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700107 const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
108 resid.package_id() != kAppPackageId;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800109
110 if (reference_type == Reference::Type::kResource) {
111 if (dynamic) {
112 out_value->dataType = android::Res_value::TYPE_DYNAMIC_REFERENCE;
113 } else {
114 out_value->dataType = android::Res_value::TYPE_REFERENCE;
115 }
116 } else {
117 if (dynamic) {
118 out_value->dataType = android::Res_value::TYPE_DYNAMIC_ATTRIBUTE;
119 } else {
120 out_value->dataType = android::Res_value::TYPE_ATTRIBUTE;
121 }
122 }
123 out_value->data = util::HostToDevice32(resid.id);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800125}
126
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700127Reference* Reference::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 return new Reference(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800129}
130
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700131void Reference::Print(std::ostream* out) const {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700132 if (reference_type == Type::kResource) {
133 *out << "(reference) @";
134 if (!name && !id) {
135 *out << "null";
136 return;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800137 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700138 } else {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700139 *out << "(attr-reference) ?";
140 }
141
142 if (private_reference) {
143 *out << "*";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800145
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 if (name) {
147 *out << name.value();
148 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800149
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700150 if (id && id.value().is_valid_dynamic()) {
151 if (name) {
152 *out << " ";
153 }
154 *out << id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800156}
157
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158bool Id::Equals(const Value* value) const {
159 return ValueCast<Id>(value) != nullptr;
Adam Lesinski458b8772016-04-25 14:20:21 -0700160}
161
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700162bool Id::Flatten(android::Res_value* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163 out->dataType = android::Res_value::TYPE_INT_BOOLEAN;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700164 out->data = util::HostToDevice32(0);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166}
167
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800169
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700170void Id::Print(std::ostream* out) const { *out << "(id)"; }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800171
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700172String::String(const StringPool::Ref& ref) : value(ref) {}
Adam Lesinski393b5f02015-12-17 13:03:11 -0800173
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174bool String::Equals(const Value* value) const {
175 const String* other = ValueCast<String>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 if (!other) {
177 return false;
178 }
Adam Lesinski75421622017-01-06 15:20:04 -0800179
180 if (this->value != other->value) {
181 return false;
182 }
183
184 if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
185 return false;
186 }
187
188 auto other_iter = other->untranslatable_sections.begin();
189 for (const UntranslatableSection& this_section : untranslatable_sections) {
190 if (this_section != *other_iter) {
191 return false;
192 }
193 ++other_iter;
194 }
195 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800196}
197
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700198bool String::Flatten(android::Res_value* out_value) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 // Verify that our StringPool index is within encode-able limits.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700200 if (value.index() > std::numeric_limits<uint32_t>::max()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 return false;
202 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800203
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700204 out_value->dataType = android::Res_value::TYPE_STRING;
205 out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800207}
208
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700209String* String::Clone(StringPool* new_pool) const {
210 String* str = new String(new_pool->MakeRef(*value));
211 str->comment_ = comment_;
212 str->source_ = source_;
Adam Lesinski75421622017-01-06 15:20:04 -0800213 str->untranslatable_sections = untranslatable_sections;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214 return str;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800215}
216
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700217void String::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700218 *out << "(string) \"" << *value << "\"";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800219}
220
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {}
Adam Lesinski393b5f02015-12-17 13:03:11 -0800222
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223bool StyledString::Equals(const Value* value) const {
224 const StyledString* other = ValueCast<StyledString>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700225 if (!other) {
Adam Lesinski458b8772016-04-25 14:20:21 -0700226 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700227 }
228
Adam Lesinski75421622017-01-06 15:20:04 -0800229 if (this->value != other->value) {
230 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700231 }
Adam Lesinski75421622017-01-06 15:20:04 -0800232
233 if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
234 return false;
235 }
236
237 auto other_iter = other->untranslatable_sections.begin();
238 for (const UntranslatableSection& this_section : untranslatable_sections) {
239 if (this_section != *other_iter) {
240 return false;
241 }
242 ++other_iter;
243 }
244 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800245}
246
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247bool StyledString::Flatten(android::Res_value* out_value) const {
248 if (value.index() > std::numeric_limits<uint32_t>::max()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 return false;
250 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800251
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 out_value->dataType = android::Res_value::TYPE_STRING;
253 out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700254 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800255}
256
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700257StyledString* StyledString::Clone(StringPool* new_pool) const {
258 StyledString* str = new StyledString(new_pool->MakeRef(value));
259 str->comment_ = comment_;
260 str->source_ = source_;
Adam Lesinski75421622017-01-06 15:20:04 -0800261 str->untranslatable_sections = untranslatable_sections;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262 return str;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263}
264
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265void StyledString::Print(std::ostream* out) const {
Adam Lesinski060b53d2017-07-28 17:10:35 -0700266 *out << "(styled string) \"" << value->value << "\"";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700267 for (const StringPool::Span& span : value->spans) {
Adam Lesinski060b53d2017-07-28 17:10:35 -0700268 *out << " " << *span.name << ":" << span.first_char << "," << span.last_char;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700269 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800270}
271
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800273
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700274bool FileReference::Equals(const Value* value) const {
275 const FileReference* other = ValueCast<FileReference>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276 if (!other) {
277 return false;
278 }
Adam Lesinski75421622017-01-06 15:20:04 -0800279 return path == other->path;
Adam Lesinski458b8772016-04-25 14:20:21 -0700280}
281
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282bool FileReference::Flatten(android::Res_value* out_value) const {
283 if (path.index() > std::numeric_limits<uint32_t>::max()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284 return false;
285 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800286
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700287 out_value->dataType = android::Res_value::TYPE_STRING;
288 out_value->data = util::HostToDevice32(static_cast<uint32_t>(path.index()));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700289 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800290}
291
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700292FileReference* FileReference::Clone(StringPool* new_pool) const {
293 FileReference* fr = new FileReference(new_pool->MakeRef(*path));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700294 fr->file = file;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700295 fr->comment_ = comment_;
296 fr->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297 return fr;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800298}
299
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700300void FileReference::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700301 *out << "(file) " << *path;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800302}
303
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700304BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800305
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700306BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700307 value.dataType = dataType;
308 value.data = data;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700309}
310
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700311bool BinaryPrimitive::Equals(const Value* value) const {
312 const BinaryPrimitive* other = ValueCast<BinaryPrimitive>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700313 if (!other) {
314 return false;
315 }
316 return this->value.dataType == other->value.dataType &&
317 this->value.data == other->value.data;
Adam Lesinski458b8772016-04-25 14:20:21 -0700318}
319
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700320bool BinaryPrimitive::Flatten(android::Res_value* out_value) const {
321 out_value->dataType = value.dataType;
322 out_value->data = util::HostToDevice32(value.data);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700323 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800324}
325
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700326BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700327 return new BinaryPrimitive(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800328}
329
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330void BinaryPrimitive::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331 switch (value.dataType) {
332 case android::Res_value::TYPE_NULL:
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700333 if (value.data == android::Res_value::DATA_NULL_EMPTY) {
334 *out << "(empty)";
335 } else {
336 *out << "(null)";
337 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700338 break;
339 case android::Res_value::TYPE_INT_DEC:
340 *out << "(integer) " << static_cast<int32_t>(value.data);
341 break;
342 case android::Res_value::TYPE_INT_HEX:
343 *out << "(integer) 0x" << std::hex << value.data << std::dec;
344 break;
345 case android::Res_value::TYPE_INT_BOOLEAN:
346 *out << "(boolean) " << (value.data != 0 ? "true" : "false");
347 break;
348 case android::Res_value::TYPE_INT_COLOR_ARGB8:
349 case android::Res_value::TYPE_INT_COLOR_RGB8:
350 case android::Res_value::TYPE_INT_COLOR_ARGB4:
351 case android::Res_value::TYPE_INT_COLOR_RGB4:
352 *out << "(color) #" << std::hex << value.data << std::dec;
353 break;
354 default:
355 *out << "(unknown 0x" << std::hex << (int)value.dataType << ") 0x"
356 << std::hex << value.data << std::dec;
357 break;
358 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800359}
360
Adam Lesinskic744ae82017-05-17 19:28:38 -0700361Attribute::Attribute()
362 : type_mask(0u),
363 min_int(std::numeric_limits<int32_t>::min()),
364 max_int(std::numeric_limits<int32_t>::max()) {
365}
366
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700367Attribute::Attribute(bool w, uint32_t t)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 : type_mask(t),
369 min_int(std::numeric_limits<int32_t>::min()),
370 max_int(std::numeric_limits<int32_t>::max()) {
371 weak_ = w;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800372}
373
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700374std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
375 if (s.symbol.name) {
376 out << s.symbol.name.value().entry;
377 } else {
378 out << "???";
379 }
380 return out << "=" << s.value;
381}
382
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700383template <typename T>
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800384constexpr T* add_pointer(T& val) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700385 return &val;
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700386}
387
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700388bool Attribute::Equals(const Value* value) const {
389 const Attribute* other = ValueCast<Attribute>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700390 if (!other) {
391 return false;
392 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700393
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700394 if (symbols.size() != other->symbols.size()) {
395 return false;
396 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700397
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700398 if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700399 return false;
400 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700401
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402 std::vector<const Symbol*> sorted_a;
403 std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800404 add_pointer<const Symbol>);
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700405 std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool {
406 return a->symbol.name < b->symbol.name;
407 });
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700408
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700409 std::vector<const Symbol*> sorted_b;
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700410 std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b),
411 add_pointer<const Symbol>);
412 std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool {
413 return a->symbol.name < b->symbol.name;
414 });
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700415
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700416 return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700417 [](const Symbol* a, const Symbol* b) -> bool {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700418 return a->symbol.Equals(&b->symbol) && a->value == b->value;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700419 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700420}
421
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700422Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700423 return new Attribute(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800424}
425
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700426void Attribute::PrintMask(std::ostream* out) const {
427 if (type_mask == android::ResTable_map::TYPE_ANY) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700428 *out << "any";
429 return;
430 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800431
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700432 bool set = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700433 if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700434 if (!set) {
435 set = true;
436 } else {
437 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800438 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700439 *out << "reference";
440 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800441
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700442 if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700443 if (!set) {
444 set = true;
445 } else {
446 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800447 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700448 *out << "string";
449 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800450
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700451 if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700452 if (!set) {
453 set = true;
454 } else {
455 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800456 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700457 *out << "integer";
458 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800459
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700460 if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700461 if (!set) {
462 set = true;
463 } else {
464 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800465 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700466 *out << "boolean";
467 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800468
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700469 if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700470 if (!set) {
471 set = true;
472 } else {
473 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800474 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700475 *out << "color";
476 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800477
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700478 if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700479 if (!set) {
480 set = true;
481 } else {
482 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800483 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700484 *out << "float";
485 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800486
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700487 if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700488 if (!set) {
489 set = true;
490 } else {
491 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800492 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700493 *out << "dimension";
494 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800495
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700496 if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700497 if (!set) {
498 set = true;
499 } else {
500 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800501 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700502 *out << "fraction";
503 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800504
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700505 if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700506 if (!set) {
507 set = true;
508 } else {
509 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800510 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700511 *out << "enum";
512 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800513
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700514 if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700515 if (!set) {
516 set = true;
517 } else {
518 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800519 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700520 *out << "flags";
521 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700522}
523
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700524void Attribute::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700525 *out << "(attr) ";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700526 PrintMask(out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800527
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700528 if (!symbols.empty()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700529 *out << " [" << util::Joiner(symbols, ", ") << "]";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700530 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800531
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700532 if (min_int != std::numeric_limits<int32_t>::min()) {
533 *out << " min=" << min_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700534 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700535
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700536 if (max_int != std::numeric_limits<int32_t>::max()) {
537 *out << " max=" << max_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700538 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700539
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700540 if (IsWeak()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700541 *out << " [weak]";
542 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800543}
544
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700545static void BuildAttributeMismatchMessage(const Attribute& attr, const Item& value,
546 DiagMessage* out_msg) {
547 *out_msg << "expected";
548 if (attr.type_mask & android::ResTable_map::TYPE_BOOLEAN) {
549 *out_msg << " boolean";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700550 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800551
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700552 if (attr.type_mask & android::ResTable_map::TYPE_COLOR) {
553 *out_msg << " color";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700554 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800555
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700556 if (attr.type_mask & android::ResTable_map::TYPE_DIMENSION) {
557 *out_msg << " dimension";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700558 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800559
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700560 if (attr.type_mask & android::ResTable_map::TYPE_ENUM) {
561 *out_msg << " enum";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700562 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800563
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700564 if (attr.type_mask & android::ResTable_map::TYPE_FLAGS) {
565 *out_msg << " flags";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700566 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800567
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700568 if (attr.type_mask & android::ResTable_map::TYPE_FLOAT) {
569 *out_msg << " float";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700570 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800571
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700572 if (attr.type_mask & android::ResTable_map::TYPE_FRACTION) {
573 *out_msg << " fraction";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700574 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800575
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700576 if (attr.type_mask & android::ResTable_map::TYPE_INTEGER) {
577 *out_msg << " integer";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700578 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800579
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700580 if (attr.type_mask & android::ResTable_map::TYPE_REFERENCE) {
581 *out_msg << " reference";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700582 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800583
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700584 if (attr.type_mask & android::ResTable_map::TYPE_STRING) {
585 *out_msg << " string";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700586 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800587
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700588 *out_msg << " but got " << value;
Adam Lesinskia5870652015-11-20 15:32:30 -0800589}
590
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700591bool Attribute::Matches(const Item& item, DiagMessage* out_msg) const {
592 constexpr const uint32_t TYPE_ENUM = android::ResTable_map::TYPE_ENUM;
593 constexpr const uint32_t TYPE_FLAGS = android::ResTable_map::TYPE_FLAGS;
594 constexpr const uint32_t TYPE_INTEGER = android::ResTable_map::TYPE_INTEGER;
595 constexpr const uint32_t TYPE_REFERENCE = android::ResTable_map::TYPE_REFERENCE;
596
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700597 android::Res_value val = {};
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700598 item.Flatten(&val);
599
600 const uint32_t flattened_data = util::DeviceToHost32(val.data);
Adam Lesinskia5870652015-11-20 15:32:30 -0800601
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700602 // Always allow references.
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700603 const uint32_t actual_type = ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType);
604
605 // Only one type must match between the actual and expected.
606 if ((actual_type & (type_mask | TYPE_REFERENCE)) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700607 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700608 BuildAttributeMismatchMessage(*this, item, out_msg);
Adam Lesinskia5870652015-11-20 15:32:30 -0800609 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700610 return false;
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700611 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700612
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700613 // Enums and flags are encoded as integers, so check them first before doing any range checks.
614 if ((type_mask & TYPE_ENUM) != 0 && (actual_type & TYPE_ENUM) != 0) {
615 for (const Symbol& s : symbols) {
616 if (flattened_data == s.value) {
617 return true;
618 }
619 }
620
621 // If the attribute accepts integers, we can't fail here.
622 if ((type_mask & TYPE_INTEGER) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700623 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700624 *out_msg << item << " is not a valid enum";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700625 }
626 return false;
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700627 }
628 }
629
630 if ((type_mask & TYPE_FLAGS) != 0 && (actual_type & TYPE_FLAGS) != 0) {
631 uint32_t mask = 0u;
632 for (const Symbol& s : symbols) {
633 mask |= s.value;
634 }
635
636 // Check if the flattened data is covered by the flag bit mask.
637 // If the attribute accepts integers, we can't fail here.
638 if ((mask & flattened_data) == flattened_data) {
639 return true;
640 } else if ((type_mask & TYPE_INTEGER) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700641 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700642 *out_msg << item << " is not a valid flag";
643 }
644 return false;
645 }
646 }
647
648 // Finally check the integer range of the value.
649 if ((type_mask & TYPE_INTEGER) != 0 && (actual_type & TYPE_INTEGER) != 0) {
650 if (static_cast<int32_t>(flattened_data) < min_int) {
651 if (out_msg) {
652 *out_msg << item << " is less than minimum integer " << min_int;
653 }
654 return false;
655 } else if (static_cast<int32_t>(flattened_data) > max_int) {
656 if (out_msg) {
657 *out_msg << item << " is greater than maximum integer " << max_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700658 }
659 return false;
660 }
661 }
662 return true;
Adam Lesinskia5870652015-11-20 15:32:30 -0800663}
664
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700665std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) {
666 if (entry.key.name) {
667 out << entry.key.name.value();
668 } else if (entry.key.id) {
669 out << entry.key.id.value();
670 } else {
671 out << "???";
672 }
673 out << " = " << entry.value;
674 return out;
675}
676
677template <typename T>
678std::vector<T*> ToPointerVec(std::vector<T>& src) {
679 std::vector<T*> dst;
680 dst.reserve(src.size());
681 for (T& in : src) {
682 dst.push_back(&in);
683 }
684 return dst;
685}
686
687template <typename T>
688std::vector<const T*> ToPointerVec(const std::vector<T>& src) {
689 std::vector<const T*> dst;
690 dst.reserve(src.size());
691 for (const T& in : src) {
692 dst.push_back(&in);
693 }
694 return dst;
695}
696
697static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) {
698 return a->key.name < b->key.name;
699}
700
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700701bool Style::Equals(const Value* value) const {
702 const Style* other = ValueCast<Style>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700703 if (!other) {
704 return false;
705 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700706
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700707 if (bool(parent) != bool(other->parent) ||
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700708 (parent && other->parent && !parent.value().Equals(&other->parent.value()))) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700709 return false;
710 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700711
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700712 if (entries.size() != other->entries.size()) {
713 return false;
714 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700715
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700716 std::vector<const Entry*> sorted_a = ToPointerVec(entries);
717 std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700718
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700719 std::vector<const Entry*> sorted_b = ToPointerVec(other->entries);
720 std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700721
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700722 return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700723 [](const Entry* a, const Entry* b) -> bool {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700724 return a->key.Equals(&b->key) && a->value->Equals(b->value.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700725 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700726}
727
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700728Style* Style::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700729 Style* style = new Style();
730 style->parent = parent;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700731 style->parent_inferred = parent_inferred;
732 style->comment_ = comment_;
733 style->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700734 for (auto& entry : entries) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700735 style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700736 }
737 return style;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800738}
739
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700740void Style::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700741 *out << "(style) ";
742 if (parent && parent.value().name) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700743 const Reference& parent_ref = parent.value();
744 if (parent_ref.private_reference) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700745 *out << "*";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800746 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700747 *out << parent_ref.name.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700748 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700749 *out << " [" << util::Joiner(entries, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800750}
751
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700752Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
753 Style::Entry cloned_entry{entry.key};
754 if (entry.value != nullptr) {
755 cloned_entry.value.reset(entry.value->Clone(pool));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700756 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700757 return cloned_entry;
758}
759
760void Style::MergeWith(Style* other, StringPool* pool) {
761 if (other->parent) {
762 parent = other->parent;
763 }
764
765 // We can't assume that the entries are sorted alphabetically since they're supposed to be
766 // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge
767 // them keying off that.
768 //
769 // Instead, sort the entries of each Style by their name in a separate structure. Then merge
770 // those.
771
772 std::vector<Entry*> this_sorted = ToPointerVec(entries);
773 std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator);
774
775 std::vector<Entry*> other_sorted = ToPointerVec(other->entries);
776 std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator);
777
778 auto this_iter = this_sorted.begin();
779 const auto this_end = this_sorted.end();
780
781 auto other_iter = other_sorted.begin();
782 const auto other_end = other_sorted.end();
783
784 std::vector<Entry> merged_entries;
785 while (this_iter != this_end) {
786 if (other_iter != other_end) {
787 if ((*this_iter)->key.name < (*other_iter)->key.name) {
788 merged_entries.push_back(std::move(**this_iter));
789 ++this_iter;
790 } else {
791 // The other overrides.
792 merged_entries.push_back(CloneEntry(**other_iter, pool));
793 if ((*this_iter)->key.name == (*other_iter)->key.name) {
794 ++this_iter;
795 }
796 ++other_iter;
797 }
798 } else {
799 merged_entries.push_back(std::move(**this_iter));
800 ++this_iter;
801 }
802 }
803
804 while (other_iter != other_end) {
805 merged_entries.push_back(CloneEntry(**other_iter, pool));
806 ++other_iter;
807 }
808
809 entries = std::move(merged_entries);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800810}
811
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700812bool Array::Equals(const Value* value) const {
813 const Array* other = ValueCast<Array>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700814 if (!other) {
815 return false;
816 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700817
Adam Lesinski4ffea042017-08-10 15:37:28 -0700818 if (elements.size() != other->elements.size()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700819 return false;
820 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700821
Adam Lesinski4ffea042017-08-10 15:37:28 -0700822 return std::equal(elements.begin(), elements.end(), other->elements.begin(),
823 [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700824 return a->Equals(b.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700825 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700826}
827
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700828Array* Array::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700829 Array* array = new Array();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700830 array->comment_ = comment_;
831 array->source_ = source_;
Adam Lesinski4ffea042017-08-10 15:37:28 -0700832 for (auto& item : elements) {
833 array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700834 }
835 return array;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800836}
837
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700838void Array::Print(std::ostream* out) const {
Adam Lesinski4ffea042017-08-10 15:37:28 -0700839 *out << "(array) [" << util::Joiner(elements, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800840}
841
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700842bool Plural::Equals(const Value* value) const {
843 const Plural* other = ValueCast<Plural>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700844 if (!other) {
845 return false;
846 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700847
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800848 auto one_iter = values.begin();
849 auto one_end_iter = values.end();
850 auto two_iter = other->values.begin();
851 for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
852 const std::unique_ptr<Item>& a = *one_iter;
853 const std::unique_ptr<Item>& b = *two_iter;
854 if (a != nullptr && b != nullptr) {
855 if (!a->Equals(b.get())) {
856 return false;
857 }
858 } else if (a != b) {
859 return false;
860 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700861 }
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800862 return true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700863}
864
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700865Plural* Plural::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700866 Plural* p = new Plural();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700867 p->comment_ = comment_;
868 p->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700869 const size_t count = values.size();
870 for (size_t i = 0; i < count; i++) {
871 if (values[i]) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700872 p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800873 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700874 }
875 return p;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800876}
877
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700878void Plural::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700879 *out << "(plural)";
880 if (values[Zero]) {
881 *out << " zero=" << *values[Zero];
882 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700883
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700884 if (values[One]) {
885 *out << " one=" << *values[One];
886 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700887
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700888 if (values[Two]) {
889 *out << " two=" << *values[Two];
890 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700891
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700892 if (values[Few]) {
893 *out << " few=" << *values[Few];
894 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700895
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700896 if (values[Many]) {
897 *out << " many=" << *values[Many];
898 }
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800899
900 if (values[Other]) {
901 *out << " other=" << *values[Other];
902 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800903}
904
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700905bool Styleable::Equals(const Value* value) const {
906 const Styleable* other = ValueCast<Styleable>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700907 if (!other) {
908 return false;
909 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700910
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700911 if (entries.size() != other->entries.size()) {
912 return false;
913 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700914
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700915 return std::equal(entries.begin(), entries.end(), other->entries.begin(),
916 [](const Reference& a, const Reference& b) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700917 return a.Equals(&b);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700918 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700919}
920
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700921Styleable* Styleable::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700922 return new Styleable(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800923}
924
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700925void Styleable::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700926 *out << "(styleable) "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700927 << " [" << util::Joiner(entries, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800928}
929
Adam Lesinski8197cc462016-08-19 12:16:49 -0700930bool operator<(const Reference& a, const Reference& b) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700931 int cmp = a.name.value_or_default({}).compare(b.name.value_or_default({}));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700932 if (cmp != 0) return cmp < 0;
933 return a.id < b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700934}
935
936bool operator==(const Reference& a, const Reference& b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700937 return a.name == b.name && a.id == b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700938}
939
940bool operator!=(const Reference& a, const Reference& b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700941 return a.name != b.name || a.id != b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700942}
943
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700944struct NameOnlyComparator {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700945 bool operator()(const Reference& a, const Reference& b) const {
946 return a.name < b.name;
947 }
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700948};
949
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700950void Styleable::MergeWith(Styleable* other) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700951 // Compare only names, because some References may already have their IDs
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700952 // assigned (framework IDs that don't change).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700953 std::set<Reference, NameOnlyComparator> references;
954 references.insert(entries.begin(), entries.end());
955 references.insert(other->entries.begin(), other->entries.end());
956 entries.clear();
957 entries.reserve(references.size());
958 entries.insert(entries.end(), references.begin(), references.end());
Adam Lesinski8197cc462016-08-19 12:16:49 -0700959}
960
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700961} // namespace aapt