Loading tools/aapt2/ResourceUtils.cpp +35 −8 Original line number Diff line number Diff line Loading @@ -23,22 +23,28 @@ namespace aapt { namespace ResourceUtils { void extractResourceName(const StringPiece16& str, StringPiece16* outPackage, bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, StringPiece16* outType, StringPiece16* outEntry) { bool hasPackageSeparator = false; bool hasTypeSeparator = false; const char16_t* start = str.data(); const char16_t* end = start + str.size(); const char16_t* current = start; while (current != end) { if (outType->size() == 0 && *current == u'/') { hasTypeSeparator = true; outType->assign(start, current - start); start = current + 1; } else if (outPackage->size() == 0 && *current == u':') { hasPackageSeparator = true; outPackage->assign(start, current - start); start = current + 1; } current++; } outEntry->assign(start, end - start); return !(hasPackageSeparator && outPackage->empty()) && !(hasTypeSeparator && outType->empty()); } bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* outCreate, Loading @@ -62,26 +68,34 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* StringPiece16 package; StringPiece16 type; StringPiece16 entry; extractResourceName(trimmedStr.substr(offset, trimmedStr.size() - offset), &package, &type, &entry); if (!extractResourceName(trimmedStr.substr(offset, trimmedStr.size() - offset), &package, &type, &entry)) { return false; } const ResourceType* parsedType = parseResourceType(type); if (!parsedType) { return false; } if (entry.empty()) { return false; } if (create && *parsedType != ResourceType::kId) { return false; } if (outRef != nullptr) { if (outRef) { outRef->package = package; outRef->type = *parsedType; outRef->entry = entry; } if (outCreate) { *outCreate = create; } if (outPrivate) { *outPrivate = priv; } Loading @@ -104,20 +118,33 @@ bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRe StringPiece16 package; StringPiece16 type; StringPiece16 entry; extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry); if (!extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry)) { return false; } if (!type.empty() && type != u"attr") { return false; } if (entry.empty()) { return false; } if (outRef) { outRef->package = package; outRef->type = ResourceType::kAttr; outRef->entry = entry; } return true; } return false; } bool isAttributeReference(const StringPiece16& str) { return tryParseAttributeReference(str, nullptr); } /* * Style parent's are a bit different. We accept the following formats: * Loading tools/aapt2/ResourceUtils.h +8 −2 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ namespace ResourceUtils { * * where the package can be empty. Validation must be performed on each * individual extracted piece to verify that the pieces are valid. * Returns false if there was no package but a ':' was present. */ void extractResourceName(const StringPiece16& str, StringPiece16* outPackage, bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, StringPiece16* outType, StringPiece16* outEntry); /* Loading @@ -54,11 +55,16 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outReference, bool isReference(const StringPiece16& str); /* * Returns true if the string was parsed as an attribute reference (?[package:]type/name), * Returns true if the string was parsed as an attribute reference (?[package:][type/]name), * with `outReference` set to the parsed reference. */ bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outReference); /** * Returns true if the string is in the form of an attribute reference(?[package:][type/]name). */ bool isAttributeReference(const StringPiece16& str); /** * Returns true if the value is a boolean, putting the result in `outValue`. */ Loading tools/aapt2/ResourceUtils_test.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,26 @@ TEST(ResourceUtilsTest, FailToParseAutoCreateNonIdReference) { &privateRef)); } TEST(ResourceUtilsTest, ParseAttributeReferences) { EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:foo")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?attr/foo")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:attr/foo")); } TEST(ResourceUtilsTest, FailParseIncompleteReference) { EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?style/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:style/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?/foo")); } TEST(ResourceUtilsTest, ParseStyleParentReference) { const ResourceName kAndroidStyleFooName = { u"android", ResourceType::kStyle, u"foo" }; const ResourceName kStyleFooName = { {}, ResourceType::kStyle, u"foo" }; Loading Loading
tools/aapt2/ResourceUtils.cpp +35 −8 Original line number Diff line number Diff line Loading @@ -23,22 +23,28 @@ namespace aapt { namespace ResourceUtils { void extractResourceName(const StringPiece16& str, StringPiece16* outPackage, bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, StringPiece16* outType, StringPiece16* outEntry) { bool hasPackageSeparator = false; bool hasTypeSeparator = false; const char16_t* start = str.data(); const char16_t* end = start + str.size(); const char16_t* current = start; while (current != end) { if (outType->size() == 0 && *current == u'/') { hasTypeSeparator = true; outType->assign(start, current - start); start = current + 1; } else if (outPackage->size() == 0 && *current == u':') { hasPackageSeparator = true; outPackage->assign(start, current - start); start = current + 1; } current++; } outEntry->assign(start, end - start); return !(hasPackageSeparator && outPackage->empty()) && !(hasTypeSeparator && outType->empty()); } bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* outCreate, Loading @@ -62,26 +68,34 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* StringPiece16 package; StringPiece16 type; StringPiece16 entry; extractResourceName(trimmedStr.substr(offset, trimmedStr.size() - offset), &package, &type, &entry); if (!extractResourceName(trimmedStr.substr(offset, trimmedStr.size() - offset), &package, &type, &entry)) { return false; } const ResourceType* parsedType = parseResourceType(type); if (!parsedType) { return false; } if (entry.empty()) { return false; } if (create && *parsedType != ResourceType::kId) { return false; } if (outRef != nullptr) { if (outRef) { outRef->package = package; outRef->type = *parsedType; outRef->entry = entry; } if (outCreate) { *outCreate = create; } if (outPrivate) { *outPrivate = priv; } Loading @@ -104,20 +118,33 @@ bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRe StringPiece16 package; StringPiece16 type; StringPiece16 entry; extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry); if (!extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry)) { return false; } if (!type.empty() && type != u"attr") { return false; } if (entry.empty()) { return false; } if (outRef) { outRef->package = package; outRef->type = ResourceType::kAttr; outRef->entry = entry; } return true; } return false; } bool isAttributeReference(const StringPiece16& str) { return tryParseAttributeReference(str, nullptr); } /* * Style parent's are a bit different. We accept the following formats: * Loading
tools/aapt2/ResourceUtils.h +8 −2 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ namespace ResourceUtils { * * where the package can be empty. Validation must be performed on each * individual extracted piece to verify that the pieces are valid. * Returns false if there was no package but a ':' was present. */ void extractResourceName(const StringPiece16& str, StringPiece16* outPackage, bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, StringPiece16* outType, StringPiece16* outEntry); /* Loading @@ -54,11 +55,16 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outReference, bool isReference(const StringPiece16& str); /* * Returns true if the string was parsed as an attribute reference (?[package:]type/name), * Returns true if the string was parsed as an attribute reference (?[package:][type/]name), * with `outReference` set to the parsed reference. */ bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outReference); /** * Returns true if the string is in the form of an attribute reference(?[package:][type/]name). */ bool isAttributeReference(const StringPiece16& str); /** * Returns true if the value is a boolean, putting the result in `outValue`. */ Loading
tools/aapt2/ResourceUtils_test.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,26 @@ TEST(ResourceUtilsTest, FailToParseAutoCreateNonIdReference) { &privateRef)); } TEST(ResourceUtilsTest, ParseAttributeReferences) { EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:foo")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?attr/foo")); EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:attr/foo")); } TEST(ResourceUtilsTest, FailParseIncompleteReference) { EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?style/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:style/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/foo")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?attr/")); EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?/foo")); } TEST(ResourceUtilsTest, ParseStyleParentReference) { const ResourceName kAndroidStyleFooName = { u"android", ResourceType::kStyle, u"foo" }; const ResourceName kStyleFooName = { {}, ResourceType::kStyle, u"foo" }; Loading