Aapt2 ValueTransformer
For future macro support, aapt2 must be able to convert Reference values into other Value types. Currently a DescendingValueVisitor is used to visit all of the References in a ResourceTable or a compiled XML file to set their resource ids during the link phase. This was fine since we were only mutating the resource id of the visited Reference. A macro may reference a String, BinaryPrimitive, or any other Item type. During the link phase, we will need to transform references to macros into the values of the macros. The only parameter in the methods of the ValueVisitor interface is a raw pointer to the type being visited. The visitor interface does not support reassigning the visited type to a different type. ValueTransformer is a new interface for consuming a Value type and transforming it into a compatible Value type. This change refactors Value::Clone to use this interface. Bug: 175616308 Test: aapt2_tests Change-Id: Ic1b9d718b932c208764114cd9c74d880e189ccb0
This commit is contained in:
@@ -162,6 +162,7 @@ cc_library_host_static {
|
||||
"Configuration.proto",
|
||||
"Resources.proto",
|
||||
"ResourcesInternal.proto",
|
||||
"ValueTransformer.cpp",
|
||||
],
|
||||
proto: {
|
||||
export_proto_headers: true,
|
||||
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
@@ -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()));
|
||||
@@ -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) @";
|
||||
@@ -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)";
|
||||
}
|
||||
@@ -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 << "\"";
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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";
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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, ", ") << "]";
|
||||
}
|
||||
@@ -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]) {
|
||||
@@ -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, ", ") << "]";
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
|
||||
50
tools/aapt2/ValueTransformer.cpp
Normal file
50
tools/aapt2/ValueTransformer.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ValueTransformer.h"
|
||||
|
||||
#include "ResourceValues.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
#define VALUE_CREATE_VALUE_DECL(T) \
|
||||
std::unique_ptr<Value> ValueTransformer::TransformValue(const T* value) { \
|
||||
return TransformDerived(value); \
|
||||
}
|
||||
|
||||
#define VALUE_CREATE_ITEM_DECL(T) \
|
||||
std::unique_ptr<Item> ValueTransformer::TransformItem(const T* value) { \
|
||||
return TransformDerived(value); \
|
||||
} \
|
||||
std::unique_ptr<Value> ValueTransformer::TransformValue(const T* value) { \
|
||||
return TransformItem(value); \
|
||||
}
|
||||
|
||||
VALUE_CREATE_ITEM_DECL(Id);
|
||||
VALUE_CREATE_ITEM_DECL(Reference);
|
||||
VALUE_CREATE_ITEM_DECL(RawString);
|
||||
VALUE_CREATE_ITEM_DECL(String);
|
||||
VALUE_CREATE_ITEM_DECL(StyledString);
|
||||
VALUE_CREATE_ITEM_DECL(FileReference);
|
||||
VALUE_CREATE_ITEM_DECL(BinaryPrimitive);
|
||||
|
||||
VALUE_CREATE_VALUE_DECL(Attribute);
|
||||
VALUE_CREATE_VALUE_DECL(Style);
|
||||
VALUE_CREATE_VALUE_DECL(Array);
|
||||
VALUE_CREATE_VALUE_DECL(Plural);
|
||||
VALUE_CREATE_VALUE_DECL(Styleable);
|
||||
|
||||
} // namespace aapt
|
||||
128
tools/aapt2/ValueTransformer.h
Normal file
128
tools/aapt2/ValueTransformer.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AAPT_VALUE_TRANSFORMER_H
|
||||
#define AAPT_VALUE_TRANSFORMER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "StringPool.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
class Value;
|
||||
struct Item;
|
||||
struct Reference;
|
||||
struct Id;
|
||||
struct RawString;
|
||||
struct String;
|
||||
struct StyledString;
|
||||
struct FileReference;
|
||||
struct BinaryPrimitive;
|
||||
struct Attribute;
|
||||
struct Style;
|
||||
struct Array;
|
||||
struct Plural;
|
||||
struct Styleable;
|
||||
|
||||
#define AAPT_TRANSFORM_VALUE(T) \
|
||||
virtual std::unique_ptr<T> TransformDerived(const T* value) = 0; \
|
||||
virtual std::unique_ptr<Value> TransformValue(const T* value);
|
||||
|
||||
#define AAPT_TRANSFORM_ITEM(T) \
|
||||
virtual std::unique_ptr<Item> TransformItem(const T* value); \
|
||||
AAPT_TRANSFORM_VALUE(T)
|
||||
|
||||
/**
|
||||
* An interface for consuming a Value type and transforming it into another Value.
|
||||
*
|
||||
* The interface defines 2 methods for each type (T) that inherits from TransformableValue:
|
||||
* std::unique_ptr<T> TransformDerived(const T*)
|
||||
* std::unique_ptr<Value> TransformValue(const T*)
|
||||
*
|
||||
* The interface defines 3 method for each type (T) that inherits from TransformableItem:
|
||||
* std::unique_ptr<T> TransformDerived(const T*)
|
||||
* std::unique_ptr<Item> TransformItem(const T*)
|
||||
* std::unique_ptr<Value> TransformValue(const T*)
|
||||
*
|
||||
* TransformDerived is invoked when Transform is invoked on the derived type T.
|
||||
* TransformItem is invoked when Transform is invoked on an Item type.
|
||||
* TransformValue is invoked when Transform is invoked on a Value type.
|
||||
*
|
||||
* ValueTransformerImpl transformer(&string_pool);
|
||||
* T* derived = ...;
|
||||
* std::unique_ptr<T> new_type = derived->Transform(transformer); // Invokes TransformDerived
|
||||
*
|
||||
* Item* item = derived;
|
||||
* std::unique_ptr<Item> new_item = item->TransformItem(transformer); // Invokes TransformItem
|
||||
*
|
||||
* Value* value = item;
|
||||
* std::unique_ptr<Value> new_value = value->TransformValue(transformer); // Invokes TransformValue
|
||||
*
|
||||
* For types that inherit from AbstractTransformableItem, the default implementation of
|
||||
* TransformValue invokes TransformItem which invokes TransformDerived.
|
||||
*
|
||||
* For types that inherit from AbstractTransformableValue, the default implementation of
|
||||
* TransformValue invokes TransformDerived.
|
||||
*/
|
||||
struct ValueTransformer {
|
||||
// `new_pool` is the new StringPool that newly created Values should use for string storing string
|
||||
// values.
|
||||
explicit ValueTransformer(StringPool* new_pool);
|
||||
virtual ~ValueTransformer() = default;
|
||||
|
||||
AAPT_TRANSFORM_ITEM(Id);
|
||||
AAPT_TRANSFORM_ITEM(Reference);
|
||||
AAPT_TRANSFORM_ITEM(RawString);
|
||||
AAPT_TRANSFORM_ITEM(String);
|
||||
AAPT_TRANSFORM_ITEM(StyledString);
|
||||
AAPT_TRANSFORM_ITEM(FileReference);
|
||||
AAPT_TRANSFORM_ITEM(BinaryPrimitive);
|
||||
|
||||
AAPT_TRANSFORM_VALUE(Attribute);
|
||||
AAPT_TRANSFORM_VALUE(Style);
|
||||
AAPT_TRANSFORM_VALUE(Array);
|
||||
AAPT_TRANSFORM_VALUE(Plural);
|
||||
AAPT_TRANSFORM_VALUE(Styleable);
|
||||
|
||||
protected:
|
||||
StringPool* const pool_;
|
||||
};
|
||||
|
||||
#undef AAPT_TRANSFORM_VALUE
|
||||
#undef AAPT_TRANSFORM_ITEM
|
||||
|
||||
template <typename Derived, typename Base>
|
||||
struct TransformableValue : public Base {
|
||||
// Transform this Derived into another Derived using the transformer.
|
||||
std::unique_ptr<Derived> Transform(ValueTransformer& transformer) const;
|
||||
|
||||
private:
|
||||
Value* TransformValueImpl(ValueTransformer& transformer) const override;
|
||||
};
|
||||
|
||||
template <typename Derived, typename Base>
|
||||
struct TransformableItem : public TransformableValue<Derived, Base> {
|
||||
private:
|
||||
Item* TransformItemImpl(ValueTransformer& transformer) const override;
|
||||
};
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
// Implementation
|
||||
#include "ValueTransformer_inline.h"
|
||||
|
||||
#endif // AAPT_VALUE_TRANSFORMER_H
|
||||
47
tools/aapt2/ValueTransformer_inline.h
Normal file
47
tools/aapt2/ValueTransformer_inline.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AAPT_VALUE_TRANSFORMER_IMPL_H
|
||||
#define AAPT_VALUE_TRANSFORMER_IMPL_H
|
||||
|
||||
namespace aapt {
|
||||
|
||||
inline ValueTransformer::ValueTransformer(StringPool* new_pool) : pool_(new_pool) {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Base>
|
||||
inline std::unique_ptr<Derived> TransformableValue<Derived, Base>::Transform(
|
||||
ValueTransformer& transformer) const {
|
||||
return transformer.TransformDerived(static_cast<const Derived*>(this));
|
||||
}
|
||||
|
||||
template <typename Derived, typename Base>
|
||||
Value* TransformableValue<Derived, Base>::TransformValueImpl(ValueTransformer& transformer) const {
|
||||
auto self = static_cast<const Derived*>(this);
|
||||
auto transformed = transformer.TransformValue(self);
|
||||
return transformed.release();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Base>
|
||||
Item* TransformableItem<Derived, Base>::TransformItemImpl(ValueTransformer& transformer) const {
|
||||
auto self = static_cast<const Derived*>(this);
|
||||
auto transformed = transformer.TransformItem(self);
|
||||
return transformed.release();
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
#endif // AAPT_VALUE_TRANSFORMER_IMPL_H
|
||||
@@ -1656,10 +1656,11 @@ class Linker {
|
||||
<< " with config \"" << config_value->config
|
||||
<< "\" for round icon compatibility");
|
||||
|
||||
auto value = icon_reference->Clone(&table->string_pool);
|
||||
CloningValueTransformer cloner(&table->string_pool);
|
||||
auto value = icon_reference->Transform(cloner);
|
||||
auto round_config_value =
|
||||
round_icon_entry->FindOrCreateValue(config_value->config, config_value->product);
|
||||
round_config_value->value.reset(value);
|
||||
round_config_value->value = std::move(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,7 @@ class Visitor : public ValueVisitor {
|
||||
: pool_(pool), method_(method), localizer_(method) {}
|
||||
|
||||
void Visit(Plural* plural) override {
|
||||
CloningValueTransformer cloner(pool_);
|
||||
std::unique_ptr<Plural> localized = util::make_unique<Plural>();
|
||||
for (size_t i = 0; i < plural->values.size(); i++) {
|
||||
Visitor sub_visitor(pool_, method_);
|
||||
@@ -234,7 +235,7 @@ class Visitor : public ValueVisitor {
|
||||
if (sub_visitor.item) {
|
||||
localized->values[i] = std::move(sub_visitor.item);
|
||||
} else {
|
||||
localized->values[i] = std::unique_ptr<Item>(plural->values[i]->Clone(pool_));
|
||||
localized->values[i] = plural->values[i]->Transform(cloner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +299,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
|
||||
.Build();
|
||||
|
||||
// Add regular entries.
|
||||
CloningValueTransformer cloner(&table->string_pool);
|
||||
int stride = static_cast<int>(1.0f / load);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
const ResourceName name = test::ParseNameOrDie(
|
||||
@@ -308,7 +309,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
|
||||
util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i));
|
||||
CHECK(table->AddResource(NewResourceBuilder(name)
|
||||
.SetId(resid)
|
||||
.SetValue(std::unique_ptr<Value>(value->Clone(nullptr)))
|
||||
.SetValue(std::unique_ptr<Value>(value->Transform(cloner)))
|
||||
.Build(),
|
||||
context->GetDiagnostics()));
|
||||
|
||||
@@ -317,7 +318,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
|
||||
CHECK(table->AddResource(
|
||||
NewResourceBuilder(name)
|
||||
.SetId(resid)
|
||||
.SetValue(std::unique_ptr<Value>(value->Clone(nullptr)), sparse_config)
|
||||
.SetValue(std::unique_ptr<Value>(value->Transform(cloner)), sparse_config)
|
||||
.Build(),
|
||||
context->GetDiagnostics()));
|
||||
}
|
||||
|
||||
@@ -334,11 +334,12 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)
|
||||
styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
|
||||
styleable.SetComment(StringPiece("This is a styleable"));
|
||||
|
||||
CloningValueTransformer cloner(nullptr);
|
||||
std::unique_ptr<ResourceTable> table =
|
||||
test::ResourceTableBuilder()
|
||||
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
|
||||
.AddValue("android:styleable/Container",
|
||||
std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
|
||||
std::unique_ptr<Styleable>(styleable.Transform(cloner)))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<IAaptContext> context =
|
||||
@@ -371,11 +372,12 @@ TEST(JavaClassGeneratorTest, CommentsForStyleableHiddenAttributesAreNotPresent)
|
||||
styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
|
||||
styleable.SetComment(StringPiece("This is a styleable"));
|
||||
|
||||
CloningValueTransformer cloner(nullptr);
|
||||
std::unique_ptr<ResourceTable> table =
|
||||
test::ResourceTableBuilder()
|
||||
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
|
||||
.AddValue("android:styleable/Container",
|
||||
std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
|
||||
std::unique_ptr<Styleable>(styleable.Transform(cloner)))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<IAaptContext> context =
|
||||
|
||||
@@ -72,6 +72,7 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
|
||||
|
||||
bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("AutoVersioner::Consume");
|
||||
CloningValueTransformer cloner(&table->string_pool);
|
||||
for (auto& package : table->packages) {
|
||||
for (auto& type : package->types) {
|
||||
if (type->type != ResourceType::kStyle) {
|
||||
@@ -128,7 +129,7 @@ bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
ConfigDescription new_config(config_value->config);
|
||||
new_config.sdkVersion = static_cast<uint16_t>(min_sdk_stripped.value());
|
||||
|
||||
std::unique_ptr<Style> new_style(style->Clone(&table->string_pool));
|
||||
std::unique_ptr<Style> new_style(style->Transform(cloner));
|
||||
new_style->SetComment(style->GetComment());
|
||||
new_style->SetSource(style->GetSource());
|
||||
|
||||
|
||||
@@ -280,13 +280,13 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
|
||||
}
|
||||
|
||||
// Continue if we're taking the new resource.
|
||||
|
||||
CloningValueTransformer cloner(&main_table_->string_pool);
|
||||
if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
|
||||
std::unique_ptr<FileReference> new_file_ref;
|
||||
if (mangle_package) {
|
||||
new_file_ref = CloneAndMangleFile(src_package->name, *f);
|
||||
} else {
|
||||
new_file_ref = std::unique_ptr<FileReference>(f->Clone(&main_table_->string_pool));
|
||||
new_file_ref = std::unique_ptr<FileReference>(f->Transform(cloner));
|
||||
}
|
||||
dst_config_value->value = std::move(new_file_ref);
|
||||
|
||||
@@ -294,8 +294,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
|
||||
Maybe<std::string> original_comment = (dst_config_value->value)
|
||||
? dst_config_value->value->GetComment() : Maybe<std::string>();
|
||||
|
||||
dst_config_value->value = std::unique_ptr<Value>(
|
||||
src_config_value->value->Clone(&main_table_->string_pool));
|
||||
dst_config_value->value = src_config_value->value->Transform(cloner);
|
||||
|
||||
// Keep the comment from the original resource and ignore all comments from overlaying
|
||||
// resources
|
||||
@@ -323,7 +322,9 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
|
||||
new_file_ref->file = file_ref.file;
|
||||
return new_file_ref;
|
||||
}
|
||||
return std::unique_ptr<FileReference>(file_ref.Clone(&main_table_->string_pool));
|
||||
|
||||
CloningValueTransformer cloner(&main_table_->string_pool);
|
||||
return std::unique_ptr<FileReference>(file_ref.Transform(cloner));
|
||||
}
|
||||
|
||||
bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFile* file) {
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
namespace aapt {
|
||||
|
||||
static xml::Attribute CopyAttr(const xml::Attribute& src, StringPool* out_string_pool) {
|
||||
CloningValueTransformer cloner(out_string_pool);
|
||||
xml::Attribute dst{src.namespace_uri, src.name, src.value, src.compiled_attribute};
|
||||
if (src.compiled_value != nullptr) {
|
||||
dst.compiled_value.reset(src.compiled_value->Clone(out_string_pool));
|
||||
dst.compiled_value = src.compiled_value->Transform(cloner);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
@@ -34,6 +35,7 @@ static xml::Attribute CopyAttr(const xml::Attribute& src, StringPool* out_string
|
||||
// (came from a rule).
|
||||
static bool CopyAttribute(const xml::Attribute& src_attr, bool generated, xml::Element* dst_el,
|
||||
StringPool* out_string_pool) {
|
||||
CloningValueTransformer cloner(out_string_pool);
|
||||
xml::Attribute* dst_attr = dst_el->FindAttribute(src_attr.namespace_uri, src_attr.name);
|
||||
if (dst_attr != nullptr) {
|
||||
if (generated) {
|
||||
@@ -41,7 +43,7 @@ static bool CopyAttribute(const xml::Attribute& src_attr, bool generated, xml::E
|
||||
dst_attr->value = src_attr.value;
|
||||
dst_attr->compiled_attribute = src_attr.compiled_attribute;
|
||||
if (src_attr.compiled_value != nullptr) {
|
||||
dst_attr->compiled_value.reset(src_attr.compiled_value->Clone(out_string_pool));
|
||||
dst_attr->compiled_value = src_attr.compiled_value->Transform(cloner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -158,7 +160,8 @@ static inline std::unique_ptr<Item> CloneIfNotNull(const std::unique_ptr<Item>&
|
||||
if (src == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return std::unique_ptr<Item>(src->Clone(out_string_pool));
|
||||
CloningValueTransformer cloner(out_string_pool);
|
||||
return src->Transform(cloner);
|
||||
}
|
||||
|
||||
std::vector<DegradeResult> DegradeToManyRule::Degrade(const xml::Element& src_el,
|
||||
|
||||
@@ -229,6 +229,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) {
|
||||
for (size_t idx = 0; idx < split_count; idx++) {
|
||||
const SplitConstraints& split_constraint = split_constraints_[idx];
|
||||
ResourceTable* split_table = splits_[idx].get();
|
||||
CloningValueTransformer cloner(&split_table->string_pool);
|
||||
|
||||
// Select the values we want from this entry for this split.
|
||||
SplitValueSelector selector(split_constraint);
|
||||
@@ -254,8 +255,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) {
|
||||
for (ResourceConfigValue* config_value : selected_values) {
|
||||
ResourceConfigValue* new_config_value =
|
||||
split_entry->FindOrCreateValue(config_value->config, config_value->product);
|
||||
new_config_value->value = std::unique_ptr<Value>(
|
||||
config_value->value->Clone(&split_table->string_pool));
|
||||
new_config_value->value = config_value->value->Transform(cloner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,10 +200,11 @@ class StaticSymbolSourceBuilder {
|
||||
|
||||
private:
|
||||
std::unique_ptr<SymbolTable::Symbol> CloneSymbol(SymbolTable::Symbol* sym) {
|
||||
CloningValueTransformer cloner(nullptr);
|
||||
std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
|
||||
clone->id = sym->id;
|
||||
if (sym->attribute) {
|
||||
clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Clone(nullptr));
|
||||
clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Transform(cloner));
|
||||
}
|
||||
clone->is_public = sym->is_public;
|
||||
return clone;
|
||||
|
||||
@@ -374,6 +374,7 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string*
|
||||
|
||||
std::unique_ptr<XmlResource> XmlResource::Clone() const {
|
||||
std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
|
||||
CloningValueTransformer cloner(&cloned->string_pool);
|
||||
if (root != nullptr) {
|
||||
cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
|
||||
dst->attributes.reserve(src.attributes.size());
|
||||
@@ -384,7 +385,7 @@ std::unique_ptr<XmlResource> XmlResource::Clone() const {
|
||||
cloned_attr.value = attr.value;
|
||||
cloned_attr.compiled_attribute = attr.compiled_attribute;
|
||||
if (attr.compiled_value != nullptr) {
|
||||
cloned_attr.compiled_value.reset(attr.compiled_value->Clone(&cloned->string_pool));
|
||||
cloned_attr.compiled_value = attr.compiled_value->Transform(cloner);
|
||||
}
|
||||
dst->attributes.push_back(std::move(cloned_attr));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user