diff options
Diffstat (limited to 'tools/aapt2/ResourceValues.cpp')
-rw-r--r-- | tools/aapt2/ResourceValues.cpp | 126 |
1 files changed, 109 insertions, 17 deletions
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index c10b134cb36e..492155ddb591 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -18,11 +18,12 @@ #include "ResourceUtils.h" #include "ResourceValues.h" #include "ValueVisitor.h" -#include "io/File.h" #include "util/Util.h" +#include <algorithm> #include <androidfw/ResourceTypes.h> #include <limits> +#include <set> namespace aapt { @@ -64,7 +65,7 @@ void RawString::print(std::ostream* out) const { *out << "(raw string) " << *value; } -Reference::Reference() : referenceType(Reference::Type::kResource) { +Reference::Reference() : referenceType(Type::kResource) { } Reference::Reference(const ResourceNameRef& n, Type t) : @@ -74,6 +75,10 @@ Reference::Reference(const ResourceNameRef& n, Type t) : Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) { } +Reference::Reference(const ResourceNameRef& n, const ResourceId& i) : + name(n.toResourceName()), id(i), referenceType(Type::kResource) { +} + bool Reference::equals(const Value* value) const { const Reference* other = valueCast<Reference>(value); if (!other) { @@ -302,18 +307,42 @@ Attribute::Attribute(bool w, uint32_t t) : mWeak = w; } +template <typename T> +T* addPointer(T& val) { + return &val; +} + bool Attribute::equals(const Value* value) const { const Attribute* other = valueCast<Attribute>(value); if (!other) { return false; } - return this->typeMask == other->typeMask && this->minInt == other->minInt && - this->maxInt == other->maxInt && - std::equal(this->symbols.begin(), this->symbols.end(), - other->symbols.begin(), - [](const Symbol& a, const Symbol& b) -> bool { - return a.symbol.equals(&b.symbol) && a.value == b.value; + if (symbols.size() != other->symbols.size()) { + return false; + } + + if (typeMask != other->typeMask || minInt != other->minInt || maxInt != other->maxInt) { + return false; + } + + std::vector<const Symbol*> sortedA; + std::transform(symbols.begin(), symbols.end(), + std::back_inserter(sortedA), addPointer<const Symbol>); + std::sort(sortedA.begin(), sortedA.end(), [](const Symbol* a, const Symbol* b) -> bool { + return a->symbol.name < b->symbol.name; + }); + + std::vector<const Symbol*> sortedB; + std::transform(other->symbols.begin(), other->symbols.end(), + std::back_inserter(sortedB), addPointer<const Symbol>); + std::sort(sortedB.begin(), sortedB.end(), [](const Symbol* a, const Symbol* b) -> bool { + return a->symbol.name < b->symbol.name; + }); + + return std::equal(sortedA.begin(), sortedA.end(), sortedB.begin(), + [](const Symbol* a, const Symbol* b) -> bool { + return a->symbol.equals(&b->symbol) && a->value == b->value; }); } @@ -424,9 +453,7 @@ void Attribute::print(std::ostream* out) const { printMask(out); if (!symbols.empty()) { - *out << " [" - << util::joiner(symbols.begin(), symbols.end(), ", ") - << "]"; + *out << " [" << util::joiner(symbols, ", ") << "]"; } if (minInt != std::numeric_limits<int32_t>::min()) { @@ -526,9 +553,28 @@ bool Style::equals(const Value* value) const { (parent && other->parent && !parent.value().equals(&other->parent.value()))) { return false; } - return std::equal(entries.begin(), entries.end(), other->entries.begin(), - [](const Entry& a, const Entry& b) -> bool { - return a.key.equals(&b.key) && a.value->equals(b.value.get()); + + if (entries.size() != other->entries.size()) { + return false; + } + + std::vector<const Entry*> sortedA; + std::transform(entries.begin(), entries.end(), + std::back_inserter(sortedA), addPointer<const Entry>); + std::sort(sortedA.begin(), sortedA.end(), [](const Entry* a, const Entry* b) -> bool { + return a->key.name < b->key.name; + }); + + std::vector<const Entry*> sortedB; + std::transform(other->entries.begin(), other->entries.end(), + std::back_inserter(sortedB), addPointer<const Entry>); + std::sort(sortedB.begin(), sortedB.end(), [](const Entry* a, const Entry* b) -> bool { + return a->key.name < b->key.name; + }); + + return std::equal(sortedA.begin(), sortedA.end(), sortedB.begin(), + [](const Entry* a, const Entry* b) -> bool { + return a->key.equals(&b->key) && a->value->equals(b->value.get()); }); } @@ -556,13 +602,15 @@ void Style::print(std::ostream* out) const { *out << parent.value().name.value(); } *out << " [" - << util::joiner(entries.begin(), entries.end(), ", ") + << util::joiner(entries, ", ") << "]"; } static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) { if (value.key.name) { out << value.key.name.value(); + } else if (value.key.id) { + out << value.key.id.value(); } else { out << "???"; } @@ -577,6 +625,10 @@ bool Array::equals(const Value* value) const { return false; } + if (items.size() != other->items.size()) { + return false; + } + return std::equal(items.begin(), items.end(), other->items.begin(), [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool { return a->equals(b.get()); @@ -595,7 +647,7 @@ Array* Array::clone(StringPool* newPool) const { void Array::print(std::ostream* out) const { *out << "(array) [" - << util::joiner(items.begin(), items.end(), ", ") + << util::joiner(items, ", ") << "]"; } @@ -605,6 +657,10 @@ bool Plural::equals(const Value* value) const { return false; } + if (values.size() != other->values.size()) { + return false; + } + return std::equal(values.begin(), values.end(), other->values.begin(), [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool { if (bool(a) != bool(b)) { @@ -659,6 +715,11 @@ bool Styleable::equals(const Value* value) const { if (!other) { return false; } + + if (entries.size() != other->entries.size()) { + return false; + } + return std::equal(entries.begin(), entries.end(), other->entries.begin(), [](const Reference& a, const Reference& b) -> bool { return a.equals(&b); @@ -671,8 +732,39 @@ Styleable* Styleable::clone(StringPool* /*newPool*/) const { void Styleable::print(std::ostream* out) const { *out << "(styleable) " << " [" - << util::joiner(entries.begin(), entries.end(), ", ") + << util::joiner(entries, ", ") << "]"; } +bool operator<(const Reference& a, const Reference& b) { + int cmp = a.name.valueOrDefault({}).compare(b.name.valueOrDefault({})); + if (cmp != 0) return cmp < 0; + return a.id < b.id; +} + +bool operator==(const Reference& a, const Reference& b) { + return a.name == b.name && a.id == b.id; +} + +bool operator!=(const Reference& a, const Reference& b) { + return a.name != b.name || a.id != b.id; +} + +struct NameOnlyComparator { + bool operator()(const Reference& a, const Reference& b) const { + return a.name < b.name; + } +}; + +void Styleable::mergeWith(Styleable* other) { + // Compare only names, because some References may already have their IDs assigned + // (framework IDs that don't change). + std::set<Reference, NameOnlyComparator> references; + references.insert(entries.begin(), entries.end()); + references.insert(other->entries.begin(), other->entries.end()); + entries.clear(); + entries.reserve(references.size()); + entries.insert(entries.end(), references.begin(), references.end()); +} + } // namespace aapt |