AAPT2: Enable building proto artifacts
- This will allow the bundle tool to ingest the outputs of the aapt2 link phase. Bug: 64143208 Test: manual Change-Id: I1a4b3ce5c2ffbbdc4bc642c3371a9ef2e7e9ad71
This commit is contained in:
@@ -35,11 +35,11 @@ namespace aapt {
|
||||
|
||||
namespace {
|
||||
|
||||
class PrintVisitor : public DescendingValueVisitor {
|
||||
class PrintVisitor : public ConstValueVisitor {
|
||||
public:
|
||||
using DescendingValueVisitor::Visit;
|
||||
using ConstValueVisitor::Visit;
|
||||
|
||||
void Visit(Attribute* attr) override {
|
||||
void Visit(const Attribute* attr) override {
|
||||
std::cout << "(attr) type=";
|
||||
attr->PrintMask(&std::cout);
|
||||
static constexpr uint32_t kMask =
|
||||
@@ -55,7 +55,7 @@ class PrintVisitor : public DescendingValueVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void Visit(Style* style) override {
|
||||
void Visit(const Style* style) override {
|
||||
std::cout << "(style)";
|
||||
if (style->parent) {
|
||||
const Reference& parent_ref = style->parent.value();
|
||||
@@ -90,15 +90,15 @@ class PrintVisitor : public DescendingValueVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void Visit(Array* array) override {
|
||||
void Visit(const Array* array) override {
|
||||
array->Print(&std::cout);
|
||||
}
|
||||
|
||||
void Visit(Plural* plural) override {
|
||||
void Visit(const Plural* plural) override {
|
||||
plural->Print(&std::cout);
|
||||
}
|
||||
|
||||
void Visit(Styleable* styleable) override {
|
||||
void Visit(const Styleable* styleable) override {
|
||||
std::cout << "(styleable)";
|
||||
for (const auto& attr : styleable->entries) {
|
||||
std::cout << "\n ";
|
||||
@@ -116,17 +116,17 @@ class PrintVisitor : public DescendingValueVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void VisitItem(Item* item) override {
|
||||
void VisitItem(const Item* item) override {
|
||||
item->Print(&std::cout);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void Debug::PrintTable(ResourceTable* table, const DebugPrintTableOptions& options) {
|
||||
void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options) {
|
||||
PrintVisitor visitor;
|
||||
|
||||
for (auto& package : table->packages) {
|
||||
for (const auto& package : table.packages) {
|
||||
std::cout << "Package name=" << package->name;
|
||||
if (package->id) {
|
||||
std::cout << " id=" << std::hex << (int)package->id.value() << std::dec;
|
||||
@@ -261,11 +261,11 @@ void Debug::DumpHex(const void* data, size_t len) {
|
||||
|
||||
namespace {
|
||||
|
||||
class XmlPrinter : public xml::Visitor {
|
||||
class XmlPrinter : public xml::ConstVisitor {
|
||||
public:
|
||||
using xml::Visitor::Visit;
|
||||
using xml::ConstVisitor::Visit;
|
||||
|
||||
void Visit(xml::Element* el) override {
|
||||
void Visit(const xml::Element* el) override {
|
||||
const size_t previous_size = prefix_.size();
|
||||
|
||||
for (const xml::NamespaceDecl& decl : el->namespace_decls) {
|
||||
@@ -301,11 +301,11 @@ class XmlPrinter : public xml::Visitor {
|
||||
}
|
||||
|
||||
prefix_ += " ";
|
||||
xml::Visitor::Visit(el);
|
||||
xml::ConstVisitor::Visit(el);
|
||||
prefix_.resize(previous_size);
|
||||
}
|
||||
|
||||
void Visit(xml::Text* text) override {
|
||||
void Visit(const xml::Text* text) override {
|
||||
std::cerr << prefix_ << "T: '" << text->text << "'\n";
|
||||
}
|
||||
|
||||
@@ -315,9 +315,9 @@ class XmlPrinter : public xml::Visitor {
|
||||
|
||||
} // namespace
|
||||
|
||||
void Debug::DumpXml(xml::XmlResource* doc) {
|
||||
void Debug::DumpXml(const xml::XmlResource& doc) {
|
||||
XmlPrinter printer;
|
||||
doc->root->Accept(&printer);
|
||||
doc.root->Accept(&printer);
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
@@ -31,13 +31,11 @@ struct DebugPrintTableOptions {
|
||||
};
|
||||
|
||||
struct Debug {
|
||||
static void PrintTable(ResourceTable* table,
|
||||
const DebugPrintTableOptions& options = {});
|
||||
static void PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options = {});
|
||||
static void PrintStyleGraph(ResourceTable* table,
|
||||
const ResourceName& target_style);
|
||||
static void DumpHex(const void* data, size_t len);
|
||||
static void DumpXml(xml::XmlResource* doc);
|
||||
static std::string ToString(xml::XmlResource* doc);
|
||||
static void DumpXml(const xml::XmlResource& doc);
|
||||
};
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
@@ -704,8 +704,15 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
|
||||
} else {
|
||||
if (type != ResourceType::kString && util::StartsWith(str, "res/")) {
|
||||
// This must be a FileReference.
|
||||
return util::make_unique<FileReference>(dst_pool->MakeRef(
|
||||
str, StringPool::Context(StringPool::Context::kHighPriority, config)));
|
||||
std::unique_ptr<FileReference> file_ref =
|
||||
util::make_unique<FileReference>(dst_pool->MakeRef(
|
||||
str, StringPool::Context(StringPool::Context::kHighPriority, config)));
|
||||
if (util::EndsWith(*file_ref->path, ".xml")) {
|
||||
file_ref->type = ResourceFile::Type::kBinaryXml;
|
||||
} else if (util::EndsWith(*file_ref->path, ".png")) {
|
||||
file_ref->type = ResourceFile::Type::kPng;
|
||||
}
|
||||
return std::move(file_ref);
|
||||
}
|
||||
|
||||
// There are no styles associated with this string, so treat it as a simple string.
|
||||
|
||||
@@ -269,8 +269,19 @@ message StyledString {
|
||||
|
||||
// A value that is a reference to an external entity, like an XML file or a PNG.
|
||||
message FileReference {
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
PNG = 1;
|
||||
BINARY_XML = 2;
|
||||
PROTO_XML = 3;
|
||||
}
|
||||
|
||||
// Path to a file within the APK (typically res/type-config/entry.ext).
|
||||
string path = 1;
|
||||
|
||||
// The type of file this path points to. For UAM bundle, this cannot be
|
||||
// BINARY_XML.
|
||||
Type type = 2;
|
||||
}
|
||||
|
||||
// A value that represents a primitive data type (float, int, boolean, etc.).
|
||||
|
||||
@@ -41,14 +41,8 @@ message CompiledFile {
|
||||
// The configuration for which the resource is defined.
|
||||
aapt.pb.Configuration config = 2;
|
||||
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
PNG = 1;
|
||||
BINARY_XML = 2;
|
||||
PROTO_XML = 3;
|
||||
}
|
||||
|
||||
Type type = 3;
|
||||
// The type of the file.
|
||||
aapt.pb.FileReference.Type type = 3;
|
||||
|
||||
// The filesystem path to where the source file originated.
|
||||
// Mainly used to display helpful error messages.
|
||||
@@ -56,7 +50,4 @@ message CompiledFile {
|
||||
|
||||
// Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file).
|
||||
repeated Symbol exported_symbol = 5;
|
||||
|
||||
// If this is a compiled XML file, this is the root node.
|
||||
aapt.pb.XmlNode xml_root = 6;
|
||||
}
|
||||
|
||||
@@ -65,21 +65,19 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path) {
|
||||
std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
|
||||
if (zip) {
|
||||
ResourceTable table;
|
||||
if (io::IFile* file = zip->FindFile("resources.arsc.flat")) {
|
||||
if (io::IFile* file = zip->FindFile("resources.pb")) {
|
||||
std::unique_ptr<io::IData> data = file->OpenAsData();
|
||||
if (data == nullptr) {
|
||||
context->GetDiagnostics()->Error(DiagMessage(file_path)
|
||||
<< "failed to open resources.arsc.flat");
|
||||
context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.pb");
|
||||
return false;
|
||||
}
|
||||
|
||||
pb::ResourceTable pb_table;
|
||||
if (!pb_table.ParseFromArray(data->data(), data->size())) {
|
||||
context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.arsc.flat");
|
||||
context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.pb");
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceTable table;
|
||||
if (!DeserializeTableFromPb(pb_table, &table, &err)) {
|
||||
context->GetDiagnostics()->Error(DiagMessage(file_path)
|
||||
<< "failed to parse table: " << err);
|
||||
@@ -98,7 +96,7 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path) {
|
||||
}
|
||||
}
|
||||
|
||||
Debug::PrintTable(&table, print_options);
|
||||
Debug::PrintTable(table, print_options);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,7 +135,7 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug::PrintTable(&table, print_options);
|
||||
Debug::PrintTable(table, print_options);
|
||||
} else if (entry->Type() == ContainerEntryType::kResFile) {
|
||||
pb::internal::CompiledFile pb_compiled_file;
|
||||
off64_t offset;
|
||||
|
||||
@@ -71,6 +71,14 @@ using ::android::base::StringPrintf;
|
||||
|
||||
namespace aapt {
|
||||
|
||||
constexpr static const char kApkResourceTablePath[] = "resources.arsc";
|
||||
constexpr static const char kProtoResourceTablePath[] = "resources.pb";
|
||||
|
||||
enum class OutputFormat {
|
||||
kApk,
|
||||
kProto,
|
||||
};
|
||||
|
||||
struct LinkOptions {
|
||||
std::string output_path;
|
||||
std::string manifest_path;
|
||||
@@ -79,6 +87,7 @@ struct LinkOptions {
|
||||
std::vector<std::string> assets_dirs;
|
||||
bool output_to_directory = false;
|
||||
bool auto_add_overlay = false;
|
||||
OutputFormat output_format = OutputFormat::kApk;
|
||||
|
||||
// Java/Proguard options.
|
||||
Maybe<std::string> generate_java_class_path;
|
||||
@@ -253,26 +262,39 @@ class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
|
||||
IAaptContext* context_;
|
||||
};
|
||||
|
||||
static bool FlattenXml(IAaptContext* context, xml::XmlResource* xml_res, const StringPiece& path,
|
||||
bool keep_raw_values, bool utf16, IArchiveWriter* writer) {
|
||||
BigBuffer buffer(1024);
|
||||
XmlFlattenerOptions options = {};
|
||||
options.keep_raw_values = keep_raw_values;
|
||||
options.use_utf16 = utf16;
|
||||
XmlFlattener flattener(&buffer, options);
|
||||
if (!flattener.Consume(context, xml_res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
|
||||
const StringPiece& path, bool keep_raw_values, bool utf16,
|
||||
OutputFormat format, IArchiveWriter* writer) {
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
|
||||
<< (keep_raw_values ? "true" : "false")
|
||||
<< ")");
|
||||
}
|
||||
|
||||
io::BigBufferInputStream input_stream(&buffer);
|
||||
return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
|
||||
ArchiveEntry::kCompress, writer);
|
||||
switch (format) {
|
||||
case OutputFormat::kApk: {
|
||||
BigBuffer buffer(1024);
|
||||
XmlFlattenerOptions options = {};
|
||||
options.keep_raw_values = keep_raw_values;
|
||||
options.use_utf16 = utf16;
|
||||
XmlFlattener flattener(&buffer, options);
|
||||
if (!flattener.Consume(context, &xml_res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
io::BigBufferInputStream input_stream(&buffer);
|
||||
return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
|
||||
ArchiveEntry::kCompress, writer);
|
||||
} break;
|
||||
|
||||
case OutputFormat::kProto: {
|
||||
pb::XmlNode pb_node;
|
||||
SerializeXmlResourceToPb(xml_res, &pb_node);
|
||||
return io::CopyProtoToArchive(context, &pb_node, path.to_string(), ArchiveEntry::kCompress,
|
||||
writer);
|
||||
} break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data,
|
||||
@@ -310,6 +332,7 @@ struct ResourceFileFlattenerOptions {
|
||||
bool keep_raw_values = false;
|
||||
bool do_not_compress_anything = false;
|
||||
bool update_proguard_spec = false;
|
||||
OutputFormat output_format = OutputFormat::kApk;
|
||||
std::unordered_set<std::string> extensions_to_not_compress;
|
||||
};
|
||||
|
||||
@@ -627,8 +650,9 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv
|
||||
return false;
|
||||
}
|
||||
}
|
||||
error |= !FlattenXml(context_, doc.get(), dst_path, options_.keep_raw_values,
|
||||
false /*utf16*/, archive_writer);
|
||||
|
||||
error |= !FlattenXml(context_, *doc, dst_path, options_.keep_raw_values,
|
||||
false /*utf16*/, options_.output_format, archive_writer);
|
||||
}
|
||||
} else {
|
||||
error |= !io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
|
||||
@@ -927,23 +951,29 @@ class LinkCommand {
|
||||
}
|
||||
}
|
||||
|
||||
bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
|
||||
BigBuffer buffer(1024);
|
||||
TableFlattener flattener(options_.table_flattener_options, &buffer);
|
||||
if (!flattener.Consume(context_, table)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
|
||||
return false;
|
||||
bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) {
|
||||
switch (format) {
|
||||
case OutputFormat::kApk: {
|
||||
BigBuffer buffer(1024);
|
||||
TableFlattener flattener(options_.table_flattener_options, &buffer);
|
||||
if (!flattener.Consume(context_, table)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
|
||||
return false;
|
||||
}
|
||||
|
||||
io::BigBufferInputStream input_stream(&buffer);
|
||||
return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath,
|
||||
ArchiveEntry::kAlign, writer);
|
||||
} break;
|
||||
|
||||
case OutputFormat::kProto: {
|
||||
pb::ResourceTable pb_table;
|
||||
SerializeTableToPb(*table, &pb_table);
|
||||
return io::CopyProtoToArchive(context_, &pb_table, kProtoResourceTablePath,
|
||||
ArchiveEntry::kCompress, writer);
|
||||
} break;
|
||||
}
|
||||
|
||||
io::BigBufferInputStream input_stream(&buffer);
|
||||
return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc",
|
||||
ArchiveEntry::kAlign, writer);
|
||||
}
|
||||
|
||||
bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
|
||||
pb::ResourceTable pb_table;
|
||||
SerializeTableToPb(*table, &pb_table);
|
||||
return io::CopyProtoToArchive(context_, &pb_table, "resources.arsc.flat", 0, writer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
|
||||
@@ -1172,7 +1202,7 @@ class LinkCommand {
|
||||
}
|
||||
|
||||
std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) {
|
||||
io::IFile* file = collection->FindFile("resources.arsc.flat");
|
||||
io::IFile* file = collection->FindFile(kProtoResourceTablePath);
|
||||
if (!file) {
|
||||
return {};
|
||||
}
|
||||
@@ -1466,15 +1496,13 @@ class LinkCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the AndroidManifest, ResourceTable, and all XML files referenced by
|
||||
* the ResourceTable to the IArchiveWriter.
|
||||
*/
|
||||
// Writes the AndroidManifest, ResourceTable, and all XML files referenced by the ResourceTable
|
||||
// to the IArchiveWriter.
|
||||
bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
|
||||
ResourceTable* table) {
|
||||
const bool keep_raw_values = context_->GetPackageType() == PackageType::kStaticLib;
|
||||
bool result = FlattenXml(context_, manifest, "AndroidManifest.xml", keep_raw_values,
|
||||
true /*utf16*/, writer);
|
||||
bool result = FlattenXml(context_, *manifest, "AndroidManifest.xml", keep_raw_values,
|
||||
true /*utf16*/, options_.output_format, writer);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
@@ -1489,6 +1517,7 @@ class LinkCommand {
|
||||
file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
|
||||
file_flattener_options.update_proguard_spec =
|
||||
static_cast<bool>(options_.generate_proguard_rules_path);
|
||||
file_flattener_options.output_format = options_.output_format;
|
||||
|
||||
ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set);
|
||||
|
||||
@@ -1497,15 +1526,9 @@ class LinkCommand {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (context_->GetPackageType() == PackageType::kStaticLib) {
|
||||
if (!FlattenTableToPb(table, writer)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!FlattenTable(table, writer)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc");
|
||||
return false;
|
||||
}
|
||||
if (!FlattenTable(table, options_.output_format, writer)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resource table");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1869,6 +1892,7 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
|
||||
bool verbose = false;
|
||||
bool shared_lib = false;
|
||||
bool static_lib = false;
|
||||
bool proto_format = false;
|
||||
Maybe<std::string> stable_id_file_path;
|
||||
std::vector<std::string> split_args;
|
||||
Flags flags =
|
||||
@@ -1949,6 +1973,10 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
|
||||
.OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
|
||||
&shared_lib)
|
||||
.OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
|
||||
.OptionalSwitch("--proto-format",
|
||||
"Generates compiled resources in Protobuf format.\n"
|
||||
"Suitable as input to the bundle tool for generating an App Bundle.",
|
||||
&proto_format)
|
||||
.OptionalSwitch("--no-static-lib-packages",
|
||||
"Merge all library resources under the app's package.",
|
||||
&options.no_static_lib_packages)
|
||||
@@ -2035,21 +2063,25 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
|
||||
context.SetVerbose(verbose);
|
||||
}
|
||||
|
||||
if (shared_lib && static_lib) {
|
||||
context.GetDiagnostics()->Error(DiagMessage()
|
||||
<< "only one of --shared-lib and --static-lib can be defined");
|
||||
if (int{shared_lib} + int{static_lib} + int{proto_format} > 1) {
|
||||
context.GetDiagnostics()->Error(
|
||||
DiagMessage()
|
||||
<< "only one of --shared-lib, --static-lib, or --proto_format can be defined");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The default build type.
|
||||
context.SetPackageType(PackageType::kApp);
|
||||
context.SetPackageId(kAppPackageId);
|
||||
|
||||
if (shared_lib) {
|
||||
context.SetPackageType(PackageType::kSharedLib);
|
||||
context.SetPackageId(0x00);
|
||||
} else if (static_lib) {
|
||||
context.SetPackageType(PackageType::kStaticLib);
|
||||
context.SetPackageId(kAppPackageId);
|
||||
} else {
|
||||
context.SetPackageType(PackageType::kApp);
|
||||
context.SetPackageId(kAppPackageId);
|
||||
options.output_format = OutputFormat::kProto;
|
||||
} else if (proto_format) {
|
||||
options.output_format = OutputFormat::kProto;
|
||||
}
|
||||
|
||||
if (package_id) {
|
||||
|
||||
@@ -43,7 +43,7 @@ TEST(ContainerTest, SerializeCompiledFile) {
|
||||
|
||||
pb::internal::CompiledFile pb_compiled_file;
|
||||
pb_compiled_file.set_resource_name("android:layout/main.xml");
|
||||
pb_compiled_file.set_type(pb::internal::CompiledFile::Type::CompiledFile_Type_PROTO_XML);
|
||||
pb_compiled_file.set_type(pb::FileReference::PROTO_XML);
|
||||
pb_compiled_file.set_source_path("res/layout/main.xml");
|
||||
io::StringInputStream data(expected_data);
|
||||
ASSERT_TRUE(writer.AddResFileEntry(pb_compiled_file, &data));
|
||||
|
||||
@@ -56,9 +56,9 @@ static bool cmp_xml_attribute_by_id(const xml::Attribute* a, const xml::Attribut
|
||||
return false;
|
||||
}
|
||||
|
||||
class XmlFlattenerVisitor : public xml::Visitor {
|
||||
class XmlFlattenerVisitor : public xml::ConstVisitor {
|
||||
public:
|
||||
using xml::Visitor::Visit;
|
||||
using xml::ConstVisitor::Visit;
|
||||
|
||||
StringPool pool;
|
||||
std::map<uint8_t, StringPool> package_pools;
|
||||
@@ -74,7 +74,7 @@ class XmlFlattenerVisitor : public xml::Visitor {
|
||||
: buffer_(buffer), options_(options) {
|
||||
}
|
||||
|
||||
void Visit(xml::Text* node) override {
|
||||
void Visit(const xml::Text* node) override {
|
||||
if (util::TrimWhitespace(node->text).empty()) {
|
||||
// Skip whitespace only text nodes.
|
||||
return;
|
||||
@@ -95,7 +95,7 @@ class XmlFlattenerVisitor : public xml::Visitor {
|
||||
writer.Finish();
|
||||
}
|
||||
|
||||
void Visit(xml::Element* node) override {
|
||||
void Visit(const xml::Element* node) override {
|
||||
for (const xml::NamespaceDecl& decl : node->namespace_decls) {
|
||||
// Skip dedicated tools namespace.
|
||||
if (decl.uri != xml::kSchemaTools) {
|
||||
@@ -125,7 +125,7 @@ class XmlFlattenerVisitor : public xml::Visitor {
|
||||
start_writer.Finish();
|
||||
}
|
||||
|
||||
xml::Visitor::Visit(node);
|
||||
xml::ConstVisitor::Visit(node);
|
||||
|
||||
{
|
||||
ChunkWriter end_writer(buffer_);
|
||||
@@ -182,12 +182,13 @@ class XmlFlattenerVisitor : public xml::Visitor {
|
||||
writer.Finish();
|
||||
}
|
||||
|
||||
void WriteAttributes(xml::Element* node, ResXMLTree_attrExt* flat_elem, ChunkWriter* writer) {
|
||||
void WriteAttributes(const xml::Element* node, ResXMLTree_attrExt* flat_elem,
|
||||
ChunkWriter* writer) {
|
||||
filtered_attrs_.clear();
|
||||
filtered_attrs_.reserve(node->attributes.size());
|
||||
|
||||
// Filter the attributes.
|
||||
for (xml::Attribute& attr : node->attributes) {
|
||||
for (const xml::Attribute& attr : node->attributes) {
|
||||
if (attr.namespace_uri != xml::kSchemaTools) {
|
||||
filtered_attrs_.push_back(&attr);
|
||||
}
|
||||
@@ -282,12 +283,12 @@ class XmlFlattenerVisitor : public xml::Visitor {
|
||||
XmlFlattenerOptions options_;
|
||||
|
||||
// Scratch vector to filter attributes. We avoid allocations making this a member.
|
||||
std::vector<xml::Attribute*> filtered_attrs_;
|
||||
std::vector<const xml::Attribute*> filtered_attrs_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool XmlFlattener::Flatten(IAaptContext* context, xml::Node* node) {
|
||||
bool XmlFlattener::Flatten(IAaptContext* context, const xml::Node* node) {
|
||||
BigBuffer node_buffer(1024);
|
||||
XmlFlattenerVisitor visitor(&node_buffer, options_);
|
||||
node->Accept(&visitor);
|
||||
@@ -341,7 +342,7 @@ bool XmlFlattener::Flatten(IAaptContext* context, xml::Node* node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XmlFlattener::Consume(IAaptContext* context, xml::XmlResource* resource) {
|
||||
bool XmlFlattener::Consume(IAaptContext* context, const xml::XmlResource* resource) {
|
||||
if (!resource->root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,18 +34,18 @@ struct XmlFlattenerOptions {
|
||||
bool use_utf16 = false;
|
||||
};
|
||||
|
||||
class XmlFlattener : public IXmlResourceConsumer {
|
||||
class XmlFlattener {
|
||||
public:
|
||||
XmlFlattener(BigBuffer* buffer, XmlFlattenerOptions options)
|
||||
: buffer_(buffer), options_(options) {
|
||||
}
|
||||
|
||||
bool Consume(IAaptContext* context, xml::XmlResource* resource) override;
|
||||
bool Consume(IAaptContext* context, const xml::XmlResource* resource);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(XmlFlattener);
|
||||
|
||||
bool Flatten(IAaptContext* context, xml::Node* node);
|
||||
bool Flatten(IAaptContext* context, const xml::Node* node);
|
||||
|
||||
BigBuffer* buffer_;
|
||||
XmlFlattenerOptions options_;
|
||||
|
||||
@@ -390,8 +390,15 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr
|
||||
}
|
||||
|
||||
ResourceTableType* type = pkg->FindOrCreateType(*res_type);
|
||||
if (pb_type.has_type_id()) {
|
||||
type->id = static_cast<uint8_t>(pb_type.type_id().id());
|
||||
}
|
||||
|
||||
for (const pb::Entry& pb_entry : pb_type.entry()) {
|
||||
ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name());
|
||||
if (pb_entry.has_entry_id()) {
|
||||
entry->id = static_cast<uint16_t>(pb_entry.entry_id().id());
|
||||
}
|
||||
|
||||
// Deserialize the symbol status (public/private with source and comments).
|
||||
if (pb_entry.has_symbol_status()) {
|
||||
@@ -405,21 +412,11 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr
|
||||
|
||||
const SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility());
|
||||
entry->symbol_status.state = visibility;
|
||||
|
||||
if (visibility == SymbolState::kPublic) {
|
||||
// This is a public symbol, we must encode the ID now if there is one.
|
||||
if (pb_entry.has_entry_id()) {
|
||||
entry->id = static_cast<uint16_t>(pb_entry.entry_id().id());
|
||||
}
|
||||
|
||||
if (type->symbol_status.state != SymbolState::kPublic) {
|
||||
// If the type has not been made public, do so now.
|
||||
type->symbol_status.state = SymbolState::kPublic;
|
||||
if (pb_type.has_type_id()) {
|
||||
type->id = static_cast<uint8_t>(pb_type.type_id().id());
|
||||
}
|
||||
}
|
||||
// Propagate the public visibility up to the Type.
|
||||
type->symbol_status.state = SymbolState::kPublic;
|
||||
} else if (visibility == SymbolState::kPrivate) {
|
||||
// Only propagate if no previous state was assigned.
|
||||
if (type->symbol_status.state == SymbolState::kUndefined) {
|
||||
type->symbol_status.state = SymbolState::kPrivate;
|
||||
}
|
||||
@@ -484,15 +481,14 @@ bool DeserializeTableFromPb(const pb::ResourceTable& pb_table, ResourceTable* ou
|
||||
return true;
|
||||
}
|
||||
|
||||
static ResourceFile::Type DeserializeCompiledFileType(
|
||||
const pb::internal::CompiledFile::Type& pb_type) {
|
||||
switch (pb_type) {
|
||||
case pb::internal::CompiledFile::Type::CompiledFile_Type_PNG:
|
||||
return ResourceFile::Type::kPng;
|
||||
case pb::internal::CompiledFile::Type::CompiledFile_Type_BINARY_XML:
|
||||
static ResourceFile::Type DeserializeFileReferenceTypeFromPb(const pb::FileReference::Type& type) {
|
||||
switch (type) {
|
||||
case pb::FileReference::BINARY_XML:
|
||||
return ResourceFile::Type::kBinaryXml;
|
||||
case pb::internal::CompiledFile::Type::CompiledFile_Type_PROTO_XML:
|
||||
case pb::FileReference::PROTO_XML:
|
||||
return ResourceFile::Type::kProtoXml;
|
||||
case pb::FileReference::PNG:
|
||||
return ResourceFile::Type::kPng;
|
||||
default:
|
||||
return ResourceFile::Type::kUnknown;
|
||||
}
|
||||
@@ -510,7 +506,7 @@ bool DeserializeCompiledFileFromPb(const pb::internal::CompiledFile& pb_file,
|
||||
|
||||
out_file->name = name_ref.ToResourceName();
|
||||
out_file->source.path = pb_file.source_path();
|
||||
out_file->type = DeserializeCompiledFileType(pb_file.type());
|
||||
out_file->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
|
||||
|
||||
std::string config_error;
|
||||
if (!DeserializeConfigFromPb(pb_file.config(), &out_file->config, &config_error)) {
|
||||
@@ -773,8 +769,12 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
|
||||
} break;
|
||||
|
||||
case pb::Item::kFile: {
|
||||
return util::make_unique<FileReference>(value_pool->MakeRef(
|
||||
pb_item.file().path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
|
||||
const pb::FileReference& pb_file = pb_item.file();
|
||||
std::unique_ptr<FileReference> file_ref =
|
||||
util::make_unique<FileReference>(value_pool->MakeRef(
|
||||
pb_file.path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
|
||||
file_ref->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
|
||||
return std::move(file_ref);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -361,6 +361,19 @@ static pb::Plural_Arity SerializePluralEnumToPb(size_t plural_idx) {
|
||||
return pb::Plural_Arity_OTHER;
|
||||
}
|
||||
|
||||
static pb::FileReference::Type SerializeFileReferenceTypeToPb(const ResourceFile::Type& type) {
|
||||
switch (type) {
|
||||
case ResourceFile::Type::kBinaryXml:
|
||||
return pb::FileReference::BINARY_XML;
|
||||
case ResourceFile::Type::kProtoXml:
|
||||
return pb::FileReference::PROTO_XML;
|
||||
case ResourceFile::Type::kPng:
|
||||
return pb::FileReference::PNG;
|
||||
default:
|
||||
return pb::FileReference::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ValueSerializer : public ConstValueVisitor {
|
||||
@@ -395,7 +408,9 @@ class ValueSerializer : public ConstValueVisitor {
|
||||
}
|
||||
|
||||
void Visit(const FileReference* file) override {
|
||||
out_value_->mutable_item()->mutable_file()->set_path(*file->path);
|
||||
pb::FileReference* pb_file = out_value_->mutable_item()->mutable_file();
|
||||
pb_file->set_path(*file->path);
|
||||
pb_file->set_type(SerializeFileReferenceTypeToPb(file->type));
|
||||
}
|
||||
|
||||
void Visit(const Id* /*id*/) override {
|
||||
@@ -507,23 +522,10 @@ void SerializeItemToPb(const Item& item, pb::Item* out_item) {
|
||||
out_item->MergeFrom(value.item());
|
||||
}
|
||||
|
||||
static pb::internal::CompiledFile::Type SerializeCompiledFileType(const ResourceFile::Type& type) {
|
||||
switch (type) {
|
||||
case ResourceFile::Type::kPng:
|
||||
return pb::internal::CompiledFile::Type::CompiledFile_Type_PNG;
|
||||
case ResourceFile::Type::kBinaryXml:
|
||||
return pb::internal::CompiledFile::Type::CompiledFile_Type_BINARY_XML;
|
||||
case ResourceFile::Type::kProtoXml:
|
||||
return pb::internal::CompiledFile::Type::CompiledFile_Type_PROTO_XML;
|
||||
default:
|
||||
return pb::internal::CompiledFile::Type::CompiledFile_Type_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeCompiledFileToPb(const ResourceFile& file, pb::internal::CompiledFile* out_file) {
|
||||
out_file->set_resource_name(file.name.ToString());
|
||||
out_file->set_source_path(file.source.path);
|
||||
out_file->set_type(SerializeCompiledFileType(file.type));
|
||||
out_file->set_type(SerializeFileReferenceTypeToPb(file.type));
|
||||
SerializeConfig(file.config, out_file->mutable_config());
|
||||
|
||||
for (const SourcedResourceName& exported : file.exported_symbols) {
|
||||
|
||||
Reference in New Issue
Block a user