diff options
author | 2022-02-15 20:02:52 +0000 | |
---|---|---|
committer | 2022-02-16 20:07:05 +0000 | |
commit | dfbac39d3854daabdef722fd62ccb58203ff3e2d (patch) | |
tree | 8dfdbd0d4089e88c05e8b7b4b3ed6e655c2feae0 | |
parent | 4095c9f3faf14a333b5094f3ccf19af0ea0e9575 (diff) |
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
-rw-r--r-- | tools/aapt2/Resource.cpp | 18 | ||||
-rw-r--r-- | tools/aapt2/Resource.h | 128 | ||||
-rw-r--r-- | tools/aapt2/Resource_test.cpp | 103 |
3 files changed, 245 insertions, 4 deletions
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp index 6364ccdd09e5..0bb330e26e6f 100644 --- a/tools/aapt2/Resource.cpp +++ b/tools/aapt2/Resource.cpp @@ -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)) { diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h index 307c21d9dc96..d394b24d9947 100644 --- a/tools/aapt2/Resource.h +++ b/tools/aapt2/Resource.h @@ -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, @@ -78,6 +77,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. */ @@ -295,6 +340,81 @@ inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& 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. // diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp index c557f3c77654..2c55d1d548db 100644 --- a/tools/aapt2/Resource_test.cpp +++ b/tools/aapt2/Resource_test.cpp @@ -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 |