blob: 4e84a476a300456bf155db8818cb9476a90ae7cd [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 Lesinski00451162017-10-03 07:44:08 -0700295 fr->type = type;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700296 fr->comment_ = comment_;
297 fr->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700298 return fr;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800299}
300
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301void FileReference::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 *out << "(file) " << *path;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800303}
304
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800306
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700307BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 value.dataType = dataType;
309 value.data = data;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700310}
311
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700312bool BinaryPrimitive::Equals(const Value* value) const {
313 const BinaryPrimitive* other = ValueCast<BinaryPrimitive>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700314 if (!other) {
315 return false;
316 }
317 return this->value.dataType == other->value.dataType &&
318 this->value.data == other->value.data;
Adam Lesinski458b8772016-04-25 14:20:21 -0700319}
320
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700321bool BinaryPrimitive::Flatten(android::Res_value* out_value) const {
322 out_value->dataType = value.dataType;
323 out_value->data = util::HostToDevice32(value.data);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700324 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800325}
326
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700327BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700328 return new BinaryPrimitive(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800329}
330
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700331void BinaryPrimitive::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700332 switch (value.dataType) {
333 case android::Res_value::TYPE_NULL:
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700334 if (value.data == android::Res_value::DATA_NULL_EMPTY) {
335 *out << "(empty)";
336 } else {
337 *out << "(null)";
338 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700339 break;
340 case android::Res_value::TYPE_INT_DEC:
341 *out << "(integer) " << static_cast<int32_t>(value.data);
342 break;
343 case android::Res_value::TYPE_INT_HEX:
344 *out << "(integer) 0x" << std::hex << value.data << std::dec;
345 break;
346 case android::Res_value::TYPE_INT_BOOLEAN:
347 *out << "(boolean) " << (value.data != 0 ? "true" : "false");
348 break;
349 case android::Res_value::TYPE_INT_COLOR_ARGB8:
350 case android::Res_value::TYPE_INT_COLOR_RGB8:
351 case android::Res_value::TYPE_INT_COLOR_ARGB4:
352 case android::Res_value::TYPE_INT_COLOR_RGB4:
353 *out << "(color) #" << std::hex << value.data << std::dec;
354 break;
355 default:
356 *out << "(unknown 0x" << std::hex << (int)value.dataType << ") 0x"
357 << std::hex << value.data << std::dec;
358 break;
359 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800360}
361
Adam Lesinskic744ae82017-05-17 19:28:38 -0700362Attribute::Attribute()
363 : type_mask(0u),
364 min_int(std::numeric_limits<int32_t>::min()),
365 max_int(std::numeric_limits<int32_t>::max()) {
366}
367
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700368Attribute::Attribute(bool w, uint32_t t)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 : type_mask(t),
370 min_int(std::numeric_limits<int32_t>::min()),
371 max_int(std::numeric_limits<int32_t>::max()) {
372 weak_ = w;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800373}
374
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700375std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
376 if (s.symbol.name) {
377 out << s.symbol.name.value().entry;
378 } else {
379 out << "???";
380 }
381 return out << "=" << s.value;
382}
383
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700384template <typename T>
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800385constexpr T* add_pointer(T& val) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700386 return &val;
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700387}
388
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700389bool Attribute::Equals(const Value* value) const {
390 const Attribute* other = ValueCast<Attribute>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700391 if (!other) {
392 return false;
393 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700394
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700395 if (symbols.size() != other->symbols.size()) {
396 return false;
397 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700398
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700399 if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700400 return false;
401 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700402
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700403 std::vector<const Symbol*> sorted_a;
404 std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800405 add_pointer<const Symbol>);
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700406 std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool {
407 return a->symbol.name < b->symbol.name;
408 });
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700409
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700410 std::vector<const Symbol*> sorted_b;
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700411 std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b),
412 add_pointer<const Symbol>);
413 std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool {
414 return a->symbol.name < b->symbol.name;
415 });
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700416
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700417 return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700418 [](const Symbol* a, const Symbol* b) -> bool {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700419 return a->symbol.Equals(&b->symbol) && a->value == b->value;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700420 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700421}
422
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700423Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700424 return new Attribute(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800425}
426
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700427void Attribute::PrintMask(std::ostream* out) const {
428 if (type_mask == android::ResTable_map::TYPE_ANY) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700429 *out << "any";
430 return;
431 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800432
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700433 bool set = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700434 if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700435 if (!set) {
436 set = true;
437 } else {
438 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800439 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700440 *out << "reference";
441 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800442
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700443 if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700444 if (!set) {
445 set = true;
446 } else {
447 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800448 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700449 *out << "string";
450 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800451
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700452 if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700453 if (!set) {
454 set = true;
455 } else {
456 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800457 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700458 *out << "integer";
459 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800460
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700461 if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700462 if (!set) {
463 set = true;
464 } else {
465 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800466 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700467 *out << "boolean";
468 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800469
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700470 if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700471 if (!set) {
472 set = true;
473 } else {
474 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800475 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700476 *out << "color";
477 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800478
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700479 if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700480 if (!set) {
481 set = true;
482 } else {
483 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800484 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700485 *out << "float";
486 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800487
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700488 if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700489 if (!set) {
490 set = true;
491 } else {
492 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800493 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700494 *out << "dimension";
495 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800496
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700497 if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700498 if (!set) {
499 set = true;
500 } else {
501 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800502 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700503 *out << "fraction";
504 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800505
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700506 if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700507 if (!set) {
508 set = true;
509 } else {
510 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800511 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700512 *out << "enum";
513 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800514
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700515 if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700516 if (!set) {
517 set = true;
518 } else {
519 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800520 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700521 *out << "flags";
522 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700523}
524
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700525void Attribute::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700526 *out << "(attr) ";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700527 PrintMask(out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800528
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700529 if (!symbols.empty()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700530 *out << " [" << util::Joiner(symbols, ", ") << "]";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700531 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800532
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700533 if (min_int != std::numeric_limits<int32_t>::min()) {
534 *out << " min=" << min_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700535 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700536
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700537 if (max_int != std::numeric_limits<int32_t>::max()) {
538 *out << " max=" << max_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700539 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700540
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700541 if (IsWeak()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700542 *out << " [weak]";
543 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800544}
545
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700546static void BuildAttributeMismatchMessage(const Attribute& attr, const Item& value,
547 DiagMessage* out_msg) {
548 *out_msg << "expected";
549 if (attr.type_mask & android::ResTable_map::TYPE_BOOLEAN) {
550 *out_msg << " boolean";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700551 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800552
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700553 if (attr.type_mask & android::ResTable_map::TYPE_COLOR) {
554 *out_msg << " color";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700555 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800556
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700557 if (attr.type_mask & android::ResTable_map::TYPE_DIMENSION) {
558 *out_msg << " dimension";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700559 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800560
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700561 if (attr.type_mask & android::ResTable_map::TYPE_ENUM) {
562 *out_msg << " enum";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700563 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800564
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700565 if (attr.type_mask & android::ResTable_map::TYPE_FLAGS) {
566 *out_msg << " flags";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700567 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800568
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700569 if (attr.type_mask & android::ResTable_map::TYPE_FLOAT) {
570 *out_msg << " float";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700571 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800572
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700573 if (attr.type_mask & android::ResTable_map::TYPE_FRACTION) {
574 *out_msg << " fraction";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700575 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800576
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700577 if (attr.type_mask & android::ResTable_map::TYPE_INTEGER) {
578 *out_msg << " integer";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700579 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800580
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700581 if (attr.type_mask & android::ResTable_map::TYPE_REFERENCE) {
582 *out_msg << " reference";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700583 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800584
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700585 if (attr.type_mask & android::ResTable_map::TYPE_STRING) {
586 *out_msg << " string";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700587 }
Adam Lesinskia5870652015-11-20 15:32:30 -0800588
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700589 *out_msg << " but got " << value;
Adam Lesinskia5870652015-11-20 15:32:30 -0800590}
591
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700592bool Attribute::Matches(const Item& item, DiagMessage* out_msg) const {
593 constexpr const uint32_t TYPE_ENUM = android::ResTable_map::TYPE_ENUM;
594 constexpr const uint32_t TYPE_FLAGS = android::ResTable_map::TYPE_FLAGS;
595 constexpr const uint32_t TYPE_INTEGER = android::ResTable_map::TYPE_INTEGER;
596 constexpr const uint32_t TYPE_REFERENCE = android::ResTable_map::TYPE_REFERENCE;
597
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700598 android::Res_value val = {};
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700599 item.Flatten(&val);
600
601 const uint32_t flattened_data = util::DeviceToHost32(val.data);
Adam Lesinskia5870652015-11-20 15:32:30 -0800602
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700603 // Always allow references.
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700604 const uint32_t actual_type = ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType);
605
606 // Only one type must match between the actual and expected.
607 if ((actual_type & (type_mask | TYPE_REFERENCE)) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700608 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700609 BuildAttributeMismatchMessage(*this, item, out_msg);
Adam Lesinskia5870652015-11-20 15:32:30 -0800610 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700611 return false;
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700612 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700613
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700614 // Enums and flags are encoded as integers, so check them first before doing any range checks.
615 if ((type_mask & TYPE_ENUM) != 0 && (actual_type & TYPE_ENUM) != 0) {
616 for (const Symbol& s : symbols) {
617 if (flattened_data == s.value) {
618 return true;
619 }
620 }
621
622 // If the attribute accepts integers, we can't fail here.
623 if ((type_mask & TYPE_INTEGER) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700624 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700625 *out_msg << item << " is not a valid enum";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700626 }
627 return false;
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700628 }
629 }
630
631 if ((type_mask & TYPE_FLAGS) != 0 && (actual_type & TYPE_FLAGS) != 0) {
632 uint32_t mask = 0u;
633 for (const Symbol& s : symbols) {
634 mask |= s.value;
635 }
636
637 // Check if the flattened data is covered by the flag bit mask.
638 // If the attribute accepts integers, we can't fail here.
639 if ((mask & flattened_data) == flattened_data) {
640 return true;
641 } else if ((type_mask & TYPE_INTEGER) == 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700642 if (out_msg) {
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700643 *out_msg << item << " is not a valid flag";
644 }
645 return false;
646 }
647 }
648
649 // Finally check the integer range of the value.
650 if ((type_mask & TYPE_INTEGER) != 0 && (actual_type & TYPE_INTEGER) != 0) {
651 if (static_cast<int32_t>(flattened_data) < min_int) {
652 if (out_msg) {
653 *out_msg << item << " is less than minimum integer " << min_int;
654 }
655 return false;
656 } else if (static_cast<int32_t>(flattened_data) > max_int) {
657 if (out_msg) {
658 *out_msg << item << " is greater than maximum integer " << max_int;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700659 }
660 return false;
661 }
662 }
663 return true;
Adam Lesinskia5870652015-11-20 15:32:30 -0800664}
665
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700666std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) {
667 if (entry.key.name) {
668 out << entry.key.name.value();
669 } else if (entry.key.id) {
670 out << entry.key.id.value();
671 } else {
672 out << "???";
673 }
674 out << " = " << entry.value;
675 return out;
676}
677
678template <typename T>
679std::vector<T*> ToPointerVec(std::vector<T>& src) {
680 std::vector<T*> dst;
681 dst.reserve(src.size());
682 for (T& in : src) {
683 dst.push_back(&in);
684 }
685 return dst;
686}
687
688template <typename T>
689std::vector<const T*> ToPointerVec(const std::vector<T>& src) {
690 std::vector<const T*> dst;
691 dst.reserve(src.size());
692 for (const T& in : src) {
693 dst.push_back(&in);
694 }
695 return dst;
696}
697
698static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) {
699 return a->key.name < b->key.name;
700}
701
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700702bool Style::Equals(const Value* value) const {
703 const Style* other = ValueCast<Style>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700704 if (!other) {
705 return false;
706 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700707
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700708 if (bool(parent) != bool(other->parent) ||
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700709 (parent && other->parent && !parent.value().Equals(&other->parent.value()))) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700710 return false;
711 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700712
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700713 if (entries.size() != other->entries.size()) {
714 return false;
715 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700716
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700717 std::vector<const Entry*> sorted_a = ToPointerVec(entries);
718 std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700719
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700720 std::vector<const Entry*> sorted_b = ToPointerVec(other->entries);
721 std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700722
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700723 return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700724 [](const Entry* a, const Entry* b) -> bool {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700725 return a->key.Equals(&b->key) && a->value->Equals(b->value.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700726 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700727}
728
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700729Style* Style::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700730 Style* style = new Style();
731 style->parent = parent;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700732 style->parent_inferred = parent_inferred;
733 style->comment_ = comment_;
734 style->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700735 for (auto& entry : entries) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700736 style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700737 }
738 return style;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800739}
740
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700741void Style::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700742 *out << "(style) ";
743 if (parent && parent.value().name) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700744 const Reference& parent_ref = parent.value();
745 if (parent_ref.private_reference) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700746 *out << "*";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800747 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700748 *out << parent_ref.name.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700749 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700750 *out << " [" << util::Joiner(entries, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800751}
752
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700753Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
754 Style::Entry cloned_entry{entry.key};
755 if (entry.value != nullptr) {
756 cloned_entry.value.reset(entry.value->Clone(pool));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700757 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700758 return cloned_entry;
759}
760
761void Style::MergeWith(Style* other, StringPool* pool) {
762 if (other->parent) {
763 parent = other->parent;
764 }
765
766 // We can't assume that the entries are sorted alphabetically since they're supposed to be
767 // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge
768 // them keying off that.
769 //
770 // Instead, sort the entries of each Style by their name in a separate structure. Then merge
771 // those.
772
773 std::vector<Entry*> this_sorted = ToPointerVec(entries);
774 std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator);
775
776 std::vector<Entry*> other_sorted = ToPointerVec(other->entries);
777 std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator);
778
779 auto this_iter = this_sorted.begin();
780 const auto this_end = this_sorted.end();
781
782 auto other_iter = other_sorted.begin();
783 const auto other_end = other_sorted.end();
784
785 std::vector<Entry> merged_entries;
786 while (this_iter != this_end) {
787 if (other_iter != other_end) {
788 if ((*this_iter)->key.name < (*other_iter)->key.name) {
789 merged_entries.push_back(std::move(**this_iter));
790 ++this_iter;
791 } else {
792 // The other overrides.
793 merged_entries.push_back(CloneEntry(**other_iter, pool));
794 if ((*this_iter)->key.name == (*other_iter)->key.name) {
795 ++this_iter;
796 }
797 ++other_iter;
798 }
799 } else {
800 merged_entries.push_back(std::move(**this_iter));
801 ++this_iter;
802 }
803 }
804
805 while (other_iter != other_end) {
806 merged_entries.push_back(CloneEntry(**other_iter, pool));
807 ++other_iter;
808 }
809
810 entries = std::move(merged_entries);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800811}
812
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700813bool Array::Equals(const Value* value) const {
814 const Array* other = ValueCast<Array>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700815 if (!other) {
816 return false;
817 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700818
Adam Lesinski4ffea042017-08-10 15:37:28 -0700819 if (elements.size() != other->elements.size()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700820 return false;
821 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700822
Adam Lesinski4ffea042017-08-10 15:37:28 -0700823 return std::equal(elements.begin(), elements.end(), other->elements.begin(),
824 [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700825 return a->Equals(b.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700826 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700827}
828
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700829Array* Array::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700830 Array* array = new Array();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700831 array->comment_ = comment_;
832 array->source_ = source_;
Adam Lesinski4ffea042017-08-10 15:37:28 -0700833 for (auto& item : elements) {
834 array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700835 }
836 return array;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800837}
838
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700839void Array::Print(std::ostream* out) const {
Adam Lesinski4ffea042017-08-10 15:37:28 -0700840 *out << "(array) [" << util::Joiner(elements, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800841}
842
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700843bool Plural::Equals(const Value* value) const {
844 const Plural* other = ValueCast<Plural>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700845 if (!other) {
846 return false;
847 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700848
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800849 auto one_iter = values.begin();
850 auto one_end_iter = values.end();
851 auto two_iter = other->values.begin();
852 for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
853 const std::unique_ptr<Item>& a = *one_iter;
854 const std::unique_ptr<Item>& b = *two_iter;
855 if (a != nullptr && b != nullptr) {
856 if (!a->Equals(b.get())) {
857 return false;
858 }
859 } else if (a != b) {
860 return false;
861 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700862 }
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800863 return true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700864}
865
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700866Plural* Plural::Clone(StringPool* new_pool) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700867 Plural* p = new Plural();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700868 p->comment_ = comment_;
869 p->source_ = source_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700870 const size_t count = values.size();
871 for (size_t i = 0; i < count; i++) {
872 if (values[i]) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700873 p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800874 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700875 }
876 return p;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800877}
878
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700879void Plural::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700880 *out << "(plural)";
881 if (values[Zero]) {
882 *out << " zero=" << *values[Zero];
883 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700884
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700885 if (values[One]) {
886 *out << " one=" << *values[One];
887 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700888
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700889 if (values[Two]) {
890 *out << " two=" << *values[Two];
891 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700892
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700893 if (values[Few]) {
894 *out << " few=" << *values[Few];
895 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700896
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700897 if (values[Many]) {
898 *out << " many=" << *values[Many];
899 }
Adam Lesinski8f7c5502017-03-02 17:45:01 -0800900
901 if (values[Other]) {
902 *out << " other=" << *values[Other];
903 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800904}
905
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700906bool Styleable::Equals(const Value* value) const {
907 const Styleable* other = ValueCast<Styleable>(value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700908 if (!other) {
909 return false;
910 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700911
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700912 if (entries.size() != other->entries.size()) {
913 return false;
914 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700915
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700916 return std::equal(entries.begin(), entries.end(), other->entries.begin(),
917 [](const Reference& a, const Reference& b) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700918 return a.Equals(&b);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700919 });
Adam Lesinski458b8772016-04-25 14:20:21 -0700920}
921
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700922Styleable* Styleable::Clone(StringPool* /*new_pool*/) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700923 return new Styleable(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800924}
925
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700926void Styleable::Print(std::ostream* out) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700927 *out << "(styleable) "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700928 << " [" << util::Joiner(entries, ", ") << "]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800929}
930
Adam Lesinski8197cc462016-08-19 12:16:49 -0700931bool operator<(const Reference& a, const Reference& b) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700932 int cmp = a.name.value_or_default({}).compare(b.name.value_or_default({}));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700933 if (cmp != 0) return cmp < 0;
934 return a.id < b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700935}
936
937bool operator==(const Reference& a, const Reference& b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700938 return a.name == b.name && a.id == b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700939}
940
941bool operator!=(const Reference& a, const Reference& b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700942 return a.name != b.name || a.id != b.id;
Adam Lesinski8197cc462016-08-19 12:16:49 -0700943}
944
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700945struct NameOnlyComparator {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700946 bool operator()(const Reference& a, const Reference& b) const {
947 return a.name < b.name;
948 }
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700949};
950
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700951void Styleable::MergeWith(Styleable* other) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700952 // Compare only names, because some References may already have their IDs
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700953 // assigned (framework IDs that don't change).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700954 std::set<Reference, NameOnlyComparator> references;
955 references.insert(entries.begin(), entries.end());
956 references.insert(other->entries.begin(), other->entries.end());
957 entries.clear();
958 entries.reserve(references.size());
959 entries.insert(entries.end(), references.begin(), references.end());
Adam Lesinski8197cc462016-08-19 12:16:49 -0700960}
961
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700962} // namespace aapt