2016-02-04 15:59:23 -08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 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.
|
|
|
|
*/
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
#include "proto/ProtoSerialize.h"
|
|
|
|
|
|
|
|
#include "android-base/logging.h"
|
|
|
|
#include "androidfw/ResourceTypes.h"
|
|
|
|
|
2016-02-04 15:59:23 -08:00
|
|
|
#include "ResourceTable.h"
|
|
|
|
#include "ResourceUtils.h"
|
|
|
|
#include "ValueVisitor.h"
|
|
|
|
#include "proto/ProtoHelpers.h"
|
|
|
|
|
|
|
|
namespace aapt {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class ReferenceIdToNameVisitor : public ValueVisitor {
|
2016-10-21 13:38:42 -07:00
|
|
|
public:
|
2016-10-21 17:56:45 -07:00
|
|
|
using ValueVisitor::Visit;
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
explicit ReferenceIdToNameVisitor(
|
|
|
|
const std::map<ResourceId, ResourceNameRef>* mapping)
|
2016-10-21 17:56:45 -07:00
|
|
|
: mapping_(mapping) {
|
|
|
|
CHECK(mapping_ != nullptr);
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
void Visit(Reference* reference) override {
|
|
|
|
if (!reference->id || !reference->id.value().is_valid()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return;
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ResourceId id = reference->id.value();
|
2016-10-21 17:56:45 -07:00
|
|
|
auto cache_iter = mapping_->find(id);
|
|
|
|
if (cache_iter != mapping_->end()) {
|
|
|
|
reference->name = cache_iter->second.ToResourceName();
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
private:
|
2016-10-21 17:56:45 -07:00
|
|
|
const std::map<ResourceId, ResourceNameRef>* mapping_;
|
2016-02-04 15:59:23 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
class PackagePbDeserializer {
|
2016-10-21 13:38:42 -07:00
|
|
|
public:
|
|
|
|
PackagePbDeserializer(const android::ResStringPool* valuePool,
|
|
|
|
const android::ResStringPool* sourcePool,
|
|
|
|
const android::ResStringPool* symbolPool,
|
|
|
|
const Source& source, IDiagnostics* diag)
|
2016-10-21 17:56:45 -07:00
|
|
|
: value_pool_(valuePool),
|
|
|
|
source_pool_(sourcePool),
|
|
|
|
symbol_pool_(symbolPool),
|
|
|
|
source_(source),
|
|
|
|
diag_(diag) {}
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
public:
|
2016-10-21 17:56:45 -07:00
|
|
|
bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
|
2016-10-21 13:38:42 -07:00
|
|
|
Maybe<uint8_t> id;
|
|
|
|
if (pbPackage.has_package_id()) {
|
|
|
|
id = static_cast<uint8_t>(pbPackage.package_id());
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
std::map<ResourceId, ResourceNameRef> idIndex;
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ResourceTablePackage* pkg =
|
2016-10-21 17:56:45 -07:00
|
|
|
table->CreatePackage(pbPackage.package_name(), id);
|
2016-10-21 13:38:42 -07:00
|
|
|
for (const pb::Type& pbType : pbPackage.types()) {
|
2016-10-21 17:56:45 -07:00
|
|
|
const ResourceType* resType = ParseResourceType(pbType.name());
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!resType) {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name()
|
2016-10-21 13:38:42 -07:00
|
|
|
<< "'");
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
ResourceTableType* type = pkg->FindOrCreateType(*resType);
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
for (const pb::Entry& pbEntry : pbType.entries()) {
|
2016-10-21 17:56:45 -07:00
|
|
|
ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.name());
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
// 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()) {
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeSourceFromPb(pbStatus.source(), *source_pool_,
|
|
|
|
&entry->symbol_status.source);
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pbStatus.has_comment()) {
|
2016-10-21 17:56:45 -07:00
|
|
|
entry->symbol_status.comment = pbStatus.comment();
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
SymbolState visibility =
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeVisibilityFromPb(pbStatus.visibility());
|
|
|
|
entry->symbol_status.state = visibility;
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
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());
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (type->symbol_status.state != SymbolState::kPublic) {
|
2016-10-21 13:38:42 -07:00
|
|
|
// If the type has not been made public, do so now.
|
2016-10-21 17:56:45 -07:00
|
|
|
type->symbol_status.state = SymbolState::kPublic;
|
2016-10-21 13:38:42 -07:00
|
|
|
if (pbType.has_id()) {
|
|
|
|
type->id = static_cast<uint8_t>(pbType.id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (visibility == SymbolState::kPrivate) {
|
2016-10-21 17:56:45 -07:00
|
|
|
if (type->symbol_status.state == SymbolState::kUndefined) {
|
|
|
|
type->symbol_status.state = SymbolState::kPrivate;
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
|
2016-10-21 17:56:45 -07:00
|
|
|
if (resId.is_valid()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
|
|
|
|
const pb::ConfigDescription& pbConfig = pbConfigValue.config();
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ConfigDescription config;
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) {
|
|
|
|
diag_->Error(DiagMessage(source_) << "invalid configuration");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ResourceConfigValue* configValue =
|
2016-10-21 17:56:45 -07:00
|
|
|
entry->FindOrCreateValue(config, pbConfig.product());
|
2016-10-21 13:38:42 -07:00
|
|
|
if (configValue->value) {
|
|
|
|
// Duplicate config.
|
2016-10-21 17:56:45 -07:00
|
|
|
diag_->Error(DiagMessage(source_) << "duplicate configuration");
|
2016-02-04 15:59:23 -08:00
|
|
|
return {};
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
configValue->value = DeserializeValueFromPb(
|
|
|
|
pbConfigValue.value(), config, &table->string_pool);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!configValue->value) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
ReferenceIdToNameVisitor visitor(&idIndex);
|
2016-10-21 17:56:45 -07:00
|
|
|
VisitAllValuesInPackage(pkg, &visitor);
|
2016-10-21 13:38:42 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-10-21 17:56:45 -07:00
|
|
|
std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
|
2016-10-21 13:38:42 -07:00
|
|
|
const ConfigDescription& config,
|
|
|
|
StringPool* pool) {
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_item.has_ref()) {
|
|
|
|
const pb::Reference& pb_ref = pb_item.ref();
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Reference> ref = util::make_unique<Reference>();
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return std::move(ref);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_item.has_prim()) {
|
|
|
|
const pb::Primitive& pb_prim = pb_item.prim();
|
2016-10-21 13:38:42 -07:00
|
|
|
android::Res_value prim = {};
|
2016-10-21 17:56:45 -07:00
|
|
|
prim.dataType = static_cast<uint8_t>(pb_prim.type());
|
|
|
|
prim.data = pb_prim.data();
|
2016-10-21 13:38:42 -07:00
|
|
|
return util::make_unique<BinaryPrimitive>(prim);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_item.has_id()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return util::make_unique<Id>();
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_item.has_str()) {
|
|
|
|
const uint32_t idx = pb_item.str().idx();
|
|
|
|
const std::string str = util::GetString(*value_pool_, idx);
|
2016-10-21 13:38:42 -07:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
const android::ResStringPool_span* spans = value_pool_->styleAt(idx);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (spans && spans->name.index != android::ResStringPool_span::END) {
|
2016-10-21 17:56:45 -07:00
|
|
|
StyleString style_str = {str};
|
2016-10-21 13:38:42 -07:00
|
|
|
while (spans->name.index != android::ResStringPool_span::END) {
|
2016-10-21 17:56:45 -07:00
|
|
|
style_str.spans.push_back(
|
|
|
|
Span{util::GetString(*value_pool_, spans->name.index),
|
2016-10-21 13:38:42 -07:00
|
|
|
spans->firstChar, spans->lastChar});
|
|
|
|
spans++;
|
|
|
|
}
|
2016-10-21 17:56:45 -07:00
|
|
|
return util::make_unique<StyledString>(pool->MakeRef(
|
|
|
|
style_str,
|
2016-10-21 13:38:42 -07:00
|
|
|
StringPool::Context(StringPool::Context::kStylePriority, config)));
|
|
|
|
}
|
|
|
|
return util::make_unique<String>(
|
2016-10-21 17:56:45 -07:00
|
|
|
pool->MakeRef(str, StringPool::Context(config)));
|
2016-10-21 13:38:42 -07:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_item.has_raw_str()) {
|
|
|
|
const uint32_t idx = pb_item.raw_str().idx();
|
|
|
|
const std::string str = util::GetString(*value_pool_, idx);
|
2016-10-21 13:38:42 -07:00
|
|
|
return util::make_unique<RawString>(
|
2016-10-21 17:56:45 -07:00
|
|
|
pool->MakeRef(str, StringPool::Context(config)));
|
2016-10-21 13:38:42 -07:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_item.has_file()) {
|
|
|
|
const uint32_t idx = pb_item.file().path_idx();
|
|
|
|
const std::string str = util::GetString(*value_pool_, idx);
|
|
|
|
return util::make_unique<FileReference>(pool->MakeRef(
|
2016-10-21 13:38:42 -07:00
|
|
|
str,
|
|
|
|
StringPool::Context(StringPool::Context::kHighPriority, config)));
|
|
|
|
|
|
|
|
} else {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag_->Error(DiagMessage(source_) << "unknown item");
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
|
2016-10-21 13:38:42 -07:00
|
|
|
const ConfigDescription& config,
|
|
|
|
StringPool* pool) {
|
2016-10-21 17:56:45 -07:00
|
|
|
const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Value> value;
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_value.has_item()) {
|
|
|
|
value = DeserializeItemFromPb(pb_value.item(), config, pool);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!value) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_value.has_compound_value()) {
|
|
|
|
const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
|
|
|
|
if (pb_compound_value.has_attr()) {
|
|
|
|
const pb::Attribute& pb_attr = pb_compound_value.attr();
|
|
|
|
std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
|
|
|
|
attr->type_mask = pb_attr.format_flags();
|
|
|
|
attr->min_int = pb_attr.min_int();
|
|
|
|
attr->max_int = pb_attr.max_int();
|
|
|
|
for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
Attribute::Symbol symbol;
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemCommon(pb_symbol, &symbol.symbol);
|
|
|
|
if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
2016-10-21 17:56:45 -07:00
|
|
|
symbol.value = pb_symbol.value();
|
2016-10-21 13:38:42 -07:00
|
|
|
attr->symbols.push_back(std::move(symbol));
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
value = std::move(attr);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_compound_value.has_style()) {
|
|
|
|
const pb::Style& pb_style = pb_compound_value.style();
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Style> style = util::make_unique<Style>();
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_style.has_parent()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
style->parent = Reference();
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!DeserializeReferenceFromPb(pb_style.parent(),
|
2016-10-21 13:38:42 -07:00
|
|
|
&style->parent.value())) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_style.has_parent_source()) {
|
|
|
|
Source parent_source;
|
|
|
|
DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_,
|
|
|
|
&parent_source);
|
|
|
|
style->parent.value().SetSource(std::move(parent_source));
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
Style::Entry entry;
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemCommon(pb_entry, &entry.key);
|
|
|
|
if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!entry.value) {
|
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemCommon(pb_entry, entry.value.get());
|
2016-10-21 13:38:42 -07:00
|
|
|
style->entries.push_back(std::move(entry));
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
value = std::move(style);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_compound_value.has_styleable()) {
|
|
|
|
const pb::Styleable& pb_styleable = pb_compound_value.styleable();
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
|
2016-10-21 17:56:45 -07:00
|
|
|
for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
|
|
|
|
Reference attr_ref;
|
|
|
|
DeserializeItemCommon(pb_entry, &attr_ref);
|
|
|
|
DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
|
|
|
|
styleable->entries.push_back(std::move(attr_ref));
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
value = std::move(styleable);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_compound_value.has_array()) {
|
|
|
|
const pb::Array& pb_array = pb_compound_value.array();
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Array> array = util::make_unique<Array>();
|
2016-10-21 17:56:45 -07:00
|
|
|
for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Item> item =
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemFromPb(pb_entry.item(), config, pool);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!item) {
|
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemCommon(pb_entry, item.get());
|
2016-10-21 13:38:42 -07:00
|
|
|
array->items.push_back(std::move(item));
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
value = std::move(array);
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
} else if (pb_compound_value.has_plural()) {
|
|
|
|
const pb::Plural& pb_plural = pb_compound_value.plural();
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
|
2016-10-21 17:56:45 -07:00
|
|
|
for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
|
|
|
|
size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
|
2016-10-21 13:38:42 -07:00
|
|
|
plural->values[pluralIdx] =
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemFromPb(pb_entry.item(), config, pool);
|
2016-10-21 13:38:42 -07:00
|
|
|
if (!plural->values[pluralIdx]) {
|
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
value = std::move(plural);
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
} else {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag_->Error(DiagMessage(source_) << "unknown compound value");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
} else {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag_->Error(DiagMessage(source_) << "unknown value");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
CHECK(value) << "forgot to set value";
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
value->SetWeak(is_weak);
|
|
|
|
DeserializeItemCommon(pb_value, value.get());
|
2016-10-21 13:38:42 -07:00
|
|
|
return value;
|
|
|
|
}
|
2016-04-06 16:09:43 -07:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
bool DeserializeReferenceFromPb(const pb::Reference& pb_ref,
|
|
|
|
Reference* out_ref) {
|
|
|
|
out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
|
|
|
|
out_ref->private_reference = pb_ref.private_();
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!pb_ref.has_id() && !pb_ref.has_symbol_idx()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return false;
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_ref.has_id()) {
|
|
|
|
out_ref->id = ResourceId(pb_ref.id());
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_ref.has_symbol_idx()) {
|
|
|
|
const std::string str_symbol =
|
|
|
|
util::GetString(*symbol_pool_, pb_ref.symbol_idx());
|
|
|
|
ResourceNameRef name_ref;
|
|
|
|
if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
|
|
|
|
diag_->Error(DiagMessage(source_) << "invalid reference name '"
|
|
|
|
<< str_symbol << "'");
|
2016-10-21 13:38:42 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
out_ref->name = name_ref.ToResourceName();
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2016-10-21 17:56:45 -07:00
|
|
|
void DeserializeItemCommon(const T& pb_item, Value* out_value) {
|
|
|
|
if (pb_item.has_source()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
Source source;
|
2016-10-21 17:56:45 -07:00
|
|
|
DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
|
|
|
|
out_value->SetSource(std::move(source));
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (pb_item.has_comment()) {
|
|
|
|
out_value->SetComment(pb_item.comment());
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-10-21 17:56:45 -07:00
|
|
|
const android::ResStringPool* value_pool_;
|
|
|
|
const android::ResStringPool* source_pool_;
|
|
|
|
const android::ResStringPool* symbol_pool_;
|
|
|
|
const Source source_;
|
|
|
|
IDiagnostics* diag_;
|
2016-10-21 13:38:42 -07:00
|
|
|
};
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
} // namespace
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
std::unique_ptr<ResourceTable> DeserializeTableFromPb(
|
|
|
|
const pb::ResourceTable& pb_table, const Source& source,
|
2016-10-21 13:38:42 -07:00
|
|
|
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>();
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!pb_table.has_string_pool()) {
|
|
|
|
diag->Error(DiagMessage(source) << "no string pool found");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
ResStringPool value_pool;
|
|
|
|
status_t result = value_pool.setTo(pb_table.string_pool().data().data(),
|
|
|
|
pb_table.string_pool().data().size());
|
2016-10-21 13:38:42 -07:00
|
|
|
if (result != NO_ERROR) {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag->Error(DiagMessage(source) << "invalid string pool");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
ResStringPool source_pool;
|
|
|
|
if (pb_table.has_source_pool()) {
|
|
|
|
result = source_pool.setTo(pb_table.source_pool().data().data(),
|
|
|
|
pb_table.source_pool().data().size());
|
2016-10-21 13:38:42 -07:00
|
|
|
if (result != NO_ERROR) {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag->Error(DiagMessage(source) << "invalid source pool");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
ResStringPool symbol_pool;
|
|
|
|
if (pb_table.has_symbol_pool()) {
|
|
|
|
result = symbol_pool.setTo(pb_table.symbol_pool().data().data(),
|
|
|
|
pb_table.symbol_pool().data().size());
|
2016-10-21 13:38:42 -07:00
|
|
|
if (result != NO_ERROR) {
|
2016-10-21 17:56:45 -07:00
|
|
|
diag->Error(DiagMessage(source) << "invalid symbol pool");
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
2016-02-04 15:59:23 -08:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
PackagePbDeserializer package_pb_deserializer(&value_pool, &source_pool,
|
|
|
|
&symbol_pool, source, diag);
|
|
|
|
for (const pb::Package& pb_package : pb_table.packages()) {
|
|
|
|
if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
|
|
|
|
const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
|
2016-10-21 13:38:42 -07:00
|
|
|
std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
|
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
ResourceNameRef name_ref;
|
2016-10-21 13:38:42 -07:00
|
|
|
|
|
|
|
// Need to create an lvalue here so that nameRef can point to something real.
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
|
|
|
|
diag->Error(DiagMessage(source)
|
2016-10-21 13:38:42 -07:00
|
|
|
<< "invalid resource name in compiled file header: "
|
2016-10-21 17:56:45 -07:00
|
|
|
<< pb_file.resource_name());
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
|
|
|
}
|
2016-10-21 17:56:45 -07:00
|
|
|
file->name = name_ref.ToResourceName();
|
|
|
|
file->source.path = pb_file.source_path();
|
|
|
|
DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
|
2016-10-21 13:38:42 -07:00
|
|
|
|
2016-10-21 17:56:45 -07:00
|
|
|
for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
|
2016-10-21 13:38:42 -07:00
|
|
|
// Need to create an lvalue here so that nameRef can point to something
|
|
|
|
// real.
|
2016-10-21 17:56:45 -07:00
|
|
|
if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
|
|
|
|
&name_ref)) {
|
|
|
|
diag->Error(DiagMessage(source)
|
2016-10-21 13:38:42 -07:00
|
|
|
<< "invalid resource name for exported symbol in "
|
|
|
|
"compiled file header: "
|
2016-10-21 17:56:45 -07:00
|
|
|
<< pb_file.resource_name());
|
2016-10-21 13:38:42 -07:00
|
|
|
return {};
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
2016-10-21 17:56:45 -07:00
|
|
|
file->exported_symbols.push_back(
|
|
|
|
SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
|
2016-10-21 13:38:42 -07:00
|
|
|
}
|
|
|
|
return file;
|
2016-02-04 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
2016-10-21 13:38:42 -07:00
|
|
|
} // namespace aapt
|