• Home
  • 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 <cinttypes>
21 #include <limits>
22 #include <set>
23 #include <sstream>
24 
25 #include "android-base/stringprintf.h"
26 #include "androidfw/ResourceTypes.h"
27 
28 #include "Resource.h"
29 #include "ResourceUtils.h"
30 #include "ValueVisitor.h"
31 #include "util/Util.h"
32 
33 using ::aapt::text::Printer;
34 using ::android::StringPiece;
35 using ::android::base::StringPrintf;
36 
37 namespace aapt {
38 
PrettyPrint(Printer * printer) const39 void Value::PrettyPrint(Printer* printer) const {
40   std::ostringstream str_stream;
41   Print(&str_stream);
42   printer->Print(str_stream.str());
43 }
44 
operator <<(std::ostream & out,const Value & value)45 std::ostream& operator<<(std::ostream& out, const Value& value) {
46   value.Print(&out);
47   return out;
48 }
49 
Transform(ValueTransformer & transformer) const50 std::unique_ptr<Value> Value::Transform(ValueTransformer& transformer) const {
51   return std::unique_ptr<Value>(this->TransformValueImpl(transformer));
52 }
53 
Transform(ValueTransformer & transformer) const54 std::unique_ptr<Item> Item::Transform(ValueTransformer& transformer) const {
55   return std::unique_ptr<Item>(this->TransformItemImpl(transformer));
56 }
57 
58 template <typename Derived>
Accept(ValueVisitor * visitor)59 void BaseValue<Derived>::Accept(ValueVisitor* visitor) {
60   visitor->Visit(static_cast<Derived*>(this));
61 }
62 
63 template <typename Derived>
Accept(ConstValueVisitor * visitor) const64 void BaseValue<Derived>::Accept(ConstValueVisitor* visitor) const {
65   visitor->Visit(static_cast<const Derived*>(this));
66 }
67 
68 template <typename Derived>
Accept(ValueVisitor * visitor)69 void BaseItem<Derived>::Accept(ValueVisitor* visitor) {
70   visitor->Visit(static_cast<Derived*>(this));
71 }
72 
73 template <typename Derived>
Accept(ConstValueVisitor * visitor) const74 void BaseItem<Derived>::Accept(ConstValueVisitor* visitor) const {
75   visitor->Visit(static_cast<const Derived*>(this));
76 }
77 
RawString(const StringPool::Ref & ref)78 RawString::RawString(const StringPool::Ref& ref) : value(ref) {}
79 
Equals(const Value * value) const80 bool RawString::Equals(const Value* value) const {
81   const RawString* other = ValueCast<RawString>(value);
82   if (!other) {
83     return false;
84   }
85   return *this->value == *other->value;
86 }
87 
Flatten(android::Res_value * out_value) const88 bool RawString::Flatten(android::Res_value* out_value) const {
89   out_value->dataType = android::Res_value::TYPE_STRING;
90   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
91   return true;
92 }
93 
Print(std::ostream * out) const94 void RawString::Print(std::ostream* out) const {
95   *out << "(raw string) " << *value;
96 }
97 
Reference()98 Reference::Reference() : reference_type(Type::kResource) {}
99 
Reference(const ResourceNameRef & n,Type t)100 Reference::Reference(const ResourceNameRef& n, Type t)
101     : name(n.ToResourceName()), reference_type(t) {}
102 
Reference(const ResourceId & i,Type type)103 Reference::Reference(const ResourceId& i, Type type)
104     : id(i), reference_type(type) {}
105 
Reference(const ResourceNameRef & n,const ResourceId & i)106 Reference::Reference(const ResourceNameRef& n, const ResourceId& i)
107     : name(n.ToResourceName()), id(i), reference_type(Type::kResource) {}
108 
Equals(const Value * value) const109 bool Reference::Equals(const Value* value) const {
110   const Reference* other = ValueCast<Reference>(value);
111   if (!other) {
112     return false;
113   }
114   return reference_type == other->reference_type && private_reference == other->private_reference &&
115          id == other->id && name == other->name && type_flags == other->type_flags;
116 }
117 
Flatten(android::Res_value * out_value) const118 bool Reference::Flatten(android::Res_value* out_value) const {
119   if (name && name.value().type.type == ResourceType::kMacro) {
120     return false;
121   }
122 
123   const ResourceId resid = id.value_or(ResourceId(0));
124   const bool dynamic = resid.is_valid() && is_dynamic;
125 
126   if (reference_type == Reference::Type::kResource) {
127     if (dynamic) {
128       out_value->dataType = android::Res_value::TYPE_DYNAMIC_REFERENCE;
129     } else {
130       out_value->dataType = android::Res_value::TYPE_REFERENCE;
131     }
132   } else {
133     if (dynamic) {
134       out_value->dataType = android::Res_value::TYPE_DYNAMIC_ATTRIBUTE;
135     } else {
136       out_value->dataType = android::Res_value::TYPE_ATTRIBUTE;
137     }
138   }
139   out_value->data = util::HostToDevice32(resid.id);
140   return true;
141 }
142 
Print(std::ostream * out) const143 void Reference::Print(std::ostream* out) const {
144   if (reference_type == Type::kResource) {
145     *out << "(reference) @";
146     if (!name && !id) {
147       *out << "null";
148       return;
149     }
150   } else {
151     *out << "(attr-reference) ?";
152   }
153 
154   if (private_reference) {
155     *out << "*";
156   }
157 
158   if (name) {
159     *out << name.value();
160   }
161 
162   if (id && id.value().is_valid()) {
163     if (name) {
164       *out << " ";
165     }
166     *out << id.value();
167   }
168 }
169 
PrettyPrintReferenceImpl(const Reference & ref,bool print_package,Printer * printer)170 static void PrettyPrintReferenceImpl(const Reference& ref, bool print_package, Printer* printer) {
171   switch (ref.reference_type) {
172     case Reference::Type::kResource:
173       printer->Print("@");
174       break;
175 
176     case Reference::Type::kAttribute:
177       printer->Print("?");
178       break;
179   }
180 
181   if (!ref.name && !ref.id) {
182     printer->Print("null");
183     return;
184   }
185 
186   if (ref.private_reference) {
187     printer->Print("*");
188   }
189 
190   if (ref.name) {
191     const ResourceName& name = ref.name.value();
192     if (print_package) {
193       printer->Print(name.to_string());
194     } else {
195       printer->Print(name.type.to_string());
196       printer->Print("/");
197       printer->Print(name.entry);
198     }
199   } else if (ref.id && ref.id.value().is_valid()) {
200     printer->Print(ref.id.value().to_string());
201   }
202 }
203 
PrettyPrint(Printer * printer) const204 void Reference::PrettyPrint(Printer* printer) const {
205   PrettyPrintReferenceImpl(*this, true /*print_package*/, printer);
206 }
207 
PrettyPrint(const StringPiece & package,Printer * printer) const208 void Reference::PrettyPrint(const StringPiece& package, Printer* printer) const {
209   const bool print_package = name ? package != name.value().package : true;
210   PrettyPrintReferenceImpl(*this, print_package, printer);
211 }
212 
Equals(const Value * value) const213 bool Id::Equals(const Value* value) const {
214   return ValueCast<Id>(value) != nullptr;
215 }
216 
Flatten(android::Res_value * out) const217 bool Id::Flatten(android::Res_value* out) const {
218   out->dataType = android::Res_value::TYPE_INT_BOOLEAN;
219   out->data = util::HostToDevice32(0);
220   return true;
221 }
222 
Print(std::ostream * out) const223 void Id::Print(std::ostream* out) const {
224   *out << "(id)";
225 }
226 
String(const StringPool::Ref & ref)227 String::String(const StringPool::Ref& ref) : value(ref) {
228 }
229 
Equals(const Value * value) const230 bool String::Equals(const Value* value) const {
231   const String* other = ValueCast<String>(value);
232   if (!other) {
233     return false;
234   }
235 
236   if (this->value != other->value) {
237     return false;
238   }
239 
240   if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
241     return false;
242   }
243 
244   auto other_iter = other->untranslatable_sections.begin();
245   for (const UntranslatableSection& this_section : untranslatable_sections) {
246     if (this_section != *other_iter) {
247       return false;
248     }
249     ++other_iter;
250   }
251   return true;
252 }
253 
Flatten(android::Res_value * out_value) const254 bool String::Flatten(android::Res_value* out_value) const {
255   // Verify that our StringPool index is within encode-able limits.
256   if (value.index() > std::numeric_limits<uint32_t>::max()) {
257     return false;
258   }
259 
260   out_value->dataType = android::Res_value::TYPE_STRING;
261   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
262   return true;
263 }
264 
Print(std::ostream * out) const265 void String::Print(std::ostream* out) const {
266   *out << "(string) \"" << *value << "\"";
267 }
268 
PrettyPrint(Printer * printer) const269 void String::PrettyPrint(Printer* printer) const {
270   printer->Print("\"");
271   printer->Print(*value);
272   printer->Print("\"");
273 }
274 
StyledString(const StringPool::StyleRef & ref)275 StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {
276 }
277 
Equals(const Value * value) const278 bool StyledString::Equals(const Value* value) const {
279   const StyledString* other = ValueCast<StyledString>(value);
280   if (!other) {
281     return false;
282   }
283 
284   if (this->value != other->value) {
285     return false;
286   }
287 
288   if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
289     return false;
290   }
291 
292   auto other_iter = other->untranslatable_sections.begin();
293   for (const UntranslatableSection& this_section : untranslatable_sections) {
294     if (this_section != *other_iter) {
295       return false;
296     }
297     ++other_iter;
298   }
299   return true;
300 }
301 
Flatten(android::Res_value * out_value) const302 bool StyledString::Flatten(android::Res_value* out_value) const {
303   if (value.index() > std::numeric_limits<uint32_t>::max()) {
304     return false;
305   }
306 
307   out_value->dataType = android::Res_value::TYPE_STRING;
308   out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
309   return true;
310 }
311 
Print(std::ostream * out) const312 void StyledString::Print(std::ostream* out) const {
313   *out << "(styled string) \"" << value->value << "\"";
314   for (const StringPool::Span& span : value->spans) {
315     *out << " " << *span.name << ":" << span.first_char << "," << span.last_char;
316   }
317 }
318 
FileReference(const StringPool::Ref & _path)319 FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {
320 }
321 
Equals(const Value * value) const322 bool FileReference::Equals(const Value* value) const {
323   const FileReference* other = ValueCast<FileReference>(value);
324   if (!other) {
325     return false;
326   }
327   return path == other->path;
328 }
329 
Flatten(android::Res_value * out_value) const330 bool FileReference::Flatten(android::Res_value* out_value) const {
331   if (path.index() > std::numeric_limits<uint32_t>::max()) {
332     return false;
333   }
334 
335   out_value->dataType = android::Res_value::TYPE_STRING;
336   out_value->data = util::HostToDevice32(static_cast<uint32_t>(path.index()));
337   return true;
338 }
339 
Print(std::ostream * out) const340 void FileReference::Print(std::ostream* out) const {
341   *out << "(file) " << *path;
342   switch (type) {
343     case ResourceFile::Type::kBinaryXml:
344       *out << " type=XML";
345       break;
346     case ResourceFile::Type::kProtoXml:
347       *out << " type=protoXML";
348       break;
349     case ResourceFile::Type::kPng:
350       *out << " type=PNG";
351       break;
352     default:
353       break;
354   }
355 }
356 
BinaryPrimitive(const android::Res_value & val)357 BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
358 }
359 
BinaryPrimitive(uint8_t dataType,uint32_t data)360 BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
361   value.dataType = dataType;
362   value.data = data;
363 }
364 
Equals(const Value * value) const365 bool BinaryPrimitive::Equals(const Value* value) const {
366   const BinaryPrimitive* other = ValueCast<BinaryPrimitive>(value);
367   if (!other) {
368     return false;
369   }
370   return this->value.dataType == other->value.dataType &&
371          this->value.data == other->value.data;
372 }
373 
Flatten(::android::Res_value * out_value) const374 bool BinaryPrimitive::Flatten(::android::Res_value* out_value) const {
375   out_value->dataType = value.dataType;
376   out_value->data = util::HostToDevice32(value.data);
377   return true;
378 }
379 
Print(std::ostream * out) const380 void BinaryPrimitive::Print(std::ostream* out) const {
381   *out << StringPrintf("(primitive) type=0x%02x data=0x%08x", value.dataType, value.data);
382 }
383 
ComplexToString(uint32_t complex_value,bool fraction)384 static std::string ComplexToString(uint32_t complex_value, bool fraction) {
385   using ::android::Res_value;
386 
387   constexpr std::array<int, 4> kRadixShifts = {{23, 16, 8, 0}};
388 
389   // Determine the radix that was used.
390   const uint32_t radix =
391       (complex_value >> Res_value::COMPLEX_RADIX_SHIFT) & Res_value::COMPLEX_RADIX_MASK;
392   const uint64_t mantissa = uint64_t{(complex_value >> Res_value::COMPLEX_MANTISSA_SHIFT) &
393                                      Res_value::COMPLEX_MANTISSA_MASK}
394                             << kRadixShifts[radix];
395   const float value = mantissa * (1.0f / (1 << 23));
396 
397   std::string str = StringPrintf("%f", value);
398 
399   const int unit_type =
400       (complex_value >> Res_value::COMPLEX_UNIT_SHIFT) & Res_value::COMPLEX_UNIT_MASK;
401   if (fraction) {
402     switch (unit_type) {
403       case Res_value::COMPLEX_UNIT_FRACTION:
404         str += "%";
405         break;
406       case Res_value::COMPLEX_UNIT_FRACTION_PARENT:
407         str += "%p";
408         break;
409       default:
410         str += "???";
411         break;
412     }
413   } else {
414     switch (unit_type) {
415       case Res_value::COMPLEX_UNIT_PX:
416         str += "px";
417         break;
418       case Res_value::COMPLEX_UNIT_DIP:
419         str += "dp";
420         break;
421       case Res_value::COMPLEX_UNIT_SP:
422         str += "sp";
423         break;
424       case Res_value::COMPLEX_UNIT_PT:
425         str += "pt";
426         break;
427       case Res_value::COMPLEX_UNIT_IN:
428         str += "in";
429         break;
430       case Res_value::COMPLEX_UNIT_MM:
431         str += "mm";
432         break;
433       default:
434         str += "???";
435         break;
436     }
437   }
438   return str;
439 }
440 
PrettyPrint(Printer * printer) const441 void BinaryPrimitive::PrettyPrint(Printer* printer) const {
442   using ::android::Res_value;
443   switch (value.dataType) {
444     case Res_value::TYPE_NULL:
445       if (value.data == Res_value::DATA_NULL_EMPTY) {
446         printer->Print("@empty");
447       } else {
448         printer->Print("@null");
449       }
450       break;
451 
452     case Res_value::TYPE_INT_DEC:
453       printer->Print(StringPrintf("%" PRIi32, static_cast<int32_t>(value.data)));
454       break;
455 
456     case Res_value::TYPE_INT_HEX:
457       printer->Print(StringPrintf("0x%08x", value.data));
458       break;
459 
460     case Res_value::TYPE_INT_BOOLEAN:
461       printer->Print(value.data != 0 ? "true" : "false");
462       break;
463 
464     case Res_value::TYPE_INT_COLOR_ARGB8:
465     case Res_value::TYPE_INT_COLOR_RGB8:
466     case Res_value::TYPE_INT_COLOR_ARGB4:
467     case Res_value::TYPE_INT_COLOR_RGB4:
468       printer->Print(StringPrintf("#%08x", value.data));
469       break;
470 
471     case Res_value::TYPE_FLOAT:
472       printer->Print(StringPrintf("%g", *reinterpret_cast<const float*>(&value.data)));
473       break;
474 
475     case Res_value::TYPE_DIMENSION:
476       printer->Print(ComplexToString(value.data, false /*fraction*/));
477       break;
478 
479     case Res_value::TYPE_FRACTION:
480       printer->Print(ComplexToString(value.data, true /*fraction*/));
481       break;
482 
483     default:
484       printer->Print(StringPrintf("(unknown 0x%02x) 0x%08x", value.dataType, value.data));
485       break;
486   }
487 }
488 
Attribute(uint32_t t)489 Attribute::Attribute(uint32_t t)
490     : type_mask(t),
491       min_int(std::numeric_limits<int32_t>::min()),
492       max_int(std::numeric_limits<int32_t>::max()) {
493 }
494 
operator <<(std::ostream & out,const Attribute::Symbol & s)495 std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
496   if (s.symbol.name) {
497     out << s.symbol.name.value().entry;
498   } else {
499     out << "???";
500   }
501   return out << "=" << s.value;
502 }
503 
504 template <typename T>
add_pointer(T & val)505 constexpr T* add_pointer(T& val) {
506   return &val;
507 }
508 
Equals(const Value * value) const509 bool Attribute::Equals(const Value* value) const {
510   const Attribute* other = ValueCast<Attribute>(value);
511   if (!other) {
512     return false;
513   }
514 
515   if (symbols.size() != other->symbols.size()) {
516     return false;
517   }
518 
519   if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) {
520     return false;
521   }
522 
523   std::vector<const Symbol*> sorted_a;
524   std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
525                  add_pointer<const Symbol>);
526   std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool {
527     return a->symbol.name < b->symbol.name;
528   });
529 
530   std::vector<const Symbol*> sorted_b;
531   std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b),
532                  add_pointer<const Symbol>);
533   std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool {
534     return a->symbol.name < b->symbol.name;
535   });
536 
537   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
538                     [](const Symbol* a, const Symbol* b) -> bool {
539                       return a->symbol.Equals(&b->symbol) && a->value == b->value;
540                     });
541 }
542 
IsCompatibleWith(const Attribute & attr) const543 bool Attribute::IsCompatibleWith(const Attribute& attr) const {
544   // If the high bits are set on any of these attribute type masks, then they are incompatible.
545   // We don't check that flags and enums are identical.
546   if ((type_mask & ~android::ResTable_map::TYPE_ANY) != 0 ||
547       (attr.type_mask & ~android::ResTable_map::TYPE_ANY) != 0) {
548     return false;
549   }
550 
551   // Every attribute accepts a reference.
552   uint32_t this_type_mask = type_mask | android::ResTable_map::TYPE_REFERENCE;
553   uint32_t that_type_mask = attr.type_mask | android::ResTable_map::TYPE_REFERENCE;
554   return this_type_mask == that_type_mask;
555 }
556 
MaskString(uint32_t type_mask)557 std::string Attribute::MaskString(uint32_t type_mask) {
558   if (type_mask == android::ResTable_map::TYPE_ANY) {
559     return "any";
560   }
561 
562   std::ostringstream out;
563   bool set = false;
564   if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) {
565     if (!set) {
566       set = true;
567     } else {
568       out << "|";
569     }
570     out << "reference";
571   }
572 
573   if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) {
574     if (!set) {
575       set = true;
576     } else {
577       out << "|";
578     }
579     out << "string";
580   }
581 
582   if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) {
583     if (!set) {
584       set = true;
585     } else {
586       out << "|";
587     }
588     out << "integer";
589   }
590 
591   if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
592     if (!set) {
593       set = true;
594     } else {
595       out << "|";
596     }
597     out << "boolean";
598   }
599 
600   if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) {
601     if (!set) {
602       set = true;
603     } else {
604       out << "|";
605     }
606     out << "color";
607   }
608 
609   if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) {
610     if (!set) {
611       set = true;
612     } else {
613       out << "|";
614     }
615     out << "float";
616   }
617 
618   if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) {
619     if (!set) {
620       set = true;
621     } else {
622       out << "|";
623     }
624     out << "dimension";
625   }
626 
627   if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) {
628     if (!set) {
629       set = true;
630     } else {
631       out << "|";
632     }
633     out << "fraction";
634   }
635 
636   if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) {
637     if (!set) {
638       set = true;
639     } else {
640       out << "|";
641     }
642     out << "enum";
643   }
644 
645   if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) {
646     if (!set) {
647       set = true;
648     } else {
649       out << "|";
650     }
651     out << "flags";
652   }
653   return out.str();
654 }
655 
MaskString() const656 std::string Attribute::MaskString() const {
657   return MaskString(type_mask);
658 }
659 
Print(std::ostream * out) const660 void Attribute::Print(std::ostream* out) const {
661   *out << "(attr) " << MaskString();
662 
663   if (!symbols.empty()) {
664     *out << " [" << util::Joiner(symbols, ", ") << "]";
665   }
666 
667   if (min_int != std::numeric_limits<int32_t>::min()) {
668     *out << " min=" << min_int;
669   }
670 
671   if (max_int != std::numeric_limits<int32_t>::max()) {
672     *out << " max=" << max_int;
673   }
674 
675   if (IsWeak()) {
676     *out << " [weak]";
677   }
678 }
679 
BuildAttributeMismatchMessage(const Attribute & attr,const Item & value,DiagMessage * out_msg)680 static void BuildAttributeMismatchMessage(const Attribute& attr, const Item& value,
681                                           DiagMessage* out_msg) {
682   *out_msg << "expected";
683   if (attr.type_mask & android::ResTable_map::TYPE_BOOLEAN) {
684     *out_msg << " boolean";
685   }
686 
687   if (attr.type_mask & android::ResTable_map::TYPE_COLOR) {
688     *out_msg << " color";
689   }
690 
691   if (attr.type_mask & android::ResTable_map::TYPE_DIMENSION) {
692     *out_msg << " dimension";
693   }
694 
695   if (attr.type_mask & android::ResTable_map::TYPE_ENUM) {
696     *out_msg << " enum";
697   }
698 
699   if (attr.type_mask & android::ResTable_map::TYPE_FLAGS) {
700     *out_msg << " flags";
701   }
702 
703   if (attr.type_mask & android::ResTable_map::TYPE_FLOAT) {
704     *out_msg << " float";
705   }
706 
707   if (attr.type_mask & android::ResTable_map::TYPE_FRACTION) {
708     *out_msg << " fraction";
709   }
710 
711   if (attr.type_mask & android::ResTable_map::TYPE_INTEGER) {
712     *out_msg << " integer";
713   }
714 
715   if (attr.type_mask & android::ResTable_map::TYPE_REFERENCE) {
716     *out_msg << " reference";
717   }
718 
719   if (attr.type_mask & android::ResTable_map::TYPE_STRING) {
720     *out_msg << " string";
721   }
722 
723   *out_msg << " but got " << value;
724 }
725 
Matches(const Item & item,DiagMessage * out_msg) const726 bool Attribute::Matches(const Item& item, DiagMessage* out_msg) const {
727   constexpr const uint32_t TYPE_ENUM = android::ResTable_map::TYPE_ENUM;
728   constexpr const uint32_t TYPE_FLAGS = android::ResTable_map::TYPE_FLAGS;
729   constexpr const uint32_t TYPE_INTEGER = android::ResTable_map::TYPE_INTEGER;
730   constexpr const uint32_t TYPE_REFERENCE = android::ResTable_map::TYPE_REFERENCE;
731 
732   android::Res_value val = {};
733   item.Flatten(&val);
734 
735   const uint32_t flattened_data = util::DeviceToHost32(val.data);
736 
737   // Always allow references.
738   const uint32_t actual_type = ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType);
739 
740   // Only one type must match between the actual and expected.
741   if ((actual_type & (type_mask | TYPE_REFERENCE)) == 0) {
742     if (out_msg) {
743       BuildAttributeMismatchMessage(*this, item, out_msg);
744     }
745     return false;
746   }
747 
748   // Enums and flags are encoded as integers, so check them first before doing any range checks.
749   if ((type_mask & TYPE_ENUM) != 0 && (actual_type & TYPE_ENUM) != 0) {
750     for (const Symbol& s : symbols) {
751       if (flattened_data == s.value) {
752         return true;
753       }
754     }
755 
756     // If the attribute accepts integers, we can't fail here.
757     if ((type_mask & TYPE_INTEGER) == 0) {
758       if (out_msg) {
759         *out_msg << item << " is not a valid enum";
760       }
761       return false;
762     }
763   }
764 
765   if ((type_mask & TYPE_FLAGS) != 0 && (actual_type & TYPE_FLAGS) != 0) {
766     uint32_t mask = 0u;
767     for (const Symbol& s : symbols) {
768       mask |= s.value;
769     }
770 
771     // Check if the flattened data is covered by the flag bit mask.
772     // If the attribute accepts integers, we can't fail here.
773     if ((mask & flattened_data) == flattened_data) {
774       return true;
775     } else if ((type_mask & TYPE_INTEGER) == 0) {
776       if (out_msg) {
777         *out_msg << item << " is not a valid flag";
778       }
779       return false;
780     }
781   }
782 
783   // Finally check the integer range of the value.
784   if ((type_mask & TYPE_INTEGER) != 0 && (actual_type & TYPE_INTEGER) != 0) {
785     if (static_cast<int32_t>(flattened_data) < min_int) {
786       if (out_msg) {
787         *out_msg << item << " is less than minimum integer " << min_int;
788       }
789       return false;
790     } else if (static_cast<int32_t>(flattened_data) > max_int) {
791       if (out_msg) {
792         *out_msg << item << " is greater than maximum integer " << max_int;
793       }
794       return false;
795     }
796   }
797   return true;
798 }
799 
operator <<(std::ostream & out,const Style::Entry & entry)800 std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) {
801   if (entry.key.name) {
802     out << entry.key.name.value();
803   } else if (entry.key.id) {
804     out << entry.key.id.value();
805   } else {
806     out << "???";
807   }
808   out << " = " << entry.value;
809   return out;
810 }
811 
812 template <typename T>
ToPointerVec(std::vector<T> & src)813 std::vector<T*> ToPointerVec(std::vector<T>& src) {
814   std::vector<T*> dst;
815   dst.reserve(src.size());
816   for (T& in : src) {
817     dst.push_back(&in);
818   }
819   return dst;
820 }
821 
822 template <typename T>
ToPointerVec(const std::vector<T> & src)823 std::vector<const T*> ToPointerVec(const std::vector<T>& src) {
824   std::vector<const T*> dst;
825   dst.reserve(src.size());
826   for (const T& in : src) {
827     dst.push_back(&in);
828   }
829   return dst;
830 }
831 
KeyNameComparator(const Style::Entry * a,const Style::Entry * b)832 static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) {
833   return a->key.name < b->key.name;
834 }
835 
Equals(const Value * value) const836 bool Style::Equals(const Value* value) const {
837   const Style* other = ValueCast<Style>(value);
838   if (!other) {
839     return false;
840   }
841 
842   if (bool(parent) != bool(other->parent) ||
843       (parent && other->parent && !parent.value().Equals(&other->parent.value()))) {
844     return false;
845   }
846 
847   if (entries.size() != other->entries.size()) {
848     return false;
849   }
850 
851   std::vector<const Entry*> sorted_a = ToPointerVec(entries);
852   std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator);
853 
854   std::vector<const Entry*> sorted_b = ToPointerVec(other->entries);
855   std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator);
856 
857   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
858                     [](const Entry* a, const Entry* b) -> bool {
859                       return a->key.Equals(&b->key) && a->value->Equals(b->value.get());
860                     });
861 }
862 
Print(std::ostream * out) const863 void Style::Print(std::ostream* out) const {
864   *out << "(style) ";
865   if (parent && parent.value().name) {
866     const Reference& parent_ref = parent.value();
867     if (parent_ref.private_reference) {
868       *out << "*";
869     }
870     *out << parent_ref.name.value();
871   }
872   *out << " [" << util::Joiner(entries, ", ") << "]";
873 }
874 
CloneEntry(const Style::Entry & entry,StringPool * pool)875 Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
876   Style::Entry cloned_entry{entry.key};
877   if (entry.value != nullptr) {
878     CloningValueTransformer cloner(pool);
879     cloned_entry.value = entry.value->Transform(cloner);
880   }
881   return cloned_entry;
882 }
883 
MergeWith(Style * other,StringPool * pool)884 void Style::MergeWith(Style* other, StringPool* pool) {
885   if (other->parent) {
886     parent = other->parent;
887   }
888 
889   // We can't assume that the entries are sorted alphabetically since they're supposed to be
890   // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge
891   // them keying off that.
892   //
893   // Instead, sort the entries of each Style by their name in a separate structure. Then merge
894   // those.
895 
896   std::vector<Entry*> this_sorted = ToPointerVec(entries);
897   std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator);
898 
899   std::vector<Entry*> other_sorted = ToPointerVec(other->entries);
900   std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator);
901 
902   auto this_iter = this_sorted.begin();
903   const auto this_end = this_sorted.end();
904 
905   auto other_iter = other_sorted.begin();
906   const auto other_end = other_sorted.end();
907 
908   std::vector<Entry> merged_entries;
909   while (this_iter != this_end) {
910     if (other_iter != other_end) {
911       if ((*this_iter)->key.name < (*other_iter)->key.name) {
912         merged_entries.push_back(std::move(**this_iter));
913         ++this_iter;
914       } else {
915         // The other overrides.
916         merged_entries.push_back(CloneEntry(**other_iter, pool));
917         if ((*this_iter)->key.name == (*other_iter)->key.name) {
918           ++this_iter;
919         }
920         ++other_iter;
921       }
922     } else {
923       merged_entries.push_back(std::move(**this_iter));
924       ++this_iter;
925     }
926   }
927 
928   while (other_iter != other_end) {
929     merged_entries.push_back(CloneEntry(**other_iter, pool));
930     ++other_iter;
931   }
932 
933   entries = std::move(merged_entries);
934 }
935 
Equals(const Value * value) const936 bool Array::Equals(const Value* value) const {
937   const Array* other = ValueCast<Array>(value);
938   if (!other) {
939     return false;
940   }
941 
942   if (elements.size() != other->elements.size()) {
943     return false;
944   }
945 
946   return std::equal(elements.begin(), elements.end(), other->elements.begin(),
947                     [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
948                       return a->Equals(b.get());
949                     });
950 }
951 
Print(std::ostream * out) const952 void Array::Print(std::ostream* out) const {
953   *out << "(array) [" << util::Joiner(elements, ", ") << "]";
954 }
955 
Equals(const Value * value) const956 bool Plural::Equals(const Value* value) const {
957   const Plural* other = ValueCast<Plural>(value);
958   if (!other) {
959     return false;
960   }
961 
962   auto one_iter = values.begin();
963   auto one_end_iter = values.end();
964   auto two_iter = other->values.begin();
965   for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
966     const std::unique_ptr<Item>& a = *one_iter;
967     const std::unique_ptr<Item>& b = *two_iter;
968     if (a != nullptr && b != nullptr) {
969       if (!a->Equals(b.get())) {
970         return false;
971       }
972     } else if (a != b) {
973       return false;
974     }
975   }
976   return true;
977 }
978 
Print(std::ostream * out) const979 void Plural::Print(std::ostream* out) const {
980   *out << "(plural)";
981   if (values[Zero]) {
982     *out << " zero=" << *values[Zero];
983   }
984 
985   if (values[One]) {
986     *out << " one=" << *values[One];
987   }
988 
989   if (values[Two]) {
990     *out << " two=" << *values[Two];
991   }
992 
993   if (values[Few]) {
994     *out << " few=" << *values[Few];
995   }
996 
997   if (values[Many]) {
998     *out << " many=" << *values[Many];
999   }
1000 
1001   if (values[Other]) {
1002     *out << " other=" << *values[Other];
1003   }
1004 }
1005 
Equals(const Value * value) const1006 bool Styleable::Equals(const Value* value) const {
1007   const Styleable* other = ValueCast<Styleable>(value);
1008   if (!other) {
1009     return false;
1010   }
1011 
1012   if (entries.size() != other->entries.size()) {
1013     return false;
1014   }
1015 
1016   return std::equal(entries.begin(), entries.end(), other->entries.begin(),
1017                     [](const Reference& a, const Reference& b) -> bool {
1018                       return a.Equals(&b);
1019                     });
1020 }
1021 
Print(std::ostream * out) const1022 void Styleable::Print(std::ostream* out) const {
1023   *out << "(styleable) "
1024        << " [" << util::Joiner(entries, ", ") << "]";
1025 }
1026 
Equals(const Value * value) const1027 bool Macro::Equals(const Value* value) const {
1028   const Macro* other = ValueCast<Macro>(value);
1029   if (!other) {
1030     return false;
1031   }
1032   return other->raw_value == raw_value && other->style_string.spans == style_string.spans &&
1033          other->style_string.str == style_string.str &&
1034          other->untranslatable_sections == untranslatable_sections &&
1035          other->alias_namespaces == alias_namespaces;
1036 }
1037 
Print(std::ostream * out) const1038 void Macro::Print(std::ostream* out) const {
1039   *out << "(macro) ";
1040 }
1041 
operator <(const Reference & a,const Reference & b)1042 bool operator<(const Reference& a, const Reference& b) {
1043   int cmp = a.name.value_or(ResourceName{}).compare(b.name.value_or(ResourceName{}));
1044   if (cmp != 0) return cmp < 0;
1045   return a.id < b.id;
1046 }
1047 
operator ==(const Reference & a,const Reference & b)1048 bool operator==(const Reference& a, const Reference& b) {
1049   return a.name == b.name && a.id == b.id;
1050 }
1051 
operator !=(const Reference & a,const Reference & b)1052 bool operator!=(const Reference& a, const Reference& b) {
1053   return a.name != b.name || a.id != b.id;
1054 }
1055 
1056 struct NameOnlyComparator {
operator ()aapt::NameOnlyComparator1057   bool operator()(const Reference& a, const Reference& b) const {
1058     return a.name < b.name;
1059   }
1060 };
1061 
MergeWith(Styleable * other)1062 void Styleable::MergeWith(Styleable* other) {
1063   // Compare only names, because some References may already have their IDs
1064   // assigned (framework IDs that don't change).
1065   std::set<Reference, NameOnlyComparator> references;
1066   references.insert(entries.begin(), entries.end());
1067   references.insert(other->entries.begin(), other->entries.end());
1068   entries.clear();
1069   entries.reserve(references.size());
1070   entries.insert(entries.end(), references.begin(), references.end());
1071 }
1072 
1073 template <typename T>
CopyValueFields(std::unique_ptr<T> new_value,const T * value)1074 std::unique_ptr<T> CopyValueFields(std::unique_ptr<T> new_value, const T* value) {
1075   new_value->SetSource(value->GetSource());
1076   new_value->SetComment(value->GetComment());
1077   return new_value;
1078 }
1079 
CloningValueTransformer(StringPool * new_pool)1080 CloningValueTransformer::CloningValueTransformer(StringPool* new_pool)
1081     : ValueTransformer(new_pool) {
1082 }
1083 
TransformDerived(const Reference * value)1084 std::unique_ptr<Reference> CloningValueTransformer::TransformDerived(const Reference* value) {
1085   return std::make_unique<Reference>(*value);
1086 }
1087 
TransformDerived(const Id * value)1088 std::unique_ptr<Id> CloningValueTransformer::TransformDerived(const Id* value) {
1089   return std::make_unique<Id>(*value);
1090 }
1091 
TransformDerived(const RawString * value)1092 std::unique_ptr<RawString> CloningValueTransformer::TransformDerived(const RawString* value) {
1093   auto new_value = std::make_unique<RawString>(pool_->MakeRef(value->value));
1094   return CopyValueFields(std::move(new_value), value);
1095 }
1096 
TransformDerived(const String * value)1097 std::unique_ptr<String> CloningValueTransformer::TransformDerived(const String* value) {
1098   auto new_value = std::make_unique<String>(pool_->MakeRef(value->value));
1099   new_value->untranslatable_sections = value->untranslatable_sections;
1100   return CopyValueFields(std::move(new_value), value);
1101 }
1102 
TransformDerived(const StyledString * value)1103 std::unique_ptr<StyledString> CloningValueTransformer::TransformDerived(const StyledString* value) {
1104   auto new_value = std::make_unique<StyledString>(pool_->MakeRef(value->value));
1105   new_value->untranslatable_sections = value->untranslatable_sections;
1106   return CopyValueFields(std::move(new_value), value);
1107 }
1108 
TransformDerived(const FileReference * value)1109 std::unique_ptr<FileReference> CloningValueTransformer::TransformDerived(
1110     const FileReference* value) {
1111   auto new_value = std::make_unique<FileReference>(pool_->MakeRef(value->path));
1112   new_value->file = value->file;
1113   new_value->type = value->type;
1114   return CopyValueFields(std::move(new_value), value);
1115 }
1116 
TransformDerived(const BinaryPrimitive * value)1117 std::unique_ptr<BinaryPrimitive> CloningValueTransformer::TransformDerived(
1118     const BinaryPrimitive* value) {
1119   return std::make_unique<BinaryPrimitive>(*value);
1120 }
1121 
TransformDerived(const Attribute * value)1122 std::unique_ptr<Attribute> CloningValueTransformer::TransformDerived(const Attribute* value) {
1123   auto new_value = std::make_unique<Attribute>();
1124   new_value->type_mask = value->type_mask;
1125   new_value->min_int = value->min_int;
1126   new_value->max_int = value->max_int;
1127   for (const Attribute::Symbol& s : value->symbols) {
1128     new_value->symbols.emplace_back(Attribute::Symbol{
1129         .symbol = *s.symbol.Transform(*this),
1130         .value = s.value,
1131         .type = s.type,
1132     });
1133   }
1134   return CopyValueFields(std::move(new_value), value);
1135 }
1136 
TransformDerived(const Style * value)1137 std::unique_ptr<Style> CloningValueTransformer::TransformDerived(const Style* value) {
1138   auto new_value = std::make_unique<Style>();
1139   new_value->parent = value->parent;
1140   new_value->parent_inferred = value->parent_inferred;
1141   for (auto& entry : value->entries) {
1142     new_value->entries.push_back(Style::Entry{entry.key, entry.value->Transform(*this)});
1143   }
1144   return CopyValueFields(std::move(new_value), value);
1145 }
1146 
TransformDerived(const Array * value)1147 std::unique_ptr<Array> CloningValueTransformer::TransformDerived(const Array* value) {
1148   auto new_value = std::make_unique<Array>();
1149   for (auto& item : value->elements) {
1150     new_value->elements.emplace_back(item->Transform(*this));
1151   }
1152   return CopyValueFields(std::move(new_value), value);
1153 }
1154 
TransformDerived(const Plural * value)1155 std::unique_ptr<Plural> CloningValueTransformer::TransformDerived(const Plural* value) {
1156   auto new_value = std::make_unique<Plural>();
1157   const size_t count = value->values.size();
1158   for (size_t i = 0; i < count; i++) {
1159     if (value->values[i]) {
1160       new_value->values[i] = value->values[i]->Transform(*this);
1161     }
1162   }
1163   return CopyValueFields(std::move(new_value), value);
1164 }
1165 
TransformDerived(const Styleable * value)1166 std::unique_ptr<Styleable> CloningValueTransformer::TransformDerived(const Styleable* value) {
1167   auto new_value = std::make_unique<Styleable>();
1168   for (const Reference& s : value->entries) {
1169     new_value->entries.emplace_back(*s.Transform(*this));
1170   }
1171   return CopyValueFields(std::move(new_value), value);
1172 }
1173 
TransformDerived(const Macro * value)1174 std::unique_ptr<Macro> CloningValueTransformer::TransformDerived(const Macro* value) {
1175   auto new_value = std::make_unique<Macro>(*value);
1176   return CopyValueFields(std::move(new_value), value);
1177 }
1178 
1179 }  // namespace aapt
1180