Loading tools/aapt2/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ cc_library_host_static { "Configuration.proto", "Resources.proto", "ResourcesInternal.proto", "ValueTransformer.cpp", ], proto: { export_proto_headers: true, Loading tools/aapt2/ResourceTable.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -577,6 +577,7 @@ Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNam std::unique_ptr<ResourceTable> ResourceTable::Clone() const { std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>(); CloningValueTransformer cloner(&new_table->string_pool); for (const auto& pkg : packages) { ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name); for (const auto& type : pkg->types) { Loading @@ -593,7 +594,7 @@ std::unique_ptr<ResourceTable> ResourceTable::Clone() const { for (const auto& config_value : entry->values) { ResourceConfigValue* new_value = new_entry->FindOrCreateValue(config_value->config, config_value->product); new_value->value.reset(config_value->value->Clone(&new_table->string_pool)); new_value->value = config_value->value->Transform(cloner); } } } Loading tools/aapt2/ResourceValues.cpp +111 −88 Original line number Diff line number Diff line Loading @@ -47,6 +47,14 @@ std::ostream& operator<<(std::ostream& out, const Value& value) { return out; } std::unique_ptr<Value> Value::Transform(ValueTransformer& transformer) const { return std::unique_ptr<Value>(this->TransformValueImpl(transformer)); } std::unique_ptr<Item> Item::Transform(ValueTransformer& transformer) const { return std::unique_ptr<Item>(this->TransformItemImpl(transformer)); } template <typename Derived> void BaseValue<Derived>::Accept(ValueVisitor* visitor) { visitor->Visit(static_cast<Derived*>(this)); Loading Loading @@ -77,13 +85,6 @@ bool RawString::Equals(const Value* value) const { return *this->value == *other->value; } RawString* RawString::Clone(StringPool* new_pool) const { RawString* rs = new RawString(new_pool->MakeRef(value)); rs->comment_ = comment_; rs->source_ = source_; return rs; } bool RawString::Flatten(android::Res_value* out_value) const { out_value->dataType = android::Res_value::TYPE_STRING; out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index())); Loading Loading @@ -136,10 +137,6 @@ bool Reference::Flatten(android::Res_value* out_value) const { return true; } Reference* Reference::Clone(StringPool* /*new_pool*/) const { return new Reference(*this); } void Reference::Print(std::ostream* out) const { if (reference_type == Type::kResource) { *out << "(reference) @"; Loading Loading @@ -220,10 +217,6 @@ bool Id::Flatten(android::Res_value* out) const { return true; } Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); } void Id::Print(std::ostream* out) const { *out << "(id)"; } Loading Loading @@ -266,14 +259,6 @@ bool String::Flatten(android::Res_value* out_value) const { return true; } String* String::Clone(StringPool* new_pool) const { String* str = new String(new_pool->MakeRef(value)); str->comment_ = comment_; str->source_ = source_; str->untranslatable_sections = untranslatable_sections; return str; } void String::Print(std::ostream* out) const { *out << "(string) \"" << *value << "\""; } Loading Loading @@ -321,14 +306,6 @@ bool StyledString::Flatten(android::Res_value* out_value) const { return true; } StyledString* StyledString::Clone(StringPool* new_pool) const { StyledString* str = new StyledString(new_pool->MakeRef(value)); str->comment_ = comment_; str->source_ = source_; str->untranslatable_sections = untranslatable_sections; return str; } void StyledString::Print(std::ostream* out) const { *out << "(styled string) \"" << value->value << "\""; for (const StringPool::Span& span : value->spans) { Loading Loading @@ -357,15 +334,6 @@ bool FileReference::Flatten(android::Res_value* out_value) const { return true; } FileReference* FileReference::Clone(StringPool* new_pool) const { FileReference* fr = new FileReference(new_pool->MakeRef(path)); fr->file = file; fr->type = type; fr->comment_ = comment_; fr->source_ = source_; return fr; } void FileReference::Print(std::ostream* out) const { *out << "(file) " << *path; switch (type) { Loading Loading @@ -406,10 +374,6 @@ bool BinaryPrimitive::Flatten(::android::Res_value* out_value) const { return true; } BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const { return new BinaryPrimitive(*this); } void BinaryPrimitive::Print(std::ostream* out) const { *out << StringPrintf("(primitive) type=0x%02x data=0x%08x", value.dataType, value.data); } Loading Loading @@ -587,10 +551,6 @@ bool Attribute::IsCompatibleWith(const Attribute& attr) const { return this_type_mask == that_type_mask; } Attribute* Attribute::Clone(StringPool* /*new_pool*/) const { return new Attribute(*this); } std::string Attribute::MaskString() const { if (type_mask == android::ResTable_map::TYPE_ANY) { return "any"; Loading Loading @@ -893,18 +853,6 @@ bool Style::Equals(const Value* value) const { }); } Style* Style::Clone(StringPool* new_pool) const { Style* style = new Style(); style->parent = parent; style->parent_inferred = parent_inferred; style->comment_ = comment_; style->source_ = source_; for (auto& entry : entries) { style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))}); } return style; } void Style::Print(std::ostream* out) const { *out << "(style) "; if (parent && parent.value().name) { Loading @@ -920,7 +868,8 @@ void Style::Print(std::ostream* out) const { Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) { Style::Entry cloned_entry{entry.key}; if (entry.value != nullptr) { cloned_entry.value.reset(entry.value->Clone(pool)); CloningValueTransformer cloner(pool); cloned_entry.value = entry.value->Transform(cloner); } return cloned_entry; } Loading Loading @@ -993,16 +942,6 @@ bool Array::Equals(const Value* value) const { }); } Array* Array::Clone(StringPool* new_pool) const { Array* array = new Array(); array->comment_ = comment_; array->source_ = source_; for (auto& item : elements) { array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool))); } return array; } void Array::Print(std::ostream* out) const { *out << "(array) [" << util::Joiner(elements, ", ") << "]"; } Loading Loading @@ -1030,19 +969,6 @@ bool Plural::Equals(const Value* value) const { return true; } Plural* Plural::Clone(StringPool* new_pool) const { Plural* p = new Plural(); p->comment_ = comment_; p->source_ = source_; const size_t count = values.size(); for (size_t i = 0; i < count; i++) { if (values[i]) { p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool)); } } return p; } void Plural::Print(std::ostream* out) const { *out << "(plural)"; if (values[Zero]) { Loading Loading @@ -1086,10 +1012,6 @@ bool Styleable::Equals(const Value* value) const { }); } Styleable* Styleable::Clone(StringPool* /*new_pool*/) const { return new Styleable(*this); } void Styleable::Print(std::ostream* out) const { *out << "(styleable) " << " [" << util::Joiner(entries, ", ") << "]"; Loading Loading @@ -1126,4 +1048,105 @@ void Styleable::MergeWith(Styleable* other) { entries.insert(entries.end(), references.begin(), references.end()); } template <typename T> std::unique_ptr<T> CopyValueFields(std::unique_ptr<T> new_value, const T* value) { new_value->SetSource(value->GetSource()); new_value->SetComment(value->GetComment()); return new_value; } CloningValueTransformer::CloningValueTransformer(StringPool* new_pool) : ValueTransformer(new_pool) { } std::unique_ptr<Reference> CloningValueTransformer::TransformDerived(const Reference* value) { return std::make_unique<Reference>(*value); } std::unique_ptr<Id> CloningValueTransformer::TransformDerived(const Id* value) { return std::make_unique<Id>(*value); } std::unique_ptr<RawString> CloningValueTransformer::TransformDerived(const RawString* value) { auto new_value = std::make_unique<RawString>(pool_->MakeRef(value->value)); return CopyValueFields(std::move(new_value), value); } std::unique_ptr<String> CloningValueTransformer::TransformDerived(const String* value) { auto new_value = std::make_unique<String>(pool_->MakeRef(value->value)); new_value->untranslatable_sections = value->untranslatable_sections; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<StyledString> CloningValueTransformer::TransformDerived(const StyledString* value) { auto new_value = std::make_unique<StyledString>(pool_->MakeRef(value->value)); new_value->untranslatable_sections = value->untranslatable_sections; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<FileReference> CloningValueTransformer::TransformDerived( const FileReference* value) { auto new_value = std::make_unique<FileReference>(pool_->MakeRef(value->path)); new_value->file = value->file; new_value->type = value->type; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<BinaryPrimitive> CloningValueTransformer::TransformDerived( const BinaryPrimitive* value) { return std::make_unique<BinaryPrimitive>(*value); } std::unique_ptr<Attribute> CloningValueTransformer::TransformDerived(const Attribute* value) { auto new_value = std::make_unique<Attribute>(); new_value->type_mask = value->type_mask; new_value->min_int = value->min_int; new_value->max_int = value->max_int; for (const Attribute::Symbol& s : value->symbols) { new_value->symbols.emplace_back(Attribute::Symbol{ .symbol = *s.symbol.Transform(*this), .value = s.value, .type = s.type, }); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Style> CloningValueTransformer::TransformDerived(const Style* value) { auto new_value = std::make_unique<Style>(); new_value->parent = value->parent; new_value->parent_inferred = value->parent_inferred; for (auto& entry : value->entries) { new_value->entries.push_back(Style::Entry{entry.key, entry.value->Transform(*this)}); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Array> CloningValueTransformer::TransformDerived(const Array* value) { auto new_value = std::make_unique<Array>(); for (auto& item : value->elements) { new_value->elements.emplace_back(item->Transform(*this)); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Plural> CloningValueTransformer::TransformDerived(const Plural* value) { auto new_value = std::make_unique<Plural>(); const size_t count = value->values.size(); for (size_t i = 0; i < count; i++) { if (value->values[i]) { new_value->values[i] = value->values[i]->Transform(*this); } } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Styleable> CloningValueTransformer::TransformDerived(const Styleable* value) { auto new_value = std::make_unique<Styleable>(); for (const Reference& s : value->entries) { new_value->entries.emplace_back(*s.Transform(*this)); } return CopyValueFields(std::move(new_value), value); } } // namespace aapt tools/aapt2/ResourceValues.h +41 −30 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "Diagnostics.h" #include "Resource.h" #include "StringPool.h" #include "ValueTransformer.h" #include "io/File.h" #include "text/Printer.h" #include "util/Maybe.h" Loading Loading @@ -100,9 +101,8 @@ class Value { // Calls the appropriate overload of ConstValueVisitor. virtual void Accept(ConstValueVisitor* visitor) const = 0; // Clone the value. `new_pool` is the new StringPool that // any resources with strings should use when copying their string. virtual Value* Clone(StringPool* new_pool) const = 0; // Transform this Value into another Value using the transformer. std::unique_ptr<Value> Transform(ValueTransformer& transformer) const; // Human readable printout of this value. virtual void Print(std::ostream* out) const = 0; Loading @@ -118,6 +118,9 @@ class Value { std::string comment_; bool weak_ = false; bool translatable_ = true; private: virtual Value* TransformValueImpl(ValueTransformer& transformer) const = 0; }; // Inherit from this to get visitor accepting implementations for free. Loading @@ -129,12 +132,15 @@ struct BaseValue : public Value { // A resource item with a single value. This maps to android::ResTable_entry. struct Item : public Value { // Clone the Item. virtual Item* Clone(StringPool* new_pool) const override = 0; // Fills in an android::Res_value structure with this Item's binary representation. // Returns false if an error occurred. virtual bool Flatten(android::Res_value* out_value) const = 0; // Transform this Item into another Item using the transformer. std::unique_ptr<Item> Transform(ValueTransformer& transformer) const; private: virtual Item* TransformItemImpl(ValueTransformer& transformer) const = 0; }; // Inherit from this to get visitor accepting implementations for free. Loading @@ -147,7 +153,7 @@ struct BaseItem : public Item { // A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE. // A reference can be symbolic (with the name set to a valid resource name) or be // numeric (the id is set to a valid resource ID). struct Reference : public BaseItem<Reference> { struct Reference : public TransformableItem<Reference, BaseItem<Reference>> { enum class Type { kResource, kAttribute, Loading @@ -166,7 +172,6 @@ struct Reference : public BaseItem<Reference> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; Reference* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; Loading @@ -178,27 +183,25 @@ bool operator<(const Reference&, const Reference&); bool operator==(const Reference&, const Reference&); // An ID resource. Has no real value, just a place holder. struct Id : public BaseItem<Id> { struct Id : public TransformableItem<Id, BaseItem<Id>> { Id() { weak_ = true; } bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out) const override; Id* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; // A raw, unprocessed string. This may contain quotations, escape sequences, and whitespace. // This shall *NOT* end up in the final resource table. struct RawString : public BaseItem<RawString> { struct RawString : public TransformableItem<RawString, BaseItem<RawString>> { StringPool::Ref value; explicit RawString(const StringPool::Ref& ref); bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; RawString* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; Loading @@ -220,7 +223,7 @@ inline bool operator!=(const UntranslatableSection& a, const UntranslatableSecti return a.start != b.start || a.end != b.end; } struct String : public BaseItem<String> { struct String : public TransformableItem<String, BaseItem<String>> { StringPool::Ref value; // Sections of the string to NOT translate. Mainly used Loading @@ -232,12 +235,11 @@ struct String : public BaseItem<String> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; String* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; }; struct StyledString : public BaseItem<StyledString> { struct StyledString : public TransformableItem<StyledString, BaseItem<StyledString>> { StringPool::StyleRef value; // Sections of the string to NOT translate. Mainly used Loading @@ -249,11 +251,10 @@ struct StyledString : public BaseItem<StyledString> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; StyledString* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct FileReference : public BaseItem<FileReference> { struct FileReference : public TransformableItem<FileReference, BaseItem<FileReference>> { StringPool::Ref path; // A handle to the file object from which this file can be read. Loading @@ -269,12 +270,11 @@ struct FileReference : public BaseItem<FileReference> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; FileReference* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; // Represents any other android::Res_value. struct BinaryPrimitive : public BaseItem<BinaryPrimitive> { struct BinaryPrimitive : public TransformableItem<BinaryPrimitive, BaseItem<BinaryPrimitive>> { android::Res_value value; BinaryPrimitive() = default; Loading @@ -283,12 +283,11 @@ struct BinaryPrimitive : public BaseItem<BinaryPrimitive> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; BinaryPrimitive* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; }; struct Attribute : public BaseValue<Attribute> { struct Attribute : public TransformableValue<Attribute, BaseValue<Attribute>> { struct Symbol { Reference symbol; uint32_t value; Loading @@ -311,13 +310,12 @@ struct Attribute : public BaseValue<Attribute> { // TYPE_ENUMS are never compatible. bool IsCompatibleWith(const Attribute& attr) const; Attribute* Clone(StringPool* new_pool) const override; std::string MaskString() const; void Print(std::ostream* out) const override; bool Matches(const Item& item, DiagMessage* out_msg = nullptr) const; }; struct Style : public BaseValue<Style> { struct Style : public TransformableValue<Style, BaseValue<Style>> { struct Entry { Reference key; std::unique_ptr<Item> value; Loading @@ -333,7 +331,6 @@ struct Style : public BaseValue<Style> { std::vector<Entry> entries; bool Equals(const Value* value) const override; Style* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; // Merges `style` into this Style. All identical attributes of `style` take precedence, including Loading @@ -341,29 +338,26 @@ struct Style : public BaseValue<Style> { void MergeWith(Style* style, StringPool* pool); }; struct Array : public BaseValue<Array> { struct Array : public TransformableValue<Array, BaseValue<Array>> { std::vector<std::unique_ptr<Item>> elements; bool Equals(const Value* value) const override; Array* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct Plural : public BaseValue<Plural> { struct Plural : public TransformableValue<Plural, BaseValue<Plural>> { enum { Zero = 0, One, Two, Few, Many, Other, Count }; std::array<std::unique_ptr<Item>, Count> values; bool Equals(const Value* value) const override; Plural* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct Styleable : public BaseValue<Styleable> { struct Styleable : public TransformableValue<Styleable, BaseValue<Styleable>> { std::vector<Reference> entries; bool Equals(const Value* value) const override; Styleable* Clone(StringPool* newPool) const override; void Print(std::ostream* out) const override; void MergeWith(Styleable* styleable); }; Loading @@ -379,6 +373,23 @@ typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type o return out; } struct CloningValueTransformer : public ValueTransformer { explicit CloningValueTransformer(StringPool* new_pool); std::unique_ptr<Reference> TransformDerived(const Reference* value) override; std::unique_ptr<Id> TransformDerived(const Id* value) override; std::unique_ptr<RawString> TransformDerived(const RawString* value) override; std::unique_ptr<String> TransformDerived(const String* value) override; std::unique_ptr<StyledString> TransformDerived(const StyledString* value) override; std::unique_ptr<FileReference> TransformDerived(const FileReference* value) override; std::unique_ptr<BinaryPrimitive> TransformDerived(const BinaryPrimitive* value) override; std::unique_ptr<Attribute> TransformDerived(const Attribute* value) override; std::unique_ptr<Style> TransformDerived(const Style* value) override; std::unique_ptr<Array> TransformDerived(const Array* value) override; std::unique_ptr<Plural> TransformDerived(const Plural* value) override; std::unique_ptr<Styleable> TransformDerived(const Styleable* value) override; }; } // namespace aapt #endif // AAPT_RESOURCE_VALUES_H tools/aapt2/ResourceValues_test.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ TEST(ResourceValuesTest, PluralClone) { a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one")); a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other")); std::unique_ptr<Plural> b(a.Clone(&pool)); CloningValueTransformer cloner(&pool); std::unique_ptr<Plural> b(a.Transform(cloner)); EXPECT_TRUE(a.Equals(b.get())); } Loading Loading @@ -97,7 +98,8 @@ TEST(ResourceValuesTest, ArrayClone) { a.elements.push_back(util::make_unique<String>(pool.MakeRef("one"))); a.elements.push_back(util::make_unique<String>(pool.MakeRef("two"))); std::unique_ptr<Array> b(a.Clone(&pool)); CloningValueTransformer cloner(&pool); std::unique_ptr<Array> b(a.Transform(cloner)); EXPECT_TRUE(a.Equals(b.get())); } Loading Loading @@ -160,7 +162,8 @@ TEST(ResourceValuesTest, StyleClone) { .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2")) .Build(); std::unique_ptr<Style> b(a->Clone(nullptr)); CloningValueTransformer cloner(nullptr); std::unique_ptr<Style> b(a->Transform(cloner)); EXPECT_TRUE(a->Equals(b.get())); } Loading @@ -174,7 +177,8 @@ TEST(ResourcesValuesTest, StringClones) { EXPECT_THAT(pool_a.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en"))); EXPECT_THAT(pool_a.strings()[0]->value, StrEq("hello")); std::unique_ptr<String> str_b(str_a.Clone(&pool_b)); CloningValueTransformer cloner(&pool_b); str_a.Transform(cloner); ASSERT_THAT(pool_b, SizeIs(1u)); EXPECT_THAT(pool_b.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en"))); EXPECT_THAT(pool_b.strings()[0]->value, StrEq("hello")); Loading Loading
tools/aapt2/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ cc_library_host_static { "Configuration.proto", "Resources.proto", "ResourcesInternal.proto", "ValueTransformer.cpp", ], proto: { export_proto_headers: true, Loading
tools/aapt2/ResourceTable.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -577,6 +577,7 @@ Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNam std::unique_ptr<ResourceTable> ResourceTable::Clone() const { std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>(); CloningValueTransformer cloner(&new_table->string_pool); for (const auto& pkg : packages) { ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name); for (const auto& type : pkg->types) { Loading @@ -593,7 +594,7 @@ std::unique_ptr<ResourceTable> ResourceTable::Clone() const { for (const auto& config_value : entry->values) { ResourceConfigValue* new_value = new_entry->FindOrCreateValue(config_value->config, config_value->product); new_value->value.reset(config_value->value->Clone(&new_table->string_pool)); new_value->value = config_value->value->Transform(cloner); } } } Loading
tools/aapt2/ResourceValues.cpp +111 −88 Original line number Diff line number Diff line Loading @@ -47,6 +47,14 @@ std::ostream& operator<<(std::ostream& out, const Value& value) { return out; } std::unique_ptr<Value> Value::Transform(ValueTransformer& transformer) const { return std::unique_ptr<Value>(this->TransformValueImpl(transformer)); } std::unique_ptr<Item> Item::Transform(ValueTransformer& transformer) const { return std::unique_ptr<Item>(this->TransformItemImpl(transformer)); } template <typename Derived> void BaseValue<Derived>::Accept(ValueVisitor* visitor) { visitor->Visit(static_cast<Derived*>(this)); Loading Loading @@ -77,13 +85,6 @@ bool RawString::Equals(const Value* value) const { return *this->value == *other->value; } RawString* RawString::Clone(StringPool* new_pool) const { RawString* rs = new RawString(new_pool->MakeRef(value)); rs->comment_ = comment_; rs->source_ = source_; return rs; } bool RawString::Flatten(android::Res_value* out_value) const { out_value->dataType = android::Res_value::TYPE_STRING; out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index())); Loading Loading @@ -136,10 +137,6 @@ bool Reference::Flatten(android::Res_value* out_value) const { return true; } Reference* Reference::Clone(StringPool* /*new_pool*/) const { return new Reference(*this); } void Reference::Print(std::ostream* out) const { if (reference_type == Type::kResource) { *out << "(reference) @"; Loading Loading @@ -220,10 +217,6 @@ bool Id::Flatten(android::Res_value* out) const { return true; } Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); } void Id::Print(std::ostream* out) const { *out << "(id)"; } Loading Loading @@ -266,14 +259,6 @@ bool String::Flatten(android::Res_value* out_value) const { return true; } String* String::Clone(StringPool* new_pool) const { String* str = new String(new_pool->MakeRef(value)); str->comment_ = comment_; str->source_ = source_; str->untranslatable_sections = untranslatable_sections; return str; } void String::Print(std::ostream* out) const { *out << "(string) \"" << *value << "\""; } Loading Loading @@ -321,14 +306,6 @@ bool StyledString::Flatten(android::Res_value* out_value) const { return true; } StyledString* StyledString::Clone(StringPool* new_pool) const { StyledString* str = new StyledString(new_pool->MakeRef(value)); str->comment_ = comment_; str->source_ = source_; str->untranslatable_sections = untranslatable_sections; return str; } void StyledString::Print(std::ostream* out) const { *out << "(styled string) \"" << value->value << "\""; for (const StringPool::Span& span : value->spans) { Loading Loading @@ -357,15 +334,6 @@ bool FileReference::Flatten(android::Res_value* out_value) const { return true; } FileReference* FileReference::Clone(StringPool* new_pool) const { FileReference* fr = new FileReference(new_pool->MakeRef(path)); fr->file = file; fr->type = type; fr->comment_ = comment_; fr->source_ = source_; return fr; } void FileReference::Print(std::ostream* out) const { *out << "(file) " << *path; switch (type) { Loading Loading @@ -406,10 +374,6 @@ bool BinaryPrimitive::Flatten(::android::Res_value* out_value) const { return true; } BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const { return new BinaryPrimitive(*this); } void BinaryPrimitive::Print(std::ostream* out) const { *out << StringPrintf("(primitive) type=0x%02x data=0x%08x", value.dataType, value.data); } Loading Loading @@ -587,10 +551,6 @@ bool Attribute::IsCompatibleWith(const Attribute& attr) const { return this_type_mask == that_type_mask; } Attribute* Attribute::Clone(StringPool* /*new_pool*/) const { return new Attribute(*this); } std::string Attribute::MaskString() const { if (type_mask == android::ResTable_map::TYPE_ANY) { return "any"; Loading Loading @@ -893,18 +853,6 @@ bool Style::Equals(const Value* value) const { }); } Style* Style::Clone(StringPool* new_pool) const { Style* style = new Style(); style->parent = parent; style->parent_inferred = parent_inferred; style->comment_ = comment_; style->source_ = source_; for (auto& entry : entries) { style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))}); } return style; } void Style::Print(std::ostream* out) const { *out << "(style) "; if (parent && parent.value().name) { Loading @@ -920,7 +868,8 @@ void Style::Print(std::ostream* out) const { Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) { Style::Entry cloned_entry{entry.key}; if (entry.value != nullptr) { cloned_entry.value.reset(entry.value->Clone(pool)); CloningValueTransformer cloner(pool); cloned_entry.value = entry.value->Transform(cloner); } return cloned_entry; } Loading Loading @@ -993,16 +942,6 @@ bool Array::Equals(const Value* value) const { }); } Array* Array::Clone(StringPool* new_pool) const { Array* array = new Array(); array->comment_ = comment_; array->source_ = source_; for (auto& item : elements) { array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool))); } return array; } void Array::Print(std::ostream* out) const { *out << "(array) [" << util::Joiner(elements, ", ") << "]"; } Loading Loading @@ -1030,19 +969,6 @@ bool Plural::Equals(const Value* value) const { return true; } Plural* Plural::Clone(StringPool* new_pool) const { Plural* p = new Plural(); p->comment_ = comment_; p->source_ = source_; const size_t count = values.size(); for (size_t i = 0; i < count; i++) { if (values[i]) { p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool)); } } return p; } void Plural::Print(std::ostream* out) const { *out << "(plural)"; if (values[Zero]) { Loading Loading @@ -1086,10 +1012,6 @@ bool Styleable::Equals(const Value* value) const { }); } Styleable* Styleable::Clone(StringPool* /*new_pool*/) const { return new Styleable(*this); } void Styleable::Print(std::ostream* out) const { *out << "(styleable) " << " [" << util::Joiner(entries, ", ") << "]"; Loading Loading @@ -1126,4 +1048,105 @@ void Styleable::MergeWith(Styleable* other) { entries.insert(entries.end(), references.begin(), references.end()); } template <typename T> std::unique_ptr<T> CopyValueFields(std::unique_ptr<T> new_value, const T* value) { new_value->SetSource(value->GetSource()); new_value->SetComment(value->GetComment()); return new_value; } CloningValueTransformer::CloningValueTransformer(StringPool* new_pool) : ValueTransformer(new_pool) { } std::unique_ptr<Reference> CloningValueTransformer::TransformDerived(const Reference* value) { return std::make_unique<Reference>(*value); } std::unique_ptr<Id> CloningValueTransformer::TransformDerived(const Id* value) { return std::make_unique<Id>(*value); } std::unique_ptr<RawString> CloningValueTransformer::TransformDerived(const RawString* value) { auto new_value = std::make_unique<RawString>(pool_->MakeRef(value->value)); return CopyValueFields(std::move(new_value), value); } std::unique_ptr<String> CloningValueTransformer::TransformDerived(const String* value) { auto new_value = std::make_unique<String>(pool_->MakeRef(value->value)); new_value->untranslatable_sections = value->untranslatable_sections; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<StyledString> CloningValueTransformer::TransformDerived(const StyledString* value) { auto new_value = std::make_unique<StyledString>(pool_->MakeRef(value->value)); new_value->untranslatable_sections = value->untranslatable_sections; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<FileReference> CloningValueTransformer::TransformDerived( const FileReference* value) { auto new_value = std::make_unique<FileReference>(pool_->MakeRef(value->path)); new_value->file = value->file; new_value->type = value->type; return CopyValueFields(std::move(new_value), value); } std::unique_ptr<BinaryPrimitive> CloningValueTransformer::TransformDerived( const BinaryPrimitive* value) { return std::make_unique<BinaryPrimitive>(*value); } std::unique_ptr<Attribute> CloningValueTransformer::TransformDerived(const Attribute* value) { auto new_value = std::make_unique<Attribute>(); new_value->type_mask = value->type_mask; new_value->min_int = value->min_int; new_value->max_int = value->max_int; for (const Attribute::Symbol& s : value->symbols) { new_value->symbols.emplace_back(Attribute::Symbol{ .symbol = *s.symbol.Transform(*this), .value = s.value, .type = s.type, }); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Style> CloningValueTransformer::TransformDerived(const Style* value) { auto new_value = std::make_unique<Style>(); new_value->parent = value->parent; new_value->parent_inferred = value->parent_inferred; for (auto& entry : value->entries) { new_value->entries.push_back(Style::Entry{entry.key, entry.value->Transform(*this)}); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Array> CloningValueTransformer::TransformDerived(const Array* value) { auto new_value = std::make_unique<Array>(); for (auto& item : value->elements) { new_value->elements.emplace_back(item->Transform(*this)); } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Plural> CloningValueTransformer::TransformDerived(const Plural* value) { auto new_value = std::make_unique<Plural>(); const size_t count = value->values.size(); for (size_t i = 0; i < count; i++) { if (value->values[i]) { new_value->values[i] = value->values[i]->Transform(*this); } } return CopyValueFields(std::move(new_value), value); } std::unique_ptr<Styleable> CloningValueTransformer::TransformDerived(const Styleable* value) { auto new_value = std::make_unique<Styleable>(); for (const Reference& s : value->entries) { new_value->entries.emplace_back(*s.Transform(*this)); } return CopyValueFields(std::move(new_value), value); } } // namespace aapt
tools/aapt2/ResourceValues.h +41 −30 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "Diagnostics.h" #include "Resource.h" #include "StringPool.h" #include "ValueTransformer.h" #include "io/File.h" #include "text/Printer.h" #include "util/Maybe.h" Loading Loading @@ -100,9 +101,8 @@ class Value { // Calls the appropriate overload of ConstValueVisitor. virtual void Accept(ConstValueVisitor* visitor) const = 0; // Clone the value. `new_pool` is the new StringPool that // any resources with strings should use when copying their string. virtual Value* Clone(StringPool* new_pool) const = 0; // Transform this Value into another Value using the transformer. std::unique_ptr<Value> Transform(ValueTransformer& transformer) const; // Human readable printout of this value. virtual void Print(std::ostream* out) const = 0; Loading @@ -118,6 +118,9 @@ class Value { std::string comment_; bool weak_ = false; bool translatable_ = true; private: virtual Value* TransformValueImpl(ValueTransformer& transformer) const = 0; }; // Inherit from this to get visitor accepting implementations for free. Loading @@ -129,12 +132,15 @@ struct BaseValue : public Value { // A resource item with a single value. This maps to android::ResTable_entry. struct Item : public Value { // Clone the Item. virtual Item* Clone(StringPool* new_pool) const override = 0; // Fills in an android::Res_value structure with this Item's binary representation. // Returns false if an error occurred. virtual bool Flatten(android::Res_value* out_value) const = 0; // Transform this Item into another Item using the transformer. std::unique_ptr<Item> Transform(ValueTransformer& transformer) const; private: virtual Item* TransformItemImpl(ValueTransformer& transformer) const = 0; }; // Inherit from this to get visitor accepting implementations for free. Loading @@ -147,7 +153,7 @@ struct BaseItem : public Item { // A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE. // A reference can be symbolic (with the name set to a valid resource name) or be // numeric (the id is set to a valid resource ID). struct Reference : public BaseItem<Reference> { struct Reference : public TransformableItem<Reference, BaseItem<Reference>> { enum class Type { kResource, kAttribute, Loading @@ -166,7 +172,6 @@ struct Reference : public BaseItem<Reference> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; Reference* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; Loading @@ -178,27 +183,25 @@ bool operator<(const Reference&, const Reference&); bool operator==(const Reference&, const Reference&); // An ID resource. Has no real value, just a place holder. struct Id : public BaseItem<Id> { struct Id : public TransformableItem<Id, BaseItem<Id>> { Id() { weak_ = true; } bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out) const override; Id* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; // A raw, unprocessed string. This may contain quotations, escape sequences, and whitespace. // This shall *NOT* end up in the final resource table. struct RawString : public BaseItem<RawString> { struct RawString : public TransformableItem<RawString, BaseItem<RawString>> { StringPool::Ref value; explicit RawString(const StringPool::Ref& ref); bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; RawString* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; Loading @@ -220,7 +223,7 @@ inline bool operator!=(const UntranslatableSection& a, const UntranslatableSecti return a.start != b.start || a.end != b.end; } struct String : public BaseItem<String> { struct String : public TransformableItem<String, BaseItem<String>> { StringPool::Ref value; // Sections of the string to NOT translate. Mainly used Loading @@ -232,12 +235,11 @@ struct String : public BaseItem<String> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; String* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; }; struct StyledString : public BaseItem<StyledString> { struct StyledString : public TransformableItem<StyledString, BaseItem<StyledString>> { StringPool::StyleRef value; // Sections of the string to NOT translate. Mainly used Loading @@ -249,11 +251,10 @@ struct StyledString : public BaseItem<StyledString> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; StyledString* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct FileReference : public BaseItem<FileReference> { struct FileReference : public TransformableItem<FileReference, BaseItem<FileReference>> { StringPool::Ref path; // A handle to the file object from which this file can be read. Loading @@ -269,12 +270,11 @@ struct FileReference : public BaseItem<FileReference> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; FileReference* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; // Represents any other android::Res_value. struct BinaryPrimitive : public BaseItem<BinaryPrimitive> { struct BinaryPrimitive : public TransformableItem<BinaryPrimitive, BaseItem<BinaryPrimitive>> { android::Res_value value; BinaryPrimitive() = default; Loading @@ -283,12 +283,11 @@ struct BinaryPrimitive : public BaseItem<BinaryPrimitive> { bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; BinaryPrimitive* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; void PrettyPrint(text::Printer* printer) const override; }; struct Attribute : public BaseValue<Attribute> { struct Attribute : public TransformableValue<Attribute, BaseValue<Attribute>> { struct Symbol { Reference symbol; uint32_t value; Loading @@ -311,13 +310,12 @@ struct Attribute : public BaseValue<Attribute> { // TYPE_ENUMS are never compatible. bool IsCompatibleWith(const Attribute& attr) const; Attribute* Clone(StringPool* new_pool) const override; std::string MaskString() const; void Print(std::ostream* out) const override; bool Matches(const Item& item, DiagMessage* out_msg = nullptr) const; }; struct Style : public BaseValue<Style> { struct Style : public TransformableValue<Style, BaseValue<Style>> { struct Entry { Reference key; std::unique_ptr<Item> value; Loading @@ -333,7 +331,6 @@ struct Style : public BaseValue<Style> { std::vector<Entry> entries; bool Equals(const Value* value) const override; Style* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; // Merges `style` into this Style. All identical attributes of `style` take precedence, including Loading @@ -341,29 +338,26 @@ struct Style : public BaseValue<Style> { void MergeWith(Style* style, StringPool* pool); }; struct Array : public BaseValue<Array> { struct Array : public TransformableValue<Array, BaseValue<Array>> { std::vector<std::unique_ptr<Item>> elements; bool Equals(const Value* value) const override; Array* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct Plural : public BaseValue<Plural> { struct Plural : public TransformableValue<Plural, BaseValue<Plural>> { enum { Zero = 0, One, Two, Few, Many, Other, Count }; std::array<std::unique_ptr<Item>, Count> values; bool Equals(const Value* value) const override; Plural* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; }; struct Styleable : public BaseValue<Styleable> { struct Styleable : public TransformableValue<Styleable, BaseValue<Styleable>> { std::vector<Reference> entries; bool Equals(const Value* value) const override; Styleable* Clone(StringPool* newPool) const override; void Print(std::ostream* out) const override; void MergeWith(Styleable* styleable); }; Loading @@ -379,6 +373,23 @@ typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type o return out; } struct CloningValueTransformer : public ValueTransformer { explicit CloningValueTransformer(StringPool* new_pool); std::unique_ptr<Reference> TransformDerived(const Reference* value) override; std::unique_ptr<Id> TransformDerived(const Id* value) override; std::unique_ptr<RawString> TransformDerived(const RawString* value) override; std::unique_ptr<String> TransformDerived(const String* value) override; std::unique_ptr<StyledString> TransformDerived(const StyledString* value) override; std::unique_ptr<FileReference> TransformDerived(const FileReference* value) override; std::unique_ptr<BinaryPrimitive> TransformDerived(const BinaryPrimitive* value) override; std::unique_ptr<Attribute> TransformDerived(const Attribute* value) override; std::unique_ptr<Style> TransformDerived(const Style* value) override; std::unique_ptr<Array> TransformDerived(const Array* value) override; std::unique_ptr<Plural> TransformDerived(const Plural* value) override; std::unique_ptr<Styleable> TransformDerived(const Styleable* value) override; }; } // namespace aapt #endif // AAPT_RESOURCE_VALUES_H
tools/aapt2/ResourceValues_test.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ TEST(ResourceValuesTest, PluralClone) { a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one")); a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other")); std::unique_ptr<Plural> b(a.Clone(&pool)); CloningValueTransformer cloner(&pool); std::unique_ptr<Plural> b(a.Transform(cloner)); EXPECT_TRUE(a.Equals(b.get())); } Loading Loading @@ -97,7 +98,8 @@ TEST(ResourceValuesTest, ArrayClone) { a.elements.push_back(util::make_unique<String>(pool.MakeRef("one"))); a.elements.push_back(util::make_unique<String>(pool.MakeRef("two"))); std::unique_ptr<Array> b(a.Clone(&pool)); CloningValueTransformer cloner(&pool); std::unique_ptr<Array> b(a.Transform(cloner)); EXPECT_TRUE(a.Equals(b.get())); } Loading Loading @@ -160,7 +162,8 @@ TEST(ResourceValuesTest, StyleClone) { .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2")) .Build(); std::unique_ptr<Style> b(a->Clone(nullptr)); CloningValueTransformer cloner(nullptr); std::unique_ptr<Style> b(a->Transform(cloner)); EXPECT_TRUE(a->Equals(b.get())); } Loading @@ -174,7 +177,8 @@ TEST(ResourcesValuesTest, StringClones) { EXPECT_THAT(pool_a.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en"))); EXPECT_THAT(pool_a.strings()[0]->value, StrEq("hello")); std::unique_ptr<String> str_b(str_a.Clone(&pool_b)); CloningValueTransformer cloner(&pool_b); str_a.Transform(cloner); ASSERT_THAT(pool_b, SizeIs(1u)); EXPECT_THAT(pool_b.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en"))); EXPECT_THAT(pool_b.strings()[0]->value, StrEq("hello")); Loading