/*
 * 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.
 */

#include "Dump.h"

#include <cinttypes>
#include <vector>

#include "Debug.h"
#include "Diagnostics.h"
#include "LoadedApk.h"
#include "Util.h"
#include "android-base/stringprintf.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/FileStream.h"
#include "androidfw/StringPiece.h"
#include "format/Container.h"
#include "format/binary/BinaryResourceParser.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "io/ZipArchive.h"
#include "process/IResourceTableConsumer.h"
#include "text/Printer.h"
#include "util/Files.h"

using ::aapt::text::Printer;
using ::android::StringPiece;
using ::android::base::StringPrintf;

namespace aapt {

static const char* ResourceFileTypeToString(const ResourceFile::Type& type) {
  switch (type) {
    case ResourceFile::Type::kPng:
      return "PNG";
    case ResourceFile::Type::kBinaryXml:
      return "BINARY_XML";
    case ResourceFile::Type::kProtoXml:
      return "PROTO_XML";
    default:
      break;
  }
  return "UNKNOWN";
}

static void DumpCompiledFile(const ResourceFile& file, const android::Source& source,
                             off64_t offset, size_t len, Printer* printer) {
  printer->Print("Resource: ");
  printer->Println(file.name.to_string());

  printer->Print("Config:   ");
  printer->Println(file.config.to_string());

  printer->Print("Source:   ");
  printer->Println(file.source.to_string());

  printer->Print("Type:     ");
  printer->Println(ResourceFileTypeToString(file.type));

  printer->Println(StringPrintf("Data:     offset=%" PRIi64 " length=%zd", offset, len));
}

namespace {

class DumpContext : public IAaptContext {
 public:
  PackageType GetPackageType() override {
    // Doesn't matter.
    return PackageType::kApp;
  }

  android::IDiagnostics* GetDiagnostics() override {
    return &diagnostics_;
  }

  NameMangler* GetNameMangler() override {
    UNIMPLEMENTED(FATAL);
    return nullptr;
  }

  const std::string& GetCompilationPackage() override {
    static std::string empty;
    return empty;
  }

  uint8_t GetPackageId() override {
    return 0;
  }

  SymbolTable* GetExternalSymbols() override {
    UNIMPLEMENTED(FATAL);
    return nullptr;
  }

  bool IsVerbose() override {
    return verbose_;
  }

  void SetVerbose(bool val) {
    verbose_ = val;
    diagnostics_.SetVerbose(val);
  }

  int GetMinSdkVersion() override {
    return 0;
  }

  const std::set<std::string>& GetSplitNameDependencies() override {
    UNIMPLEMENTED(FATAL) << "Split Name Dependencies should not be necessary";
    static std::set<std::string> empty;
    return empty;
  }

 private:
  StdErrDiagnostics diagnostics_;
  bool verbose_ = false;
};

}  // namespace

int DumpAPCCommand::Action(const std::vector<std::string>& args) {
  DumpContext context;
  DebugPrintTableOptions print_options;
  print_options.show_sources = true;
  print_options.show_values = !no_values_;

  if (args.size() < 1) {
    diag_->Error(android::DiagMessage() << "No dump container specified");
    return 1;
  }

  bool error = false;
  for (auto container : args) {
    android::FileInputStream input(container);
    if (input.HadError()) {
      context.GetDiagnostics()->Error(android::DiagMessage(container)
                                      << "failed to open file: " << input.GetError());
      error = true;
      continue;
    }

    // Try as a compiled file.
    ContainerReader reader(&input);
    if (reader.HadError()) {
      context.GetDiagnostics()->Error(android::DiagMessage(container)
                                      << "failed to read container: " << reader.GetError());
      error = true;
      continue;
    }

    printer_->Println("AAPT2 Container (APC)");
    ContainerReaderEntry* entry;
    std::string error;
    while ((entry = reader.Next()) != nullptr) {
      if (entry->Type() == ContainerEntryType::kResTable) {
        printer_->Println("kResTable");

        pb::ResourceTable pb_table;
        if (!entry->GetResTable(&pb_table)) {
          context.GetDiagnostics()->Error(android::DiagMessage(container)
                                          << "failed to parse proto table: " << entry->GetError());
          error = true;
          continue;
        }

        ResourceTable table;
        error.clear();
        if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &error)) {
          context.GetDiagnostics()->Error(android::DiagMessage(container)
                                          << "failed to parse table: " << error);
          error = true;
          continue;
        }

        printer_->Indent();
        Debug::PrintTable(table, print_options, printer_);
        printer_->Undent();
      } else if (entry->Type() == ContainerEntryType::kResFile) {
        printer_->Println("kResFile");
        pb::internal::CompiledFile pb_compiled_file;
        off64_t offset;
        size_t length;
        if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) {
          context.GetDiagnostics()->Error(android::DiagMessage(container)
                                          << "failed to parse compiled proto file: "
                                          << entry->GetError());
          error = true;
          continue;
        }

        ResourceFile file;
        if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) {
          context.GetDiagnostics()->Warn(android::DiagMessage(container)
                                         << "failed to parse compiled file: " << error);
          error = true;
          continue;
        }

        printer_->Indent();
        DumpCompiledFile(file, android::Source(container), offset, length, printer_);
        printer_->Undent();
      }
    }
  }

  return (error) ? 1 : 0;
}

int DumpBadgerCommand::Action(const std::vector<std::string>& args) {
  printer_->Print(StringPrintf("%s", kBadgerData));
  printer_->Print("Did you mean \"aapt2 dump badging\"?\n");
  return 1;
}

int DumpConfigsCommand::Dump(LoadedApk* apk) {
  ResourceTable* table = apk->GetResourceTable();
  if (!table) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to retrieve resource table");
    return 1;
  }

  // Comparison function used to order configurations
  auto compare = [](android::ConfigDescription c1, android::ConfigDescription c2) -> bool {
    return c1.compare(c2) < 0;
  };

  // Insert the configurations into a set in order to keep every configuarion seen
  std::set<android::ConfigDescription, decltype(compare)> configs(compare);
  for (auto& package : table->packages) {
    for (auto& type : package->types) {
      for (auto& entry : type->entries) {
        for (auto& value : entry->values) {
          configs.insert(value->config);
        }
      }
    }
  }

  // Print the configurations in order
  for (auto& config : configs) {
    GetPrinter()->Print(StringPrintf("%s\n", config.to_string().data()));
  }
  return 0;
}

int DumpPackageNameCommand::Dump(LoadedApk* apk) {
  auto package_name = GetPackageName(apk);
  if (!package_name.has_value()) {
    return 1;
  }
  GetPrinter()->Println(*package_name);
  return 0;
}

int DumpStringsCommand::Dump(LoadedApk* apk) {
  ResourceTable* table = apk->GetResourceTable();
  if (!table) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to retrieve resource table");
    return 1;
  }

  // Load the run-time xml string pool using the flattened data
  android::BigBuffer buffer(4096);
  android::StringPool::FlattenUtf8(&buffer, table->string_pool, GetDiagnostics());
  auto data = buffer.to_string();
  android::ResStringPool pool(data.data(), data.size(), false);
  Debug::DumpResStringPool(&pool, GetPrinter());
  return 0;
}

int DumpStyleParentCommand::Dump(LoadedApk* apk) {
  auto package_name = GetPackageName(apk);
  if (!package_name.has_value()) {
    return 1;
  }

  const auto target_style = ResourceName(*package_name, ResourceType::kStyle, style_);
  const auto table = apk->GetResourceTable();

  if (!table) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to retrieve resource table");
    return 1;
  }

  std::optional<ResourceTable::SearchResult> target = table->FindResource(target_style);
  if (!target) {
    GetDiagnostics()->Error(android::DiagMessage()
                            << "Target style \"" << target_style.entry << "\" does not exist");
    return 1;
  }

  Debug::PrintStyleGraph(table, target_style);
  return 0;
}

int DumpTableCommand::Dump(LoadedApk* apk) {
  if (apk->GetApkFormat() == ApkFormat::kProto) {
    GetPrinter()->Println("Proto APK");
  } else {
    GetPrinter()->Println("Binary APK");
  }

  ResourceTable* table = apk->GetResourceTable();
  if (!table) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to retrieve resource table");
    return 1;
  }

  DebugPrintTableOptions print_options;
  print_options.show_sources = true;
  print_options.show_values = !no_values_;
  Debug::PrintTable(*table, print_options, GetPrinter());
  return 0;
}

int DumpXmlStringsCommand::Dump(LoadedApk* apk) {
  DumpContext context;
  bool error = false;
  for (auto xml_file : files_) {
    android::ResXMLTree tree;

    if (apk->GetApkFormat() == ApkFormat::kProto) {
      auto xml = apk->LoadXml(xml_file, GetDiagnostics());
      if (!xml) {
        error = true;
        continue;
      }

      // Flatten the xml document to get a binary representation of the proto xml file
      android::BigBuffer buffer(4096);
      XmlFlattenerOptions options = {};
      options.keep_raw_values = true;
      XmlFlattener flattener(&buffer, options);
      if (!flattener.Consume(&context, xml.get())) {
        error = true;
        continue;
      }

      // Load the run-time xml tree using the flattened data
      std::string data = buffer.to_string();
      tree.setTo(data.data(), data.size(), /** copyData */ true);

    } else if (apk->GetApkFormat() == ApkFormat::kBinary) {
      io::IFile* file = apk->GetFileCollection()->FindFile(xml_file);
      if (!file) {
        GetDiagnostics()->Error(android::DiagMessage(xml_file)
                                << "File '" << xml_file << "' not found in APK");
        error = true;
        continue;
      }

      std::unique_ptr<io::IData> data = file->OpenAsData();
      if (!data) {
        GetDiagnostics()->Error(android::DiagMessage() << "Failed to open " << xml_file);
        error = true;
        continue;
      }

      // Load the run-time xml tree from the file data
      tree.setTo(data->data(), data->size(), /** copyData */ true);
    } else {
      GetDiagnostics()->Error(android::DiagMessage(apk->GetSource()) << "Unknown APK format");
      error = true;
      continue;
    }

    Debug::DumpResStringPool(&tree.getStrings(), GetPrinter());
  }
  return (error) ? 1 : 0;
}

int DumpXmlTreeCommand::Dump(LoadedApk* apk) {
  for (auto file : files_) {
    auto xml = apk->LoadXml(file, GetDiagnostics());
    if (!xml) {
      return 1;
    }
    Debug::DumpXml(*xml, GetPrinter());
  }
  return 0;
}

int DumpOverlayableCommand::Dump(LoadedApk* apk) {
  ResourceTable* table = apk->GetResourceTable();
  if (!table) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to retrieve resource table");
    return 1;
  }

  Debug::DumpOverlayable(*table, GetPrinter());
  return 0;
}

const char DumpBadgerCommand::kBadgerData[2925] = {
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  95,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  61,  63,  86,  35,  40,  46,  46,
    95,  95,  95,  95,  97,  97,  44,  32,  46,  124, 42,  33,  83,  62,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  58,  46,  58,  59,  61,  59,  61,  81,  81,  81,  81,  66,  96,  61,  61,  58,  46,
    46,  46,  58,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  61,  59,  59,  59,  58,  106, 81,  81,
    81,  81,  102, 59,  61,  59,  59,  61,  61,  61,  58,  46,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    61,  59,  59,  59,  58,  109, 81,  81,  81,  81,  61,  59,  59,  59,  59,  59,  58,  59,  59,
    46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  46,  61,  59,  59,  59,  60,  81,  81,  81,  81,  87,  58,
    59,  59,  59,  59,  59,  59,  61,  119, 44,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  47,  61,  59,  59,
    58,  100, 81,  81,  81,  81,  35,  58,  59,  59,  59,  59,  59,  58,  121, 81,  91,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  46,  109, 58,  59,  59,  61,  81,  81,  81,  81,  81,  109, 58,  59,  59,  59,
    59,  61,  109, 81,  81,  76,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  41,  87,  59,  61,  59,  41,  81,  81,
    81,  81,  81,  81,  59,  61,  59,  59,  58,  109, 81,  81,  87,  39,  46,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    60,  81,  91,  59,  59,  61,  81,  81,  81,  81,  81,  87,  43,  59,  58,  59,  60,  81,  81,
    81,  76,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  52,  91,  58,  45,  59,  87,  81,  81,  81,  81,
    70,  58,  58,  58,  59,  106, 81,  81,  81,  91,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  93,  40,
    32,  46,  59,  100, 81,  81,  81,  81,  40,  58,  46,  46,  58,  100, 81,  81,  68,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  46,  46,  32,  46,
    46,  46,  32,  46,  32,  46,  45,  91,  59,  61,  58,  109, 81,  81,  81,  87,  46,  58,  61,
    59,  60,  81,  81,  80,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  46,  46,
    61,  59,  61,  61,  61,  59,  61,  61,  59,  59,  59,  58,  58,  46,  46,  41,  58,  59,  58,
    81,  81,  81,  81,  69,  58,  59,  59,  60,  81,  81,  68,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,
    32,  32,  32,  32,  58,  59,  61,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,
    59,  59,  61,  61,  46,  61,  59,  93,  81,  81,  81,  81,  107, 58,  59,  58,  109, 87,  68,
    96,  32,  32,  32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  10,  32,  32,  32,  46,  60,  61,  61,  59,  59,  59,  59,  59,  59,
    59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  58,  58,  58,  115, 109, 68,  41,  36,
    81,  109, 46,  61,  61,  81,  69,  96,  46,  58,  58,  46,  58,  46,  46,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  46,  32,  95,  81,  67,
    61,  61,  58,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,
    59,  59,  58,  68,  39,  61,  105, 61,  63,  81,  119, 58,  106, 80,  32,  58,  61,  59,  59,
    61,  59,  61,  59,  61,  46,  95,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  10,  32,  32,  36,  81,  109, 105, 59,  61,  59,  59,  59,  59,  59,  59,  59,  59,
    59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  46,  58,  37,  73,  108, 108, 62,  52,  81,
    109, 34,  32,  61,  59,  59,  59,  59,  59,  59,  59,  59,  59,  61,  59,  61,  61,  46,  46,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  46,  45,  57,  101, 43,  43,  61,
    61,  59,  59,  59,  59,  59,  59,  61,  59,  59,  59,  59,  59,  59,  59,  59,  59,  58,  97,
    46,  61,  108, 62,  126, 58,  106, 80,  96,  46,  61,  61,  59,  59,  59,  59,  59,  59,  59,
    59,  59,  59,  59,  59,  59,  61,  61,  97,  103, 97,  32,  32,  32,  32,  32,  32,  32,  10,
    32,  32,  32,  32,  45,  46,  32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  45,  45,  45,
    58,  59,  59,  59,  59,  61,  119, 81,  97,  124, 105, 124, 124, 39,  126, 95,  119, 58,  61,
    58,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  61,  119, 81,  81,
    99,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  58,  59,  59,  58,  106, 81,  81,  81,  109, 119,
    119, 119, 109, 109, 81,  81,  122, 58,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,
    59,  59,  59,  58,  115, 81,  87,  81,  102, 32,  32,  32,  32,  32,  32,  10,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  61,  58,
    59,  61,  81,  81,  81,  81,  81,  81,  87,  87,  81,  81,  81,  81,  81,  58,  59,  59,  59,
    59,  59,  59,  59,  59,  58,  45,  45,  45,  59,  59,  59,  41,  87,  66,  33,  32,  32,  32,
    32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  58,  59,  59,  93,  81,  81,  81,  81,  81,  81,  81,  81,  81,
    81,  81,  81,  81,  40,  58,  59,  59,  59,  58,  45,  32,  46,  32,  32,  32,  32,  32,  46,
    32,  126, 96,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  58,  61,  59,  58,  81,
    81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  40,  58,  59,  59,  59,  58,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  58,  59,  59,  58,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,
    81,  40,  58,  59,  59,  59,  46,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  58,  61,  59,  60,  81,  81,  81,  81,
    81,  81,  81,  81,  81,  81,  81,  81,  81,  59,  61,  59,  59,  61,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    58,  59,  59,  93,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  40,  59,
    59,  59,  59,  32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  58,  61,  58,  106, 81,  81,  81,  81,  81,  81,  81,
    81,  81,  81,  81,  81,  81,  76,  58,  59,  59,  59,  32,  46,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  61,  58,  58,
    81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  87,  58,  59,  59,  59,  59,
    32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  58,  59,  61,  41,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,
    81,  81,  87,  59,  61,  58,  59,  59,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  58,  61,  58,  61,  81,  81,
    81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  107, 58,  59,  59,  59,  59,  58,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  58,  59,  59,  58,  51,  81,  81,  81,  81,  81,  81,  81,  81,  81,  81,  102, 94,
    59,  59,  59,  59,  59,  61,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  58,  61,  59,  59,  59,  43,  63,  36,  81,
    81,  81,  87,  64,  86,  102, 58,  59,  59,  59,  59,  59,  59,  59,  46,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  61,
    59,  59,  59,  59,  59,  59,  59,  43,  33,  58,  126, 126, 58,  59,  59,  59,  59,  59,  59,
    59,  59,  59,  59,  32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  46,  61,  59,  59,  59,  58,  45,  58,  61,  59,  58,  58,  58,  61,
    59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  59,  58,  32,  46,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  61,  59,  59,  59,  59,  59,
    58,  95,  32,  45,  61,  59,  61,  59,  59,  59,  59,  59,  59,  59,  45,  58,  59,  59,  59,
    59,  61,  58,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  58,  61,  59,  59,  59,  59,  59,  61,  59,  61,  46,  46,  32,  45,  45,  45,  59,  58,
    45,  45,  46,  58,  59,  59,  59,  59,  59,  59,  61,  46,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  46,  58,  59,  59,  59,  59,  59,  59,  59,  59,  59,
    61,  59,  46,  32,  32,  46,  32,  46,  32,  58,  61,  59,  59,  59,  59,  59,  59,  59,  59,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  45,
    59,  59,  59,  59,  59,  59,  59,  59,  58,  32,  32,  32,  32,  32,  32,  32,  32,  32,  61,
    59,  59,  59,  59,  59,  59,  59,  58,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  46,  61,  59,  59,  59,  59,  59,  59,  59,  32,  46,  32,
    32,  32,  32,  32,  32,  61,  46,  61,  59,  59,  59,  59,  59,  59,  58,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  61,  59,  59,  59,
    59,  59,  59,  59,  59,  32,  46,  32,  32,  32,  32,  32,  32,  32,  46,  61,  58,  59,  59,
    59,  59,  59,  58,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  58,  59,  59,  59,  59,  59,  59,  59,  59,  46,  46,  32,  32,  32,  32,
    32,  32,  32,  61,  59,  59,  59,  59,  59,  59,  59,  45,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  32,  45,  61,  59,  59,  59,  59,
    59,  58,  32,  46,  32,  32,  32,  32,  32,  32,  32,  58,  59,  59,  59,  59,  59,  58,  45,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  45,  45,  45,  45,  32,  46,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  45,  61,  59,  58,  45,  45,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  10,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  46,  32,  32,  46,  32,  32,  32,  32,  32,  32,
    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  10};

int DumpChunks::Dump(LoadedApk* apk) {
  auto file = apk->GetFileCollection()->FindFile("resources.arsc");
  if (!file) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to find resources.arsc in APK");
    return 1;
  }

  auto data = file->OpenAsData();
  if (!data) {
    GetDiagnostics()->Error(android::DiagMessage() << "Failed to open resources.arsc ");
    return 1;
  }

  Debug::DumpChunks(data->data(), data->size(), GetPrinter(), GetDiagnostics());
  return 0;
}

}  // namespace aapt
