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