Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17cd0bca authored by Iurii Makhno's avatar Iurii Makhno Committed by Android (Google) Code Review
Browse files

Merge changes I0b97fc00,Ib09776e6

* changes:
  Switch ResourceName to use ResourceNamedType instead of ResourceType.
  Introduce ResourceNamedType that represents pair of name + ResourceType.
parents 8d25bbe0 cff10cec
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ class ValueHeadlinePrinter : public ConstValueVisitor {
          printer_->Print(parent_name.package);
          printer_->Print(":");
        }
        printer_->Print(to_string(parent_name.type));
        printer_->Print(parent_name.type.to_string());
        printer_->Print("/");
        printer_->Print(parent_name.entry);
        if (parent_ref.id) {
+18 −0
Original line number Diff line number Diff line
@@ -134,6 +134,24 @@ static const std::map<StringPiece, ResourceType> sResourceTypeMap{
    {"xml", ResourceType::kXml},
};

ResourceNamedTypeRef ResourceNamedTypeWithDefaultName(ResourceType t) {
  return {to_string(t), t};
}

std::optional<ResourceNamedTypeRef> ParseResourceNamedType(const android::StringPiece& s) {
  auto colon = std::find(s.begin(), s.end(), ':');
  const ResourceType* parsedType;
  if (colon != s.end() && colon != std::prev(s.end())) {
    parsedType = ParseResourceType(s.substr(s.begin(), colon));
  } else {
    parsedType = ParseResourceType(s);
  }
  if (parsedType == nullptr) {
    return std::nullopt;
  }
  return ResourceNamedTypeRef(s, *parsedType);
}

const ResourceType* ParseResourceType(const StringPiece& str) {
  auto iter = sResourceTypeMap.find(str);
  if (iter == std::end(sResourceTypeMap)) {
+147 −10
Original line number Diff line number Diff line
@@ -19,22 +19,21 @@

#include <iomanip>
#include <limits>
#include <optional>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>

#include "Source.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "utils/JenkinsHash.h"

#include "Source.h"

namespace aapt {

/**
 * The various types of resource types available. Corresponds
 * to the 'type' in package:type/entry.
 * The various types of resource types available.
 */
enum class ResourceType {
  kAnim,
@@ -77,16 +76,64 @@ android::StringPiece to_string(ResourceType type);
 */
const ResourceType* ParseResourceType(const android::StringPiece& str);

/**
 * Pair of type name as in ResourceTable and actual resource type.
 * Corresponds to the 'type' in package:type/entry.
 *
 * This is to support resource types with custom names inside resource tables.
 */
struct ResourceNamedType {
  std::string name;
  ResourceType type = ResourceType::kRaw;

  ResourceNamedType() = default;
  ResourceNamedType(const android::StringPiece& n, ResourceType t);

  int compare(const ResourceNamedType& other) const;

  const std::string& to_string() const;
};

/**
 * Same as ResourceNamedType, but uses StringPieces instead.
 * Use this if you need to avoid copying and know that
 * the lifetime of this object is shorter than that
 * of the original string.
 */
struct ResourceNamedTypeRef {
  android::StringPiece name;
  ResourceType type = ResourceType::kRaw;

  ResourceNamedTypeRef() = default;
  ResourceNamedTypeRef(const ResourceNamedTypeRef&) = default;
  ResourceNamedTypeRef(ResourceNamedTypeRef&&) = default;
  ResourceNamedTypeRef(const ResourceNamedType& rhs);  // NOLINT(google-explicit-constructor)
  ResourceNamedTypeRef(const android::StringPiece& n, ResourceType t);
  ResourceNamedTypeRef& operator=(const ResourceNamedTypeRef& rhs) = default;
  ResourceNamedTypeRef& operator=(ResourceNamedTypeRef&& rhs) = default;
  ResourceNamedTypeRef& operator=(const ResourceNamedType& rhs);

  ResourceNamedType ToResourceNamedType() const;

  std::string to_string() const;
};

ResourceNamedTypeRef ResourceNamedTypeWithDefaultName(ResourceType t);

std::optional<ResourceNamedTypeRef> ParseResourceNamedType(const android::StringPiece& s);

/**
 * A resource's name. This can uniquely identify
 * a resource in the ResourceTable.
 */
struct ResourceName {
  std::string package;
  ResourceType type = ResourceType::kRaw;
  ResourceNamedType type;
  std::string entry;

  ResourceName() = default;
  ResourceName(const android::StringPiece& p, const ResourceNamedTypeRef& t,
               const android::StringPiece& e);
  ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);

  int compare(const ResourceName& other) const;
@@ -103,13 +150,15 @@ struct ResourceName {
 */
struct ResourceNameRef {
  android::StringPiece package;
  ResourceType type = ResourceType::kRaw;
  ResourceNamedTypeRef type;
  android::StringPiece entry;

  ResourceNameRef() = default;
  ResourceNameRef(const ResourceNameRef&) = default;
  ResourceNameRef(ResourceNameRef&&) = default;
  ResourceNameRef(const ResourceName& rhs);  // NOLINT(google-explicit-constructor)
  ResourceNameRef(const android::StringPiece& p, const ResourceNamedTypeRef& t,
                  const android::StringPiece& e);
  ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
  ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
  ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -294,18 +343,99 @@ inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val)
  return out << to_string(val);
}

//
// ResourceNamedType implementation.
//
inline ResourceNamedType::ResourceNamedType(const android::StringPiece& n, ResourceType t)
    : name(n.to_string()), type(t) {
}

inline int ResourceNamedType::compare(const ResourceNamedType& other) const {
  int cmp = static_cast<int>(type) - static_cast<int>(other.type);
  if (cmp != 0) return cmp;
  cmp = name.compare(other.name);
  return cmp;
}

inline const std::string& ResourceNamedType::to_string() const {
  return name;
}

inline bool operator<(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
  return lhs.compare(rhs) < 0;
}

inline bool operator==(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
  return lhs.compare(rhs) == 0;
}

inline bool operator!=(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
  return lhs.compare(rhs) != 0;
}

inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNamedType& val) {
  return out << val.to_string();
}

//
// ResourceNamedTypeRef implementation.
//
inline ResourceNamedTypeRef::ResourceNamedTypeRef(const android::StringPiece& n, ResourceType t)
    : name(n), type(t) {
}

inline ResourceNamedTypeRef::ResourceNamedTypeRef(const ResourceNamedType& rhs)
    : name(rhs.name), type(rhs.type) {
}

inline ResourceNamedTypeRef& ResourceNamedTypeRef::operator=(const ResourceNamedType& rhs) {
  name = rhs.name;
  type = rhs.type;
  return *this;
}

inline ResourceNamedType ResourceNamedTypeRef::ToResourceNamedType() const {
  return ResourceNamedType(name, type);
}

inline std::string ResourceNamedTypeRef::to_string() const {
  return name.to_string();
}

inline bool operator<(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
  return std::tie(lhs.type, lhs.name) < std::tie(rhs.type, rhs.name);
}

inline bool operator==(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
  return std::tie(lhs.type, lhs.name) == std::tie(rhs.type, rhs.name);
}

inline bool operator!=(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
  return std::tie(lhs.type, lhs.name) != std::tie(rhs.type, rhs.name);
}

inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNamedTypeRef& val) {
  return out << val.name;
}

//
// ResourceName implementation.
//

inline ResourceName::ResourceName(const android::StringPiece& p, const ResourceNamedTypeRef& t,
                                  const android::StringPiece& e)
    : package(p.to_string()), type(t.ToResourceNamedType()), entry(e.to_string()) {
}

inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
                                  const android::StringPiece& e)
    : package(p.to_string()), type(t), entry(e.to_string()) {}
    : ResourceName(p, ResourceNamedTypeWithDefaultName(t), e) {
}

inline int ResourceName::compare(const ResourceName& other) const {
  int cmp = package.compare(other.package);
  if (cmp != 0) return cmp;
  cmp = static_cast<int>(type) - static_cast<int>(other.type);
  cmp = type.compare(other.type);
  if (cmp != 0) return cmp;
  cmp = entry.compare(other.entry);
  return cmp;
@@ -341,9 +471,16 @@ inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name)
inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
    : package(rhs.package), type(rhs.type), entry(rhs.entry) {}

inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p,
                                        const ResourceNamedTypeRef& t,
                                        const android::StringPiece& e)
    : package(p), type(t), entry(e) {
}

inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
                                        const android::StringPiece& e)
    : package(p), type(t), entry(e) {}
    : ResourceNameRef(p, ResourceNamedTypeWithDefaultName(t), e) {
}

inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
  package = rhs.package;
@@ -400,7 +537,7 @@ struct hash<aapt::ResourceName> {
  size_t operator()(const aapt::ResourceName& name) const {
    android::hash_t h = 0;
    h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package)));
    h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
    h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.type.name)));
    h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry)));
    return static_cast<size_t>(h);
  }
+31 −22
Original line number Diff line number Diff line
@@ -604,7 +604,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
      return false;
    }

    out_resource->name.type = ResourceType::kId;
    out_resource->name.type =
        ResourceNamedTypeWithDefaultName(ResourceType::kId).ToResourceNamedType();
    out_resource->name.entry = maybe_name.value().to_string();

    // Ids either represent a unique resource id or reference another resource id
@@ -623,7 +624,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
        // A null reference also means there is no inner element when ids are in the form:
        //    <id name="name"/>
        out_resource->value = util::make_unique<Id>();
      } else if (!ref || ref->name.value().type != ResourceType::kId) {
      } else if (!ref || ref->name.value().type.type != ResourceType::kId) {
        // If an inner element exists, the inner element must be a reference to another resource id
        diag_->Error(DiagMessage(out_resource->source)
                         << "<" << parser->element_name()
@@ -640,7 +641,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
      return false;
    }

    out_resource->name.type = ResourceType::kMacro;
    out_resource->name.type =
        ResourceNamedTypeWithDefaultName(ResourceType::kMacro).ToResourceNamedType();
    out_resource->name.entry = maybe_name.value().to_string();
    return ParseMacro(parser, out_resource);
  }
@@ -656,7 +658,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
        return false;
      }

      out_resource->name.type = item_iter->second.type;
      out_resource->name.type =
          ResourceNamedTypeWithDefaultName(item_iter->second.type).ToResourceNamedType();
      out_resource->name.entry = maybe_name.value().to_string();

      // Only use the implied format of the type when there is no explicit format.
@@ -699,7 +702,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
  if (can_be_item) {
    // Try parsing the elementName (or type) as a resource. These shall only be
    // resources like 'layout' or 'xml' and they can only be references.
    const ResourceType* parsed_type = ParseResourceType(resource_type);
    std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(resource_type);
    if (parsed_type) {
      if (!maybe_name) {
        diag_->Error(DiagMessage(out_resource->source)
@@ -708,7 +711,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
        return false;
      }

      out_resource->name.type = *parsed_type;
      out_resource->name.type = parsed_type->ToResourceNamedType();
      out_resource->name.entry = maybe_name.value().to_string();
      out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
      if (!out_resource->value) {
@@ -933,7 +936,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
    return false;
  }

  const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
  std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
  if (!parsed_type) {
    diag_->Error(DiagMessage(out_resource->source) << "invalid resource type '"
                                                   << maybe_type.value()
@@ -941,7 +944,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
    return false;
  }

  out_resource->name.type = *parsed_type;
  out_resource->name.type = parsed_type->ToResourceNamedType();

  if (std::optional<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "id")) {
    std::optional<ResourceId> maybe_id = ResourceUtils::ParseResourceId(maybe_id_str.value());
@@ -953,7 +956,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
    out_resource->id = maybe_id.value();
  }

  if (*parsed_type == ResourceType::kId) {
  if (parsed_type->type == ResourceType::kId) {
    // An ID marked as public is also the definition of an ID.
    out_resource->value = util::make_unique<Id>();
  }
@@ -978,7 +981,7 @@ bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resou
    return false;
  }

  const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
  std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
  if (!parsed_type) {
    diag->Error(DiagMessage(out_resource->source)
                << "invalid resource type '" << maybe_type.value() << "' in <" << tag_name << ">");
@@ -1096,7 +1099,7 @@ bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser,
    return false;
  }

  const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
  std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
  if (!parsed_type) {
    diag_->Error(DiagMessage(out_resource->source)
                 << "invalid resource type '" << maybe_type.value() << "' in <"
@@ -1104,7 +1107,7 @@ bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser,
    return false;
  }

  out_resource->name.type = *parsed_type;
  out_resource->name.type = parsed_type->ToResourceNamedType();
  return true;
}

@@ -1208,8 +1211,8 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
        continue;
      }

      const ResourceType* type = ParseResourceType(item_type.value());
      if (type == nullptr) {
      std::optional<ResourceNamedTypeRef> type = ParseResourceNamedType(item_type.value());
      if (!type) {
        diag_->Error(DiagMessage(element_source)
                     << "invalid resource type '" << item_type.value()
                     << "' in <item> within an <overlayable>");
@@ -1223,7 +1226,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
      overlayable_item.source = element_source;

      ParsedResource child_resource{};
      child_resource.name.type = *type;
      child_resource.name.type = type->ToResourceNamedType();
      child_resource.name.entry = item_name.value().to_string();
      child_resource.overlayable_item = overlayable_item;
      out_resource->child_resources.push_back(std::move(child_resource));
@@ -1289,7 +1292,8 @@ bool ResourceParser::ParseAttr(xml::XmlPullParser* parser,

bool ResourceParser::ParseAttrImpl(xml::XmlPullParser* parser,
                                   ParsedResource* out_resource, bool weak) {
  out_resource->name.type = ResourceType::kAttr;
  out_resource->name.type =
      ResourceNamedTypeWithDefaultName(ResourceType::kAttr).ToResourceNamedType();

  // Attributes only end up in default configuration.
  if (out_resource->config != ConfigDescription::DefaultConfig()) {
@@ -1475,7 +1479,8 @@ std::optional<Attribute::Symbol> ResourceParser::ParseEnumOrFlagItem(xml::XmlPul
  }

  return Attribute::Symbol{
      Reference(ResourceNameRef({}, ResourceType::kId, maybe_name.value())),
      Reference(ResourceNameRef({}, ResourceNamedTypeWithDefaultName(ResourceType::kId),
                                maybe_name.value())),
      val.data, val.dataType};
}

@@ -1509,7 +1514,7 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) {

bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
                                ParsedResource* out_resource) {
  out_resource->name.type = type;
  out_resource->name.type = ResourceNamedTypeWithDefaultName(type).ToResourceNamedType();

  std::unique_ptr<Style> style = util::make_unique<Style>();

@@ -1535,7 +1540,8 @@ bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* par
    size_t pos = style_name.find_last_of(u'.');
    if (pos != std::string::npos) {
      style->parent_inferred = true;
      style->parent = Reference(ResourceName({}, ResourceType::kStyle, style_name.substr(0, pos)));
      style->parent = Reference(ResourceName(
          {}, ResourceNamedTypeWithDefaultName(ResourceType::kStyle), style_name.substr(0, pos)));
    }
  }

@@ -1591,7 +1597,8 @@ bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser, ParsedResource
bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
                                    ParsedResource* out_resource,
                                    const uint32_t typeMask) {
  out_resource->name.type = ResourceType::kArray;
  out_resource->name.type =
      ResourceNamedTypeWithDefaultName(ResourceType::kArray).ToResourceNamedType();

  std::unique_ptr<Array> array = util::make_unique<Array>();

@@ -1646,7 +1653,8 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,

bool ResourceParser::ParsePlural(xml::XmlPullParser* parser,
                                 ParsedResource* out_resource) {
  out_resource->name.type = ResourceType::kPlurals;
  out_resource->name.type =
      ResourceNamedTypeWithDefaultName(ResourceType::kPlurals).ToResourceNamedType();

  std::unique_ptr<Plural> plural = util::make_unique<Plural>();

@@ -1727,7 +1735,8 @@ bool ResourceParser::ParsePlural(xml::XmlPullParser* parser,

bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser,
                                           ParsedResource* out_resource) {
  out_resource->name.type = ResourceType::kStyleable;
  out_resource->name.type =
      ResourceNamedTypeWithDefaultName(ResourceType::kStyleable).ToResourceNamedType();

  if (!options_.preserve_visibility_of_styleables) {
    // This was added in change Idd21b5de4d20be06c6f8c8eb5a22ccd68afc4927 to mimic aapt1, but no one
+4 −4
Original line number Diff line number Diff line
@@ -473,7 +473,7 @@ bool ResourceTable::AddResource(NewResource&& res, IDiagnostics* diag) {
  }

  auto package = FindOrCreatePackage(res.name.package);
  auto type = package->FindOrCreateType(res.name.type);
  auto type = package->FindOrCreateType(res.name.type.type);
  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry,
                                   NameEqualRange<ResourceEntry>{});
  const size_t entry_count = std::distance(entry_it.first, entry_it.second);
@@ -593,7 +593,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  ResourceTableType* type = package->FindType(name.type.type);
  if (type == nullptr) {
    return {};
  }
@@ -612,7 +612,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(const Res
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  ResourceTableType* type = package->FindType(name.type.type);
  if (type == nullptr) {
    return {};
  }
@@ -633,7 +633,7 @@ bool ResourceTable::RemoveResource(const ResourceNameRef& name, ResourceId id) c
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  ResourceTableType* type = package->FindType(name.type.type);
  if (type == nullptr) {
    return {};
  }
Loading