AAPT2: Ensure string pool ordering is compact
Keep styledstrings at the beginning of the StringPool
to reduce the padding in the StyledString array.
Bug:32336940
Test: manual
Change-Id: Iec820c21a54daac40ecc3b2f87517a0f1efc9d3d
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 595fa6f..0dfb01c 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -27,445 +27,460 @@
namespace {
class ReferenceIdToNameVisitor : public ValueVisitor {
-public:
- using ValueVisitor::visit;
+ public:
+ using ValueVisitor::visit;
- explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping) :
- mMapping(mapping) {
- assert(mMapping);
+ explicit ReferenceIdToNameVisitor(
+ const std::map<ResourceId, ResourceNameRef>* mapping)
+ : mMapping(mapping) {
+ assert(mMapping);
+ }
+
+ void visit(Reference* reference) override {
+ if (!reference->id || !reference->id.value().isValid()) {
+ return;
}
- void visit(Reference* reference) override {
- if (!reference->id || !reference->id.value().isValid()) {
- return;
- }
-
- ResourceId id = reference->id.value();
- auto cacheIter = mMapping->find(id);
- if (cacheIter != mMapping->end()) {
- reference->name = cacheIter->second.toResourceName();
- }
+ ResourceId id = reference->id.value();
+ auto cacheIter = mMapping->find(id);
+ if (cacheIter != mMapping->end()) {
+ reference->name = cacheIter->second.toResourceName();
}
+ }
-private:
- const std::map<ResourceId, ResourceNameRef>* mMapping;
+ private:
+ const std::map<ResourceId, ResourceNameRef>* mMapping;
};
class PackagePbDeserializer {
-public:
- PackagePbDeserializer(const android::ResStringPool* valuePool,
- const android::ResStringPool* sourcePool,
- const android::ResStringPool* symbolPool,
- const Source& source, IDiagnostics* diag) :
- mValuePool(valuePool), mSourcePool(sourcePool), mSymbolPool(symbolPool),
- mSource(source), mDiag(diag) {
+ public:
+ PackagePbDeserializer(const android::ResStringPool* valuePool,
+ const android::ResStringPool* sourcePool,
+ const android::ResStringPool* symbolPool,
+ const Source& source, IDiagnostics* diag)
+ : mValuePool(valuePool),
+ mSourcePool(sourcePool),
+ mSymbolPool(symbolPool),
+ mSource(source),
+ mDiag(diag) {}
+
+ public:
+ bool deserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
+ Maybe<uint8_t> id;
+ if (pbPackage.has_package_id()) {
+ id = static_cast<uint8_t>(pbPackage.package_id());
}
-public:
- bool deserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
- Maybe<uint8_t> id;
- if (pbPackage.has_package_id()) {
- id = static_cast<uint8_t>(pbPackage.package_id());
- }
+ std::map<ResourceId, ResourceNameRef> idIndex;
- std::map<ResourceId, ResourceNameRef> idIndex;
+ ResourceTablePackage* pkg =
+ table->createPackage(pbPackage.package_name(), id);
+ for (const pb::Type& pbType : pbPackage.types()) {
+ const ResourceType* resType = parseResourceType(pbType.name());
+ if (!resType) {
+ mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name()
+ << "'");
+ return {};
+ }
- ResourceTablePackage* pkg = table->createPackage(pbPackage.package_name(), id);
- for (const pb::Type& pbType : pbPackage.types()) {
- const ResourceType* resType = parseResourceType(pbType.name());
- if (!resType) {
- mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name() << "'");
- return {};
+ ResourceTableType* type = pkg->findOrCreateType(*resType);
+
+ for (const pb::Entry& pbEntry : pbType.entries()) {
+ ResourceEntry* entry = type->findOrCreateEntry(pbEntry.name());
+
+ // Deserialize the symbol status (public/private with source and
+ // comments).
+ if (pbEntry.has_symbol_status()) {
+ const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
+ if (pbStatus.has_source()) {
+ deserializeSourceFromPb(pbStatus.source(), *mSourcePool,
+ &entry->symbolStatus.source);
+ }
+
+ if (pbStatus.has_comment()) {
+ entry->symbolStatus.comment = pbStatus.comment();
+ }
+
+ SymbolState visibility =
+ deserializeVisibilityFromPb(pbStatus.visibility());
+ entry->symbolStatus.state = visibility;
+
+ if (visibility == SymbolState::kPublic) {
+ // This is a public symbol, we must encode the ID now if there is
+ // one.
+ if (pbEntry.has_id()) {
+ entry->id = static_cast<uint16_t>(pbEntry.id());
}
- ResourceTableType* type = pkg->findOrCreateType(*resType);
-
- for (const pb::Entry& pbEntry : pbType.entries()) {
- ResourceEntry* entry = type->findOrCreateEntry(pbEntry.name());
-
- // Deserialize the symbol status (public/private with source and comments).
- if (pbEntry.has_symbol_status()) {
- const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
- if (pbStatus.has_source()) {
- deserializeSourceFromPb(pbStatus.source(), *mSourcePool,
- &entry->symbolStatus.source);
- }
-
- if (pbStatus.has_comment()) {
- entry->symbolStatus.comment = pbStatus.comment();
- }
-
- SymbolState visibility = deserializeVisibilityFromPb(pbStatus.visibility());
- entry->symbolStatus.state = visibility;
-
- if (visibility == SymbolState::kPublic) {
- // This is a public symbol, we must encode the ID now if there is one.
- if (pbEntry.has_id()) {
- entry->id = static_cast<uint16_t>(pbEntry.id());
- }
-
- if (type->symbolStatus.state != SymbolState::kPublic) {
- // If the type has not been made public, do so now.
- type->symbolStatus.state = SymbolState::kPublic;
- if (pbType.has_id()) {
- type->id = static_cast<uint8_t>(pbType.id());
- }
- }
- } else if (visibility == SymbolState::kPrivate) {
- if (type->symbolStatus.state == SymbolState::kUndefined) {
- type->symbolStatus.state = SymbolState::kPrivate;
- }
- }
- }
-
- ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
- if (resId.isValid()) {
- idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
- }
-
- for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
- const pb::ConfigDescription& pbConfig = pbConfigValue.config();
-
- ConfigDescription config;
- if (!deserializeConfigDescriptionFromPb(pbConfig, &config)) {
- mDiag->error(DiagMessage(mSource) << "invalid configuration");
- return {};
- }
-
- ResourceConfigValue* configValue = entry->findOrCreateValue(config,
- pbConfig.product());
- if (configValue->value) {
- // Duplicate config.
- mDiag->error(DiagMessage(mSource) << "duplicate configuration");
- return {};
- }
-
- configValue->value = deserializeValueFromPb(pbConfigValue.value(),
- config, &table->stringPool);
- if (!configValue->value) {
- return {};
- }
- }
+ if (type->symbolStatus.state != SymbolState::kPublic) {
+ // If the type has not been made public, do so now.
+ type->symbolStatus.state = SymbolState::kPublic;
+ if (pbType.has_id()) {
+ type->id = static_cast<uint8_t>(pbType.id());
+ }
}
+ } else if (visibility == SymbolState::kPrivate) {
+ if (type->symbolStatus.state == SymbolState::kUndefined) {
+ type->symbolStatus.state = SymbolState::kPrivate;
+ }
+ }
}
- ReferenceIdToNameVisitor visitor(&idIndex);
- visitAllValuesInPackage(pkg, &visitor);
- return true;
+ ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
+ if (resId.isValid()) {
+ idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
+ }
+
+ for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
+ const pb::ConfigDescription& pbConfig = pbConfigValue.config();
+
+ ConfigDescription config;
+ if (!deserializeConfigDescriptionFromPb(pbConfig, &config)) {
+ mDiag->error(DiagMessage(mSource) << "invalid configuration");
+ return {};
+ }
+
+ ResourceConfigValue* configValue =
+ entry->findOrCreateValue(config, pbConfig.product());
+ if (configValue->value) {
+ // Duplicate config.
+ mDiag->error(DiagMessage(mSource) << "duplicate configuration");
+ return {};
+ }
+
+ configValue->value = deserializeValueFromPb(
+ pbConfigValue.value(), config, &table->stringPool);
+ if (!configValue->value) {
+ return {};
+ }
+ }
+ }
}
-private:
- std::unique_ptr<Item> deserializeItemFromPb(const pb::Item& pbItem,
+ ReferenceIdToNameVisitor visitor(&idIndex);
+ visitAllValuesInPackage(pkg, &visitor);
+ return true;
+ }
+
+ private:
+ std::unique_ptr<Item> deserializeItemFromPb(const pb::Item& pbItem,
+ const ConfigDescription& config,
+ StringPool* pool) {
+ if (pbItem.has_ref()) {
+ const pb::Reference& pbRef = pbItem.ref();
+ std::unique_ptr<Reference> ref = util::make_unique<Reference>();
+ if (!deserializeReferenceFromPb(pbRef, ref.get())) {
+ return {};
+ }
+ return std::move(ref);
+
+ } else if (pbItem.has_prim()) {
+ const pb::Primitive& pbPrim = pbItem.prim();
+ android::Res_value prim = {};
+ prim.dataType = static_cast<uint8_t>(pbPrim.type());
+ prim.data = pbPrim.data();
+ return util::make_unique<BinaryPrimitive>(prim);
+
+ } else if (pbItem.has_id()) {
+ return util::make_unique<Id>();
+
+ } else if (pbItem.has_str()) {
+ const uint32_t idx = pbItem.str().idx();
+ const std::string str = util::getString(*mValuePool, idx);
+
+ const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
+ if (spans && spans->name.index != android::ResStringPool_span::END) {
+ StyleString styleStr = {str};
+ while (spans->name.index != android::ResStringPool_span::END) {
+ styleStr.spans.push_back(
+ Span{util::getString(*mValuePool, spans->name.index),
+ spans->firstChar, spans->lastChar});
+ spans++;
+ }
+ return util::make_unique<StyledString>(pool->makeRef(
+ styleStr,
+ StringPool::Context(StringPool::Context::kStylePriority, config)));
+ }
+ return util::make_unique<String>(
+ pool->makeRef(str, StringPool::Context(config)));
+
+ } else if (pbItem.has_raw_str()) {
+ const uint32_t idx = pbItem.raw_str().idx();
+ const std::string str = util::getString(*mValuePool, idx);
+ return util::make_unique<RawString>(
+ pool->makeRef(str, StringPool::Context(config)));
+
+ } else if (pbItem.has_file()) {
+ const uint32_t idx = pbItem.file().path_idx();
+ const std::string str = util::getString(*mValuePool, idx);
+ return util::make_unique<FileReference>(pool->makeRef(
+ str,
+ StringPool::Context(StringPool::Context::kHighPriority, config)));
+
+ } else {
+ mDiag->error(DiagMessage(mSource) << "unknown item");
+ }
+ return {};
+ }
+
+ std::unique_ptr<Value> deserializeValueFromPb(const pb::Value& pbValue,
const ConfigDescription& config,
StringPool* pool) {
- if (pbItem.has_ref()) {
- const pb::Reference& pbRef = pbItem.ref();
- std::unique_ptr<Reference> ref = util::make_unique<Reference>();
- if (!deserializeReferenceFromPb(pbRef, ref.get())) {
- return {};
- }
- return std::move(ref);
+ const bool isWeak = pbValue.has_weak() ? pbValue.weak() : false;
- } else if (pbItem.has_prim()) {
- const pb::Primitive& pbPrim = pbItem.prim();
- android::Res_value prim = {};
- prim.dataType = static_cast<uint8_t>(pbPrim.type());
- prim.data = pbPrim.data();
- return util::make_unique<BinaryPrimitive>(prim);
-
- } else if (pbItem.has_id()) {
- return util::make_unique<Id>();
-
- } else if (pbItem.has_str()) {
- const uint32_t idx = pbItem.str().idx();
- const std::string str = util::getString(*mValuePool, idx);
-
- const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
- if (spans && spans->name.index != android::ResStringPool_span::END) {
- StyleString styleStr = { str };
- while (spans->name.index != android::ResStringPool_span::END) {
- styleStr.spans.push_back(Span{
- util::getString(*mValuePool, spans->name.index),
- spans->firstChar,
- spans->lastChar
- });
- spans++;
- }
- return util::make_unique<StyledString>(
- pool->makeRef(styleStr, StringPool::Context{ 1, config }));
- }
- return util::make_unique<String>(
- pool->makeRef(str, StringPool::Context{ 1, config }));
-
- } else if (pbItem.has_raw_str()) {
- const uint32_t idx = pbItem.raw_str().idx();
- const std::string str = util::getString(*mValuePool, idx);
- return util::make_unique<RawString>(
- pool->makeRef(str, StringPool::Context{ 1, config }));
-
- } else if (pbItem.has_file()) {
- const uint32_t idx = pbItem.file().path_idx();
- const std::string str = util::getString(*mValuePool, idx);
- return util::make_unique<FileReference>(
- pool->makeRef(str, StringPool::Context{ 0, config }));
-
- } else {
- mDiag->error(DiagMessage(mSource) << "unknown item");
- }
+ std::unique_ptr<Value> value;
+ if (pbValue.has_item()) {
+ value = deserializeItemFromPb(pbValue.item(), config, pool);
+ if (!value) {
return {};
- }
+ }
- std::unique_ptr<Value> deserializeValueFromPb(const pb::Value& pbValue,
- const ConfigDescription& config,
- StringPool* pool) {
- const bool isWeak = pbValue.has_weak() ? pbValue.weak() : false;
-
- std::unique_ptr<Value> value;
- if (pbValue.has_item()) {
- value = deserializeItemFromPb(pbValue.item(), config, pool);
- if (!value) {
- return {};
- }
-
- } else if (pbValue.has_compound_value()) {
- const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
- if (pbCompoundValue.has_attr()) {
- const pb::Attribute& pbAttr = pbCompoundValue.attr();
- std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
- attr->typeMask = pbAttr.format_flags();
- attr->minInt = pbAttr.min_int();
- attr->maxInt = pbAttr.max_int();
- for (const pb::Attribute_Symbol& pbSymbol : pbAttr.symbols()) {
- Attribute::Symbol symbol;
- deserializeItemCommon(pbSymbol, &symbol.symbol);
- if (!deserializeReferenceFromPb(pbSymbol.name(), &symbol.symbol)) {
- return {};
- }
- symbol.value = pbSymbol.value();
- attr->symbols.push_back(std::move(symbol));
- }
- value = std::move(attr);
-
- } else if (pbCompoundValue.has_style()) {
- const pb::Style& pbStyle = pbCompoundValue.style();
- std::unique_ptr<Style> style = util::make_unique<Style>();
- if (pbStyle.has_parent()) {
- style->parent = Reference();
- if (!deserializeReferenceFromPb(pbStyle.parent(), &style->parent.value())) {
- return {};
- }
-
- if (pbStyle.has_parent_source()) {
- Source parentSource;
- deserializeSourceFromPb(pbStyle.parent_source(), *mSourcePool,
- &parentSource);
- style->parent.value().setSource(std::move(parentSource));
- }
- }
-
- for (const pb::Style_Entry& pbEntry : pbStyle.entries()) {
- Style::Entry entry;
- deserializeItemCommon(pbEntry, &entry.key);
- if (!deserializeReferenceFromPb(pbEntry.key(), &entry.key)) {
- return {};
- }
-
- entry.value = deserializeItemFromPb(pbEntry.item(), config, pool);
- if (!entry.value) {
- return {};
- }
-
- deserializeItemCommon(pbEntry, entry.value.get());
- style->entries.push_back(std::move(entry));
- }
- value = std::move(style);
-
- } else if (pbCompoundValue.has_styleable()) {
- const pb::Styleable& pbStyleable = pbCompoundValue.styleable();
- std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
- for (const pb::Styleable_Entry& pbEntry : pbStyleable.entries()) {
- Reference attrRef;
- deserializeItemCommon(pbEntry, &attrRef);
- deserializeReferenceFromPb(pbEntry.attr(), &attrRef);
- styleable->entries.push_back(std::move(attrRef));
- }
- value = std::move(styleable);
-
- } else if (pbCompoundValue.has_array()) {
- const pb::Array& pbArray = pbCompoundValue.array();
- std::unique_ptr<Array> array = util::make_unique<Array>();
- for (const pb::Array_Entry& pbEntry : pbArray.entries()) {
- std::unique_ptr<Item> item = deserializeItemFromPb(pbEntry.item(), config,
- pool);
- if (!item) {
- return {};
- }
-
- deserializeItemCommon(pbEntry, item.get());
- array->items.push_back(std::move(item));
- }
- value = std::move(array);
-
- } else if (pbCompoundValue.has_plural()) {
- const pb::Plural& pbPlural = pbCompoundValue.plural();
- std::unique_ptr<Plural> plural = util::make_unique<Plural>();
- for (const pb::Plural_Entry& pbEntry : pbPlural.entries()) {
- size_t pluralIdx = deserializePluralEnumFromPb(pbEntry.arity());
- plural->values[pluralIdx] = deserializeItemFromPb(pbEntry.item(), config,
- pool);
- if (!plural->values[pluralIdx]) {
- return {};
- }
-
- deserializeItemCommon(pbEntry, plural->values[pluralIdx].get());
- }
- value = std::move(plural);
-
- } else {
- mDiag->error(DiagMessage(mSource) << "unknown compound value");
- return {};
- }
- } else {
- mDiag->error(DiagMessage(mSource) << "unknown value");
+ } else if (pbValue.has_compound_value()) {
+ const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
+ if (pbCompoundValue.has_attr()) {
+ const pb::Attribute& pbAttr = pbCompoundValue.attr();
+ std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
+ attr->typeMask = pbAttr.format_flags();
+ attr->minInt = pbAttr.min_int();
+ attr->maxInt = pbAttr.max_int();
+ for (const pb::Attribute_Symbol& pbSymbol : pbAttr.symbols()) {
+ Attribute::Symbol symbol;
+ deserializeItemCommon(pbSymbol, &symbol.symbol);
+ if (!deserializeReferenceFromPb(pbSymbol.name(), &symbol.symbol)) {
return {};
+ }
+ symbol.value = pbSymbol.value();
+ attr->symbols.push_back(std::move(symbol));
+ }
+ value = std::move(attr);
+
+ } else if (pbCompoundValue.has_style()) {
+ const pb::Style& pbStyle = pbCompoundValue.style();
+ std::unique_ptr<Style> style = util::make_unique<Style>();
+ if (pbStyle.has_parent()) {
+ style->parent = Reference();
+ if (!deserializeReferenceFromPb(pbStyle.parent(),
+ &style->parent.value())) {
+ return {};
+ }
+
+ if (pbStyle.has_parent_source()) {
+ Source parentSource;
+ deserializeSourceFromPb(pbStyle.parent_source(), *mSourcePool,
+ &parentSource);
+ style->parent.value().setSource(std::move(parentSource));
+ }
}
- assert(value && "forgot to set value");
+ for (const pb::Style_Entry& pbEntry : pbStyle.entries()) {
+ Style::Entry entry;
+ deserializeItemCommon(pbEntry, &entry.key);
+ if (!deserializeReferenceFromPb(pbEntry.key(), &entry.key)) {
+ return {};
+ }
- value->setWeak(isWeak);
- deserializeItemCommon(pbValue, value.get());
- return value;
+ entry.value = deserializeItemFromPb(pbEntry.item(), config, pool);
+ if (!entry.value) {
+ return {};
+ }
+
+ deserializeItemCommon(pbEntry, entry.value.get());
+ style->entries.push_back(std::move(entry));
+ }
+ value = std::move(style);
+
+ } else if (pbCompoundValue.has_styleable()) {
+ const pb::Styleable& pbStyleable = pbCompoundValue.styleable();
+ std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+ for (const pb::Styleable_Entry& pbEntry : pbStyleable.entries()) {
+ Reference attrRef;
+ deserializeItemCommon(pbEntry, &attrRef);
+ deserializeReferenceFromPb(pbEntry.attr(), &attrRef);
+ styleable->entries.push_back(std::move(attrRef));
+ }
+ value = std::move(styleable);
+
+ } else if (pbCompoundValue.has_array()) {
+ const pb::Array& pbArray = pbCompoundValue.array();
+ std::unique_ptr<Array> array = util::make_unique<Array>();
+ for (const pb::Array_Entry& pbEntry : pbArray.entries()) {
+ std::unique_ptr<Item> item =
+ deserializeItemFromPb(pbEntry.item(), config, pool);
+ if (!item) {
+ return {};
+ }
+
+ deserializeItemCommon(pbEntry, item.get());
+ array->items.push_back(std::move(item));
+ }
+ value = std::move(array);
+
+ } else if (pbCompoundValue.has_plural()) {
+ const pb::Plural& pbPlural = pbCompoundValue.plural();
+ std::unique_ptr<Plural> plural = util::make_unique<Plural>();
+ for (const pb::Plural_Entry& pbEntry : pbPlural.entries()) {
+ size_t pluralIdx = deserializePluralEnumFromPb(pbEntry.arity());
+ plural->values[pluralIdx] =
+ deserializeItemFromPb(pbEntry.item(), config, pool);
+ if (!plural->values[pluralIdx]) {
+ return {};
+ }
+
+ deserializeItemCommon(pbEntry, plural->values[pluralIdx].get());
+ }
+ value = std::move(plural);
+
+ } else {
+ mDiag->error(DiagMessage(mSource) << "unknown compound value");
+ return {};
+ }
+ } else {
+ mDiag->error(DiagMessage(mSource) << "unknown value");
+ return {};
}
- bool deserializeReferenceFromPb(const pb::Reference& pbRef, Reference* outRef) {
- outRef->referenceType = deserializeReferenceTypeFromPb(pbRef.type());
- outRef->privateReference = pbRef.private_();
+ assert(value && "forgot to set value");
- if (!pbRef.has_id() && !pbRef.has_symbol_idx()) {
- return false;
- }
+ value->setWeak(isWeak);
+ deserializeItemCommon(pbValue, value.get());
+ return value;
+ }
- if (pbRef.has_id()) {
- outRef->id = ResourceId(pbRef.id());
- }
+ bool deserializeReferenceFromPb(const pb::Reference& pbRef,
+ Reference* outRef) {
+ outRef->referenceType = deserializeReferenceTypeFromPb(pbRef.type());
+ outRef->privateReference = pbRef.private_();
- if (pbRef.has_symbol_idx()) {
- const std::string strSymbol = util::getString(*mSymbolPool, pbRef.symbol_idx());
- ResourceNameRef nameRef;
- if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
- mDiag->error(DiagMessage(mSource) << "invalid reference name '"
- << strSymbol << "'");
- return false;
- }
-
- outRef->name = nameRef.toResourceName();
- }
- return true;
+ if (!pbRef.has_id() && !pbRef.has_symbol_idx()) {
+ return false;
}
- template <typename T>
- void deserializeItemCommon(const T& pbItem, Value* outValue) {
- if (pbItem.has_source()) {
- Source source;
- deserializeSourceFromPb(pbItem.source(), *mSourcePool, &source);
- outValue->setSource(std::move(source));
- }
-
- if (pbItem.has_comment()) {
- outValue->setComment(pbItem.comment());
- }
+ if (pbRef.has_id()) {
+ outRef->id = ResourceId(pbRef.id());
}
-private:
- const android::ResStringPool* mValuePool;
- const android::ResStringPool* mSourcePool;
- const android::ResStringPool* mSymbolPool;
- const Source mSource;
- IDiagnostics* mDiag;
+ if (pbRef.has_symbol_idx()) {
+ const std::string strSymbol =
+ util::getString(*mSymbolPool, pbRef.symbol_idx());
+ ResourceNameRef nameRef;
+ if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
+ mDiag->error(DiagMessage(mSource) << "invalid reference name '"
+ << strSymbol << "'");
+ return false;
+ }
+
+ outRef->name = nameRef.toResourceName();
+ }
+ return true;
+ }
+
+ template <typename T>
+ void deserializeItemCommon(const T& pbItem, Value* outValue) {
+ if (pbItem.has_source()) {
+ Source source;
+ deserializeSourceFromPb(pbItem.source(), *mSourcePool, &source);
+ outValue->setSource(std::move(source));
+ }
+
+ if (pbItem.has_comment()) {
+ outValue->setComment(pbItem.comment());
+ }
+ }
+
+ private:
+ const android::ResStringPool* mValuePool;
+ const android::ResStringPool* mSourcePool;
+ const android::ResStringPool* mSymbolPool;
+ const Source mSource;
+ IDiagnostics* mDiag;
};
-} // namespace
+} // namespace
-std::unique_ptr<ResourceTable> deserializeTableFromPb(const pb::ResourceTable& pbTable,
- const Source& source,
- IDiagnostics* diag) {
- // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
- // causes errors when qualifying it with android::
- using namespace android;
+std::unique_ptr<ResourceTable> deserializeTableFromPb(
+ const pb::ResourceTable& pbTable, const Source& source,
+ IDiagnostics* diag) {
+ // We import the android namespace because on Windows NO_ERROR is a macro, not
+ // an enum, which
+ // causes errors when qualifying it with android::
+ using namespace android;
- std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
+ std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
- if (!pbTable.has_string_pool()) {
- diag->error(DiagMessage(source) << "no string pool found");
- return {};
- }
+ if (!pbTable.has_string_pool()) {
+ diag->error(DiagMessage(source) << "no string pool found");
+ return {};
+ }
- ResStringPool valuePool;
- status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
- pbTable.string_pool().data().size());
+ ResStringPool valuePool;
+ status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
+ pbTable.string_pool().data().size());
+ if (result != NO_ERROR) {
+ diag->error(DiagMessage(source) << "invalid string pool");
+ return {};
+ }
+
+ ResStringPool sourcePool;
+ if (pbTable.has_source_pool()) {
+ result = sourcePool.setTo(pbTable.source_pool().data().data(),
+ pbTable.source_pool().data().size());
if (result != NO_ERROR) {
- diag->error(DiagMessage(source) << "invalid string pool");
- return {};
+ diag->error(DiagMessage(source) << "invalid source pool");
+ return {};
}
+ }
- ResStringPool sourcePool;
- if (pbTable.has_source_pool()) {
- result = sourcePool.setTo(pbTable.source_pool().data().data(),
- pbTable.source_pool().data().size());
- if (result != NO_ERROR) {
- diag->error(DiagMessage(source) << "invalid source pool");
- return {};
- }
+ ResStringPool symbolPool;
+ if (pbTable.has_symbol_pool()) {
+ result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
+ pbTable.symbol_pool().data().size());
+ if (result != NO_ERROR) {
+ diag->error(DiagMessage(source) << "invalid symbol pool");
+ return {};
}
+ }
- ResStringPool symbolPool;
- if (pbTable.has_symbol_pool()) {
- result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
- pbTable.symbol_pool().data().size());
- if (result != NO_ERROR) {
- diag->error(DiagMessage(source) << "invalid symbol pool");
- return {};
- }
+ PackagePbDeserializer packagePbDeserializer(&valuePool, &sourcePool,
+ &symbolPool, source, diag);
+ for (const pb::Package& pbPackage : pbTable.packages()) {
+ if (!packagePbDeserializer.deserializeFromPb(pbPackage, table.get())) {
+ return {};
}
-
- PackagePbDeserializer packagePbDeserializer(&valuePool, &sourcePool, &symbolPool, source, diag);
- for (const pb::Package& pbPackage : pbTable.packages()) {
- if (!packagePbDeserializer.deserializeFromPb(pbPackage, table.get())) {
- return {};
- }
- }
- return table;
+ }
+ return table;
}
-std::unique_ptr<ResourceFile> deserializeCompiledFileFromPb(const pb::CompiledFile& pbFile,
- const Source& source,
- IDiagnostics* diag) {
- std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
+std::unique_ptr<ResourceFile> deserializeCompiledFileFromPb(
+ const pb::CompiledFile& pbFile, const Source& source, IDiagnostics* diag) {
+ std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
- ResourceNameRef nameRef;
+ ResourceNameRef nameRef;
- // Need to create an lvalue here so that nameRef can point to something real.
- if (!ResourceUtils::parseResourceName(pbFile.resource_name(), &nameRef)) {
- diag->error(DiagMessage(source) << "invalid resource name in compiled file header: "
- << pbFile.resource_name());
- return {};
+ // Need to create an lvalue here so that nameRef can point to something real.
+ if (!ResourceUtils::parseResourceName(pbFile.resource_name(), &nameRef)) {
+ diag->error(DiagMessage(source)
+ << "invalid resource name in compiled file header: "
+ << pbFile.resource_name());
+ return {};
+ }
+ file->name = nameRef.toResourceName();
+ file->source.path = pbFile.source_path();
+ deserializeConfigDescriptionFromPb(pbFile.config(), &file->config);
+
+ for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
+ // Need to create an lvalue here so that nameRef can point to something
+ // real.
+ if (!ResourceUtils::parseResourceName(pbSymbol.resource_name(), &nameRef)) {
+ diag->error(DiagMessage(source)
+ << "invalid resource name for exported symbol in "
+ "compiled file header: "
+ << pbFile.resource_name());
+ return {};
}
- file->name = nameRef.toResourceName();
- file->source.path = pbFile.source_path();
- deserializeConfigDescriptionFromPb(pbFile.config(), &file->config);
-
- for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
- // Need to create an lvalue here so that nameRef can point to something real.
- if (!ResourceUtils::parseResourceName(pbSymbol.resource_name(), &nameRef)) {
- diag->error(DiagMessage(source) << "invalid resource name for exported symbol in "
- "compiled file header: "
- << pbFile.resource_name());
- return {};
- }
- file->exportedSymbols.push_back(
- SourcedResourceName{ nameRef.toResourceName(), pbSymbol.line_no() });
- }
- return file;
+ file->exportedSymbols.push_back(
+ SourcedResourceName{nameRef.toResourceName(), pbSymbol.line_no()});
+ }
+ return file;
}
-} // namespace aapt
+} // namespace aapt