• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ResourceValues.h"
18 
19 #include <algorithm>
20 #include <limits>
21 #include <set>
22 
23 #include "androidfw/ResourceTypes.h"
24 
25 #include "Resource.h"
26 #include "ResourceUtils.h"
27 #include "ValueVisitor.h"
28 #include "util/Util.h"
29 
30 namespace aapt {
31 
operator <<(std::ostream & out,const Value & value)32 std::ostream& operator<<(std::ostream& out, const Value& value) {
33   value.Print(&out);
34   return out;
35 }
36 
37 template <typename Derived>
Accept(RawValueVisitor * visitor)38 void BaseValue<Derived>::Accept(RawValueVisitor* visitor) {
39   visitor->Visit(static_cast<Derived*>(this));
40 }
41 
42 template <typename Derived>
Accept(RawValueVisitor * visitor)43 void BaseItem<Derived>::Accept(RawValueVisitor* visitor) {
44   visitor->Visit(static_cast<Derived*>(this));
45 }
46 
RawString(const StringPool::Ref & ref)47 RawString::RawString(const StringPool::Ref& ref) : value(ref) {}
48 
Equals(const Value * value) const49 bool RawString::Equals(const Value* value) const {
50   const RawString* other = ValueCast<RawString>(value);
51   if (!other) {
52     return false;
53   }
54   return *this->value == *other->value;
55 }
56 
Clone(StringPool * new_pool) const57 RawString* RawString::Clone(StringPool* new_pool) const {
58   RawString* rs = new RawString(new_pool->MakeRef(*value));
59   rs->comment_ = comment_;
60   rs->source_ = source_;
61   return rs;
62 }
63 
Flatten(android::Res_value * out_value) const64 bool RawString::Flatten(android::Res_value* out_value) const {
65   out_value->dataType = android::Res_value::TYPE_STRING;
66   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
67   return true;
68 }
69 
Print(std::ostream * out) const70 void RawString::Print(std::ostream* out) const {
71   *out << "(raw string) " << *value;
72 }
73 
Reference()74 Reference::Reference() : reference_type(Type::kResource) {}
75 
Reference(const ResourceNameRef & n,Type t)76 Reference::Reference(const ResourceNameRef& n, Type t)
77     : name(n.ToResourceName()), reference_type(t) {}
78 
Reference(const ResourceId & i,Type type)79 Reference::Reference(const ResourceId& i, Type type)
80     : id(i), reference_type(type) {}
81 
Reference(const ResourceNameRef & n,const ResourceId & i)82 Reference::Reference(const ResourceNameRef& n, const ResourceId& i)
83     : name(n.ToResourceName()), id(i), reference_type(Type::kResource) {}
84 
Equals(const Value * value) const85 bool Reference::Equals(const Value* value) const {
86   const Reference* other = ValueCast<Reference>(value);
87   if (!other) {
88     return false;
89   }
90   return reference_type == other->reference_type &&
91          private_reference == other->private_reference && id == other->id &&
92          name == other->name;
93 }
94 
Flatten(android::Res_value * out_value) const95 bool Reference::Flatten(android::Res_value* out_value) const {
96   const ResourceId resid = id.value_or_default(ResourceId(0));
97   const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
98                        resid.package_id() != kAppPackageId;
99 
100   if (reference_type == Reference::Type::kResource) {
101     if (dynamic) {
102       out_value->dataType = android::Res_value::TYPE_DYNAMIC_REFERENCE;
103     } else {
104       out_value->dataType = android::Res_value::TYPE_REFERENCE;
105     }
106   } else {
107     if (dynamic) {
108       out_value->dataType = android::Res_value::TYPE_DYNAMIC_ATTRIBUTE;
109     } else {
110       out_value->dataType = android::Res_value::TYPE_ATTRIBUTE;
111     }
112   }
113   out_value->data = util::HostToDevice32(resid.id);
114   return true;
115 }
116 
Clone(StringPool *) const117 Reference* Reference::Clone(StringPool* /*new_pool*/) const {
118   return new Reference(*this);
119 }
120 
Print(std::ostream * out) const121 void Reference::Print(std::ostream* out) const {
122   if (reference_type == Type::kResource) {
123     *out << "(reference) @";
124     if (!name && !id) {
125       *out << "null";
126       return;
127     }
128   } else {
129     *out << "(attr-reference) ?";
130   }
131 
132   if (private_reference) {
133     *out << "*";
134   }
135 
136   if (name) {
137     *out << name.value();
138   }
139 
140   if (id && id.value().is_valid_dynamic()) {
141     if (name) {
142       *out << " ";
143     }
144     *out << id.value();
145   }
146 }
147 
Equals(const Value * value) const148 bool Id::Equals(const Value* value) const {
149   return ValueCast<Id>(value) != nullptr;
150 }
151 
Flatten(android::Res_value * out) const152 bool Id::Flatten(android::Res_value* out) const {
153   out->dataType = android::Res_value::TYPE_INT_BOOLEAN;
154   out->data = util::HostToDevice32(0);
155   return true;
156 }
157 
Clone(StringPool *) const158 Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); }
159 
Print(std::ostream * out) const160 void Id::Print(std::ostream* out) const { *out << "(id)"; }
161 
String(const StringPool::Ref & ref)162 String::String(const StringPool::Ref& ref) : value(ref) {}
163 
Equals(const Value * value) const164 bool String::Equals(const Value* value) const {
165   const String* other = ValueCast<String>(value);
166   if (!other) {
167     return false;
168   }
169 
170   if (this->value != other->value) {
171     return false;
172   }
173 
174   if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
175     return false;
176   }
177 
178   auto other_iter = other->untranslatable_sections.begin();
179   for (const UntranslatableSection& this_section : untranslatable_sections) {
180     if (this_section != *other_iter) {
181       return false;
182     }
183     ++other_iter;
184   }
185   return true;
186 }
187 
Flatten(android::Res_value * out_value) const188 bool String::Flatten(android::Res_value* out_value) const {
189   // Verify that our StringPool index is within encode-able limits.
190   if (value.index() > std::numeric_limits<uint32_t>::max()) {
191     return false;
192   }
193 
194   out_value->dataType = android::Res_value::TYPE_STRING;
195   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
196   return true;
197 }
198 
Clone(StringPool * new_pool) const199 String* String::Clone(StringPool* new_pool) const {
200   String* str = new String(new_pool->MakeRef(*value));
201   str->comment_ = comment_;
202   str->source_ = source_;
203   str->untranslatable_sections = untranslatable_sections;
204   return str;
205 }
206 
Print(std::ostream * out) const207 void String::Print(std::ostream* out) const {
208   *out << "(string) \"" << *value << "\"";
209 }
210 
StyledString(const StringPool::StyleRef & ref)211 StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {}
212 
Equals(const Value * value) const213 bool StyledString::Equals(const Value* value) const {
214   const StyledString* other = ValueCast<StyledString>(value);
215   if (!other) {
216     return false;
217   }
218 
219   if (this->value != other->value) {
220     return false;
221   }
222 
223   if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
224     return false;
225   }
226 
227   auto other_iter = other->untranslatable_sections.begin();
228   for (const UntranslatableSection& this_section : untranslatable_sections) {
229     if (this_section != *other_iter) {
230       return false;
231     }
232     ++other_iter;
233   }
234   return true;
235 }
236 
Flatten(android::Res_value * out_value) const237 bool StyledString::Flatten(android::Res_value* out_value) const {
238   if (value.index() > std::numeric_limits<uint32_t>::max()) {
239     return false;
240   }
241 
242   out_value->dataType = android::Res_value::TYPE_STRING;
243   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
244   return true;
245 }
246 
Clone(StringPool * new_pool) const247 StyledString* StyledString::Clone(StringPool* new_pool) const {
248   StyledString* str = new StyledString(new_pool->MakeRef(value));
249   str->comment_ = comment_;
250   str->source_ = source_;
251   str->untranslatable_sections = untranslatable_sections;
252   return str;
253 }
254 
Print(std::ostream * out) const255 void StyledString::Print(std::ostream* out) const {
256   *out << "(styled string) \"" << *value->str << "\"";
257   for (const StringPool::Span& span : value->spans) {
258     *out << " " << *span.name << ":" << span.first_char << ","
259          << span.last_char;
260   }
261 }
262 
FileReference(const StringPool::Ref & _path)263 FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {}
264 
Equals(const Value * value) const265 bool FileReference::Equals(const Value* value) const {
266   const FileReference* other = ValueCast<FileReference>(value);
267   if (!other) {
268     return false;
269   }
270   return path == other->path;
271 }
272 
Flatten(android::Res_value * out_value) const273 bool FileReference::Flatten(android::Res_value* out_value) const {
274   if (path.index() > std::numeric_limits<uint32_t>::max()) {
275     return false;
276   }
277 
278   out_value->dataType = android::Res_value::TYPE_STRING;
279   out_value->data = util::HostToDevice32(static_cast<uint32_t>(path.index()));
280   return true;
281 }
282 
Clone(StringPool * new_pool) const283 FileReference* FileReference::Clone(StringPool* new_pool) const {
284   FileReference* fr = new FileReference(new_pool->MakeRef(*path));
285   fr->file = file;
286   fr->comment_ = comment_;
287   fr->source_ = source_;
288   return fr;
289 }
290 
Print(std::ostream * out) const291 void FileReference::Print(std::ostream* out) const {
292   *out << "(file) " << *path;
293 }
294 
BinaryPrimitive(const android::Res_value & val)295 BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {}
296 
BinaryPrimitive(uint8_t dataType,uint32_t data)297 BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
298   value.dataType = dataType;
299   value.data = data;
300 }
301 
Equals(const Value * value) const302 bool BinaryPrimitive::Equals(const Value* value) const {
303   const BinaryPrimitive* other = ValueCast<BinaryPrimitive>(value);
304   if (!other) {
305     return false;
306   }
307   return this->value.dataType == other->value.dataType &&
308          this->value.data == other->value.data;
309 }
310 
Flatten(android::Res_value * out_value) const311 bool BinaryPrimitive::Flatten(android::Res_value* out_value) const {
312   out_value->dataType = value.dataType;
313   out_value->data = util::HostToDevice32(value.data);
314   return true;
315 }
316 
Clone(StringPool *) const317 BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
318   return new BinaryPrimitive(*this);
319 }
320 
Print(std::ostream * out) const321 void BinaryPrimitive::Print(std::ostream* out) const {
322   switch (value.dataType) {
323     case android::Res_value::TYPE_NULL:
324       if (value.data == android::Res_value::DATA_NULL_EMPTY) {
325         *out << "(empty)";
326       } else {
327         *out << "(null)";
328       }
329       break;
330     case android::Res_value::TYPE_INT_DEC:
331       *out << "(integer) " << static_cast<int32_t>(value.data);
332       break;
333     case android::Res_value::TYPE_INT_HEX:
334       *out << "(integer) 0x" << std::hex << value.data << std::dec;
335       break;
336     case android::Res_value::TYPE_INT_BOOLEAN:
337       *out << "(boolean) " << (value.data != 0 ? "true" : "false");
338       break;
339     case android::Res_value::TYPE_INT_COLOR_ARGB8:
340     case android::Res_value::TYPE_INT_COLOR_RGB8:
341     case android::Res_value::TYPE_INT_COLOR_ARGB4:
342     case android::Res_value::TYPE_INT_COLOR_RGB4:
343       *out << "(color) #" << std::hex << value.data << std::dec;
344       break;
345     default:
346       *out << "(unknown 0x" << std::hex << (int)value.dataType << ") 0x"
347            << std::hex << value.data << std::dec;
348       break;
349   }
350 }
351 
Attribute()352 Attribute::Attribute()
353     : type_mask(0u),
354       min_int(std::numeric_limits<int32_t>::min()),
355       max_int(std::numeric_limits<int32_t>::max()) {
356 }
357 
Attribute(bool w,uint32_t t)358 Attribute::Attribute(bool w, uint32_t t)
359     : type_mask(t),
360       min_int(std::numeric_limits<int32_t>::min()),
361       max_int(std::numeric_limits<int32_t>::max()) {
362   weak_ = w;
363 }
364 
operator <<(std::ostream & out,const Attribute::Symbol & s)365 std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
366   if (s.symbol.name) {
367     out << s.symbol.name.value().entry;
368   } else {
369     out << "???";
370   }
371   return out << "=" << s.value;
372 }
373 
374 template <typename T>
add_pointer(T & val)375 constexpr T* add_pointer(T& val) {
376   return &val;
377 }
378 
Equals(const Value * value) const379 bool Attribute::Equals(const Value* value) const {
380   const Attribute* other = ValueCast<Attribute>(value);
381   if (!other) {
382     return false;
383   }
384 
385   if (symbols.size() != other->symbols.size()) {
386     return false;
387   }
388 
389   if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) {
390     return false;
391   }
392 
393   std::vector<const Symbol*> sorted_a;
394   std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
395                  add_pointer<const Symbol>);
396   std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool {
397     return a->symbol.name < b->symbol.name;
398   });
399 
400   std::vector<const Symbol*> sorted_b;
401   std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b),
402                  add_pointer<const Symbol>);
403   std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool {
404     return a->symbol.name < b->symbol.name;
405   });
406 
407   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
408                     [](const Symbol* a, const Symbol* b) -> bool {
409                       return a->symbol.Equals(&b->symbol) && a->value == b->value;
410                     });
411 }
412 
Clone(StringPool *) const413 Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
414   return new Attribute(*this);
415 }
416 
PrintMask(std::ostream * out) const417 void Attribute::PrintMask(std::ostream* out) const {
418   if (type_mask == android::ResTable_map::TYPE_ANY) {
419     *out << "any";
420     return;
421   }
422 
423   bool set = false;
424   if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) {
425     if (!set) {
426       set = true;
427     } else {
428       *out << "|";
429     }
430     *out << "reference";
431   }
432 
433   if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) {
434     if (!set) {
435       set = true;
436     } else {
437       *out << "|";
438     }
439     *out << "string";
440   }
441 
442   if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) {
443     if (!set) {
444       set = true;
445     } else {
446       *out << "|";
447     }
448     *out << "integer";
449   }
450 
451   if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
452     if (!set) {
453       set = true;
454     } else {
455       *out << "|";
456     }
457     *out << "boolean";
458   }
459 
460   if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) {
461     if (!set) {
462       set = true;
463     } else {
464       *out << "|";
465     }
466     *out << "color";
467   }
468 
469   if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) {
470     if (!set) {
471       set = true;
472     } else {
473       *out << "|";
474     }
475     *out << "float";
476   }
477 
478   if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) {
479     if (!set) {
480       set = true;
481     } else {
482       *out << "|";
483     }
484     *out << "dimension";
485   }
486 
487   if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) {
488     if (!set) {
489       set = true;
490     } else {
491       *out << "|";
492     }
493     *out << "fraction";
494   }
495 
496   if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) {
497     if (!set) {
498       set = true;
499     } else {
500       *out << "|";
501     }
502     *out << "enum";
503   }
504 
505   if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) {
506     if (!set) {
507       set = true;
508     } else {
509       *out << "|";
510     }
511     *out << "flags";
512   }
513 }
514 
Print(std::ostream * out) const515 void Attribute::Print(std::ostream* out) const {
516   *out << "(attr) ";
517   PrintMask(out);
518 
519   if (!symbols.empty()) {
520     *out << " [" << util::Joiner(symbols, ", ") << "]";
521   }
522 
523   if (min_int != std::numeric_limits<int32_t>::min()) {
524     *out << " min=" << min_int;
525   }
526 
527   if (max_int != std::numeric_limits<int32_t>::max()) {
528     *out << " max=" << max_int;
529   }
530 
531   if (IsWeak()) {
532     *out << " [weak]";
533   }
534 }
535 
BuildAttributeMismatchMessage(DiagMessage * msg,const Attribute * attr,const Item * value)536 static void BuildAttributeMismatchMessage(DiagMessage* msg,
537                                           const Attribute* attr,
538                                           const Item* value) {
539   *msg << "expected";
540   if (attr->type_mask & android::ResTable_map::TYPE_BOOLEAN) {
541     *msg << " boolean";
542   }
543 
544   if (attr->type_mask & android::ResTable_map::TYPE_COLOR) {
545     *msg << " color";
546   }
547 
548   if (attr->type_mask & android::ResTable_map::TYPE_DIMENSION) {
549     *msg << " dimension";
550   }
551 
552   if (attr->type_mask & android::ResTable_map::TYPE_ENUM) {
553     *msg << " enum";
554   }
555 
556   if (attr->type_mask & android::ResTable_map::TYPE_FLAGS) {
557     *msg << " flags";
558   }
559 
560   if (attr->type_mask & android::ResTable_map::TYPE_FLOAT) {
561     *msg << " float";
562   }
563 
564   if (attr->type_mask & android::ResTable_map::TYPE_FRACTION) {
565     *msg << " fraction";
566   }
567 
568   if (attr->type_mask & android::ResTable_map::TYPE_INTEGER) {
569     *msg << " integer";
570   }
571 
572   if (attr->type_mask & android::ResTable_map::TYPE_REFERENCE) {
573     *msg << " reference";
574   }
575 
576   if (attr->type_mask & android::ResTable_map::TYPE_STRING) {
577     *msg << " string";
578   }
579 
580   *msg << " but got " << *value;
581 }
582 
Matches(const Item * item,DiagMessage * out_msg) const583 bool Attribute::Matches(const Item* item, DiagMessage* out_msg) const {
584   android::Res_value val = {};
585   item->Flatten(&val);
586 
587   // Always allow references.
588   const uint32_t mask = type_mask | android::ResTable_map::TYPE_REFERENCE;
589   if (!(mask & ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType))) {
590     if (out_msg) {
591       BuildAttributeMismatchMessage(out_msg, this, item);
592     }
593     return false;
594 
595   } else if (ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType) &
596              android::ResTable_map::TYPE_INTEGER) {
597     if (static_cast<int32_t>(util::DeviceToHost32(val.data)) < min_int) {
598       if (out_msg) {
599         *out_msg << *item << " is less than minimum integer " << min_int;
600       }
601       return false;
602     } else if (static_cast<int32_t>(util::DeviceToHost32(val.data)) > max_int) {
603       if (out_msg) {
604         *out_msg << *item << " is greater than maximum integer " << max_int;
605       }
606       return false;
607     }
608   }
609   return true;
610 }
611 
operator <<(std::ostream & out,const Style::Entry & entry)612 std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) {
613   if (entry.key.name) {
614     out << entry.key.name.value();
615   } else if (entry.key.id) {
616     out << entry.key.id.value();
617   } else {
618     out << "???";
619   }
620   out << " = " << entry.value;
621   return out;
622 }
623 
624 template <typename T>
ToPointerVec(std::vector<T> & src)625 std::vector<T*> ToPointerVec(std::vector<T>& src) {
626   std::vector<T*> dst;
627   dst.reserve(src.size());
628   for (T& in : src) {
629     dst.push_back(&in);
630   }
631   return dst;
632 }
633 
634 template <typename T>
ToPointerVec(const std::vector<T> & src)635 std::vector<const T*> ToPointerVec(const std::vector<T>& src) {
636   std::vector<const T*> dst;
637   dst.reserve(src.size());
638   for (const T& in : src) {
639     dst.push_back(&in);
640   }
641   return dst;
642 }
643 
KeyNameComparator(const Style::Entry * a,const Style::Entry * b)644 static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) {
645   return a->key.name < b->key.name;
646 }
647 
Equals(const Value * value) const648 bool Style::Equals(const Value* value) const {
649   const Style* other = ValueCast<Style>(value);
650   if (!other) {
651     return false;
652   }
653 
654   if (bool(parent) != bool(other->parent) ||
655       (parent && other->parent && !parent.value().Equals(&other->parent.value()))) {
656     return false;
657   }
658 
659   if (entries.size() != other->entries.size()) {
660     return false;
661   }
662 
663   std::vector<const Entry*> sorted_a = ToPointerVec(entries);
664   std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator);
665 
666   std::vector<const Entry*> sorted_b = ToPointerVec(other->entries);
667   std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator);
668 
669   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
670                     [](const Entry* a, const Entry* b) -> bool {
671                       return a->key.Equals(&b->key) && a->value->Equals(b->value.get());
672                     });
673 }
674 
Clone(StringPool * new_pool) const675 Style* Style::Clone(StringPool* new_pool) const {
676   Style* style = new Style();
677   style->parent = parent;
678   style->parent_inferred = parent_inferred;
679   style->comment_ = comment_;
680   style->source_ = source_;
681   for (auto& entry : entries) {
682     style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
683   }
684   return style;
685 }
686 
Print(std::ostream * out) const687 void Style::Print(std::ostream* out) const {
688   *out << "(style) ";
689   if (parent && parent.value().name) {
690     const Reference& parent_ref = parent.value();
691     if (parent_ref.private_reference) {
692       *out << "*";
693     }
694     *out << parent_ref.name.value();
695   }
696   *out << " [" << util::Joiner(entries, ", ") << "]";
697 }
698 
CloneEntry(const Style::Entry & entry,StringPool * pool)699 Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
700   Style::Entry cloned_entry{entry.key};
701   if (entry.value != nullptr) {
702     cloned_entry.value.reset(entry.value->Clone(pool));
703   }
704   return cloned_entry;
705 }
706 
MergeWith(Style * other,StringPool * pool)707 void Style::MergeWith(Style* other, StringPool* pool) {
708   if (other->parent) {
709     parent = other->parent;
710   }
711 
712   // We can't assume that the entries are sorted alphabetically since they're supposed to be
713   // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge
714   // them keying off that.
715   //
716   // Instead, sort the entries of each Style by their name in a separate structure. Then merge
717   // those.
718 
719   std::vector<Entry*> this_sorted = ToPointerVec(entries);
720   std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator);
721 
722   std::vector<Entry*> other_sorted = ToPointerVec(other->entries);
723   std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator);
724 
725   auto this_iter = this_sorted.begin();
726   const auto this_end = this_sorted.end();
727 
728   auto other_iter = other_sorted.begin();
729   const auto other_end = other_sorted.end();
730 
731   std::vector<Entry> merged_entries;
732   while (this_iter != this_end) {
733     if (other_iter != other_end) {
734       if ((*this_iter)->key.name < (*other_iter)->key.name) {
735         merged_entries.push_back(std::move(**this_iter));
736         ++this_iter;
737       } else {
738         // The other overrides.
739         merged_entries.push_back(CloneEntry(**other_iter, pool));
740         if ((*this_iter)->key.name == (*other_iter)->key.name) {
741           ++this_iter;
742         }
743         ++other_iter;
744       }
745     } else {
746       merged_entries.push_back(std::move(**this_iter));
747       ++this_iter;
748     }
749   }
750 
751   while (other_iter != other_end) {
752     merged_entries.push_back(CloneEntry(**other_iter, pool));
753     ++other_iter;
754   }
755 
756   entries = std::move(merged_entries);
757 }
758 
Equals(const Value * value) const759 bool Array::Equals(const Value* value) const {
760   const Array* other = ValueCast<Array>(value);
761   if (!other) {
762     return false;
763   }
764 
765   if (items.size() != other->items.size()) {
766     return false;
767   }
768 
769   return std::equal(items.begin(), items.end(), other->items.begin(),
770                     [](const std::unique_ptr<Item>& a,
771                        const std::unique_ptr<Item>& b) -> bool {
772                       return a->Equals(b.get());
773                     });
774 }
775 
Clone(StringPool * new_pool) const776 Array* Array::Clone(StringPool* new_pool) const {
777   Array* array = new Array();
778   array->comment_ = comment_;
779   array->source_ = source_;
780   for (auto& item : items) {
781     array->items.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
782   }
783   return array;
784 }
785 
Print(std::ostream * out) const786 void Array::Print(std::ostream* out) const {
787   *out << "(array) [" << util::Joiner(items, ", ") << "]";
788 }
789 
Equals(const Value * value) const790 bool Plural::Equals(const Value* value) const {
791   const Plural* other = ValueCast<Plural>(value);
792   if (!other) {
793     return false;
794   }
795 
796   auto one_iter = values.begin();
797   auto one_end_iter = values.end();
798   auto two_iter = other->values.begin();
799   for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
800     const std::unique_ptr<Item>& a = *one_iter;
801     const std::unique_ptr<Item>& b = *two_iter;
802     if (a != nullptr && b != nullptr) {
803       if (!a->Equals(b.get())) {
804         return false;
805       }
806     } else if (a != b) {
807       return false;
808     }
809   }
810   return true;
811 }
812 
Clone(StringPool * new_pool) const813 Plural* Plural::Clone(StringPool* new_pool) const {
814   Plural* p = new Plural();
815   p->comment_ = comment_;
816   p->source_ = source_;
817   const size_t count = values.size();
818   for (size_t i = 0; i < count; i++) {
819     if (values[i]) {
820       p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool));
821     }
822   }
823   return p;
824 }
825 
Print(std::ostream * out) const826 void Plural::Print(std::ostream* out) const {
827   *out << "(plural)";
828   if (values[Zero]) {
829     *out << " zero=" << *values[Zero];
830   }
831 
832   if (values[One]) {
833     *out << " one=" << *values[One];
834   }
835 
836   if (values[Two]) {
837     *out << " two=" << *values[Two];
838   }
839 
840   if (values[Few]) {
841     *out << " few=" << *values[Few];
842   }
843 
844   if (values[Many]) {
845     *out << " many=" << *values[Many];
846   }
847 
848   if (values[Other]) {
849     *out << " other=" << *values[Other];
850   }
851 }
852 
Equals(const Value * value) const853 bool Styleable::Equals(const Value* value) const {
854   const Styleable* other = ValueCast<Styleable>(value);
855   if (!other) {
856     return false;
857   }
858 
859   if (entries.size() != other->entries.size()) {
860     return false;
861   }
862 
863   return std::equal(entries.begin(), entries.end(), other->entries.begin(),
864                     [](const Reference& a, const Reference& b) -> bool {
865                       return a.Equals(&b);
866                     });
867 }
868 
Clone(StringPool *) const869 Styleable* Styleable::Clone(StringPool* /*new_pool*/) const {
870   return new Styleable(*this);
871 }
872 
Print(std::ostream * out) const873 void Styleable::Print(std::ostream* out) const {
874   *out << "(styleable) "
875        << " [" << util::Joiner(entries, ", ") << "]";
876 }
877 
operator <(const Reference & a,const Reference & b)878 bool operator<(const Reference& a, const Reference& b) {
879   int cmp = a.name.value_or_default({}).compare(b.name.value_or_default({}));
880   if (cmp != 0) return cmp < 0;
881   return a.id < b.id;
882 }
883 
operator ==(const Reference & a,const Reference & b)884 bool operator==(const Reference& a, const Reference& b) {
885   return a.name == b.name && a.id == b.id;
886 }
887 
operator !=(const Reference & a,const Reference & b)888 bool operator!=(const Reference& a, const Reference& b) {
889   return a.name != b.name || a.id != b.id;
890 }
891 
892 struct NameOnlyComparator {
operator ()aapt::NameOnlyComparator893   bool operator()(const Reference& a, const Reference& b) const {
894     return a.name < b.name;
895   }
896 };
897 
MergeWith(Styleable * other)898 void Styleable::MergeWith(Styleable* other) {
899   // Compare only names, because some References may already have their IDs
900   // assigned (framework IDs that don't change).
901   std::set<Reference, NameOnlyComparator> references;
902   references.insert(entries.begin(), entries.end());
903   references.insert(other->entries.begin(), other->entries.end());
904   entries.clear();
905   entries.reserve(references.size());
906   entries.insert(entries.end(), references.begin(), references.end());
907 }
908 
909 }  // namespace aapt
910