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

Commit dfbac39d authored by Iurii Makhno's avatar Iurii Makhno
Browse files

Introduce ResourceNamedType that represents pair of name + ResourceType.

This type will be used as part of ResourceName to support types with
custom names inside aapt2.

DD: go/custom-resource-types-in-aapt2

Bug: b/215108200
Test: Resource_test.cpp
Change-Id: Ib09776e6b2f69fefb9724136a345dc25bea42573
parent 4095c9f3
Loading
Loading
Loading
Loading
+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)) {
+124 −4
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,6 +76,52 @@ 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.
@@ -294,6 +339,81 @@ 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.
//
+103 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@

#include "test/Test.h"

using ::testing::Eq;
using ::testing::Optional;

namespace aapt {

TEST(ResourceTypeTest, ParseResourceTypes) {
@@ -125,4 +128,104 @@ TEST(ResourceTypeTest, ParseResourceTypes) {
  EXPECT_EQ(type, nullptr);
}

TEST(ResourceTypeTest, ParseResourceNamedType) {
  auto type = ParseResourceNamedType("anim");
  EXPECT_THAT(type, Optional(Eq(ResourceNamedType("anim", ResourceType::kAnim))));

  type = ParseResourceNamedType("layout");
  EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout", ResourceType::kLayout))));

  type = ParseResourceNamedType("layout:2");
  EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:2", ResourceType::kLayout))));

  type = ParseResourceNamedType("layout:another");
  EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:another", ResourceType::kLayout))));

  type = ParseResourceNamedType("layout:");
  EXPECT_THAT(type, Eq(std::nullopt));

  type = ParseResourceNamedType("layout2");
  EXPECT_THAT(type, Eq(std::nullopt));

  type = ParseResourceNamedType("blahaha");
  EXPECT_THAT(type, Eq(std::nullopt));
}

TEST(ResourceTypeTest, ResourceNamedTypeWithDefaultName) {
  auto type = ResourceNamedTypeWithDefaultName(ResourceType::kAnim);
  EXPECT_THAT(type, Eq(ResourceNamedType("anim", ResourceType::kAnim)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kAnimator);
  EXPECT_THAT(type, Eq(ResourceNamedType("animator", ResourceType::kAnimator)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kArray);
  EXPECT_THAT(type, Eq(ResourceNamedType("array", ResourceType::kArray)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kAttr);
  EXPECT_THAT(type, Eq(ResourceNamedType("attr", ResourceType::kAttr)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kAttrPrivate);
  EXPECT_THAT(type, Eq(ResourceNamedType("^attr-private", ResourceType::kAttrPrivate)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kBool);
  EXPECT_THAT(type, Eq(ResourceNamedType("bool", ResourceType::kBool)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kColor);
  EXPECT_THAT(type, Eq(ResourceNamedType("color", ResourceType::kColor)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kConfigVarying);
  EXPECT_THAT(type, Eq(ResourceNamedType("configVarying", ResourceType::kConfigVarying)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kDimen);
  EXPECT_THAT(type, Eq(ResourceNamedType("dimen", ResourceType::kDimen)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kDrawable);
  EXPECT_THAT(type, Eq(ResourceNamedType("drawable", ResourceType::kDrawable)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kFont);
  EXPECT_THAT(type, Eq(ResourceNamedType("font", ResourceType::kFont)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kFraction);
  EXPECT_THAT(type, Eq(ResourceNamedType("fraction", ResourceType::kFraction)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kId);
  EXPECT_THAT(type, Eq(ResourceNamedType("id", ResourceType::kId)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kInteger);
  EXPECT_THAT(type, Eq(ResourceNamedType("integer", ResourceType::kInteger)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kInterpolator);
  EXPECT_THAT(type, Eq(ResourceNamedType("interpolator", ResourceType::kInterpolator)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kLayout);
  EXPECT_THAT(type, Eq(ResourceNamedType("layout", ResourceType::kLayout)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kMenu);
  EXPECT_THAT(type, Eq(ResourceNamedType("menu", ResourceType::kMenu)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kMipmap);
  EXPECT_THAT(type, Eq(ResourceNamedType("mipmap", ResourceType::kMipmap)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kNavigation);
  EXPECT_THAT(type, Eq(ResourceNamedType("navigation", ResourceType::kNavigation)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kPlurals);
  EXPECT_THAT(type, Eq(ResourceNamedType("plurals", ResourceType::kPlurals)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kRaw);
  EXPECT_THAT(type, Eq(ResourceNamedType("raw", ResourceType::kRaw)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kString);
  EXPECT_THAT(type, Eq(ResourceNamedType("string", ResourceType::kString)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kStyle);
  EXPECT_THAT(type, Eq(ResourceNamedType("style", ResourceType::kStyle)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kTransition);
  EXPECT_THAT(type, Eq(ResourceNamedType("transition", ResourceType::kTransition)));

  type = ResourceNamedTypeWithDefaultName(ResourceType::kXml);
  EXPECT_THAT(type, Eq(ResourceNamedType("xml", ResourceType::kXml)));
}

}  // namespace aapt