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
This commit is contained in:
Iurii Makhno
2022-02-15 20:02:52 +00:00
parent 4095c9f3fa
commit dfbac39d38
3 changed files with 245 additions and 4 deletions

View File

@@ -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)) {

View File

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

View File

@@ -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