diff options
Diffstat (limited to 'tools/aapt2/ResourceUtils.cpp')
-rw-r--r-- | tools/aapt2/ResourceUtils.cpp | 170 |
1 files changed, 104 insertions, 66 deletions
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 302c04fc3780..31d6435a6184 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -27,19 +27,52 @@ namespace aapt { namespace ResourceUtils { -bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, - StringPiece16* outType, StringPiece16* outEntry) { +Maybe<ResourceName> toResourceName(const android::ResTable::resource_name& nameIn) { + ResourceName nameOut; + if (!nameIn.package) { + return {}; + } + + nameOut.package = util::utf16ToUtf8(StringPiece16(nameIn.package, nameIn.packageLen)); + + const ResourceType* type; + if (nameIn.type) { + type = parseResourceType(util::utf16ToUtf8(StringPiece16(nameIn.type, nameIn.typeLen))); + } else if (nameIn.type8) { + type = parseResourceType(StringPiece(nameIn.type8, nameIn.typeLen)); + } else { + return {}; + } + + if (!type) { + return {}; + } + + nameOut.type = *type; + + if (nameIn.name) { + nameOut.entry = util::utf16ToUtf8(StringPiece16(nameIn.name, nameIn.nameLen)); + } else if (nameIn.name8) { + nameOut.entry = StringPiece(nameIn.name8, nameIn.nameLen).toString(); + } else { + return {}; + } + return nameOut; +} + +bool extractResourceName(const StringPiece& str, StringPiece* outPackage, + StringPiece* outType, StringPiece* 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; + const char* start = str.data(); + const char* end = start + str.size(); + const char* current = start; while (current != end) { - if (outType->size() == 0 && *current == u'/') { + if (outType->size() == 0 && *current == '/') { hasTypeSeparator = true; outType->assign(start, current - start); start = current + 1; - } else if (outPackage->size() == 0 && *current == u':') { + } else if (outPackage->size() == 0 && *current == ':') { hasPackageSeparator = true; outPackage->assign(start, current - start); start = current + 1; @@ -51,21 +84,21 @@ bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage, return !(hasPackageSeparator && outPackage->empty()) && !(hasTypeSeparator && outType->empty()); } -bool parseResourceName(const StringPiece16& str, ResourceNameRef* outRef, bool* outPrivate) { +bool parseResourceName(const StringPiece& str, ResourceNameRef* outRef, bool* outPrivate) { if (str.empty()) { return false; } size_t offset = 0; bool priv = false; - if (str.data()[0] == u'*') { + if (str.data()[0] == '*') { priv = true; offset = 1; } - StringPiece16 package; - StringPiece16 type; - StringPiece16 entry; + StringPiece package; + StringPiece type; + StringPiece entry; if (!extractResourceName(str.substr(offset, str.size() - offset), &package, &type, &entry)) { return false; } @@ -91,18 +124,18 @@ bool parseResourceName(const StringPiece16& str, ResourceNameRef* outRef, bool* return true; } -bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* outCreate, +bool tryParseReference(const StringPiece& str, ResourceNameRef* outRef, bool* outCreate, bool* outPrivate) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); + StringPiece trimmedStr(util::trimWhitespace(str)); if (trimmedStr.empty()) { return false; } bool create = false; bool priv = false; - if (trimmedStr.data()[0] == u'@') { + if (trimmedStr.data()[0] == '@') { size_t offset = 1; - if (trimmedStr.data()[1] == u'+') { + if (trimmedStr.data()[1] == '+') { create = true; offset += 1; } @@ -137,26 +170,26 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* return false; } -bool isReference(const StringPiece16& str) { +bool isReference(const StringPiece& str) { return tryParseReference(str, nullptr, nullptr, nullptr); } -bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRef) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); +bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outRef) { + StringPiece trimmedStr(util::trimWhitespace(str)); if (trimmedStr.empty()) { return false; } - if (*trimmedStr.data() == u'?') { - StringPiece16 package; - StringPiece16 type; - StringPiece16 entry; + if (*trimmedStr.data() == '?') { + StringPiece package; + StringPiece type; + StringPiece entry; if (!extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry)) { return false; } - if (!type.empty() && type != u"attr") { + if (!type.empty() && type != "attr") { return false; } @@ -174,7 +207,7 @@ bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRe return false; } -bool isAttributeReference(const StringPiece16& str) { +bool isAttributeReference(const StringPiece& str) { return tryParseAttributeReference(str, nullptr); } @@ -186,23 +219,23 @@ bool isAttributeReference(const StringPiece16& str) { * <[*]package>:[style/]<entry> * [[*]package:style/]<entry> */ -Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string* outError) { +Maybe<Reference> parseStyleParentReference(const StringPiece& str, std::string* outError) { if (str.empty()) { return {}; } - StringPiece16 name = str; + StringPiece name = str; bool hasLeadingIdentifiers = false; bool privateRef = false; // Skip over these identifiers. A style's parent is a normal reference. - if (name.data()[0] == u'@' || name.data()[0] == u'?') { + if (name.data()[0] == '@' || name.data()[0] == '?') { hasLeadingIdentifiers = true; name = name.substr(1, name.size() - 1); } - if (name.data()[0] == u'*') { + if (name.data()[0] == '*') { privateRef = true; name = name.substr(1, name.size() - 1); } @@ -210,7 +243,7 @@ Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string ResourceNameRef ref; ref.type = ResourceType::kStyle; - StringPiece16 typeStr; + StringPiece typeStr; extractResourceName(name, &ref.package, &typeStr, &ref.entry); if (!typeStr.empty()) { // If we have a type, make sure it is a Style. @@ -235,7 +268,7 @@ Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string return result; } -std::unique_ptr<Reference> tryParseReference(const StringPiece16& str, bool* outCreate) { +std::unique_ptr<Reference> tryParseReference(const StringPiece& str, bool* outCreate) { ResourceNameRef ref; bool privateRef = false; if (tryParseReference(str, &ref, outCreate, &privateRef)) { @@ -253,14 +286,14 @@ std::unique_ptr<Reference> tryParseReference(const StringPiece16& str, bool* out return {}; } -std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece16& str) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); +std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece& str) { + StringPiece trimmedStr(util::trimWhitespace(str)); android::Res_value value = { }; - if (trimmedStr == u"@null") { + if (trimmedStr == "@null") { // TYPE_NULL with data set to 0 is interpreted by the runtime as an error. // Instead we set the data type to TYPE_REFERENCE with a value of 0. value.dataType = android::Res_value::TYPE_REFERENCE; - } else if (trimmedStr == u"@empty") { + } else if (trimmedStr == "@empty") { // TYPE_NULL with value of DATA_NULL_EMPTY is handled fine by the runtime. value.dataType = android::Res_value::TYPE_NULL; value.data = android::Res_value::DATA_NULL_EMPTY; @@ -271,8 +304,8 @@ std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece16& str) { } std::unique_ptr<BinaryPrimitive> tryParseEnumSymbol(const Attribute* enumAttr, - const StringPiece16& str) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); + const StringPiece& str) { + StringPiece trimmedStr(util::trimWhitespace(str)); for (const Attribute::Symbol& symbol : enumAttr->symbols) { // Enum symbols are stored as @package:id/symbol resources, // so we need to match against the 'entry' part of the identifier. @@ -288,7 +321,7 @@ std::unique_ptr<BinaryPrimitive> tryParseEnumSymbol(const Attribute* enumAttr, } std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* flagAttr, - const StringPiece16& str) { + const StringPiece& str) { android::Res_value flags = { }; flags.dataType = android::Res_value::TYPE_INT_HEX; flags.data = 0u; @@ -298,8 +331,8 @@ std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* flagAttr, return util::make_unique<BinaryPrimitive>(flags); } - for (StringPiece16 part : util::tokenize(str, u'|')) { - StringPiece16 trimmedPart = util::trimWhitespace(part); + for (StringPiece part : util::tokenize(str, '|')) { + StringPiece trimmedPart = util::trimWhitespace(part); bool flagSet = false; for (const Attribute::Symbol& symbol : flagAttr->symbols) { @@ -320,24 +353,24 @@ std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* flagAttr, return util::make_unique<BinaryPrimitive>(flags); } -static uint32_t parseHex(char16_t c, bool* outError) { - if (c >= u'0' && c <= u'9') { - return c - u'0'; - } else if (c >= u'a' && c <= u'f') { - return c - u'a' + 0xa; - } else if (c >= u'A' && c <= u'F') { - return c - u'A' + 0xa; +static uint32_t parseHex(char c, bool* outError) { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 0xa; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 0xa; } else { *outError = true; return 0xffffffffu; } } -std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str) { - StringPiece16 colorStr(util::trimWhitespace(str)); - const char16_t* start = colorStr.data(); +std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece& str) { + StringPiece colorStr(util::trimWhitespace(str)); + const char* start = colorStr.data(); const size_t len = colorStr.size(); - if (len == 0 || start[0] != u'#') { + if (len == 0 || start[0] != '#') { return {}; } @@ -387,14 +420,14 @@ std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str) { return error ? std::unique_ptr<BinaryPrimitive>() : util::make_unique<BinaryPrimitive>(value); } -bool tryParseBool(const StringPiece16& str, bool* outValue) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); - if (trimmedStr == u"true" || trimmedStr == u"TRUE" || trimmedStr == u"True") { +bool tryParseBool(const StringPiece& str, bool* outValue) { + StringPiece trimmedStr(util::trimWhitespace(str)); + if (trimmedStr == "true" || trimmedStr == "TRUE" || trimmedStr == "True") { if (outValue) { *outValue = true; } return true; - } else if (trimmedStr == u"false" || trimmedStr == u"FALSE" || trimmedStr == u"False") { + } else if (trimmedStr == "false" || trimmedStr == "FALSE" || trimmedStr == "False") { if (outValue) { *outValue = false; } @@ -403,22 +436,24 @@ bool tryParseBool(const StringPiece16& str, bool* outValue) { return false; } -Maybe<int> tryParseSdkVersion(const StringPiece16& str) { - StringPiece16 trimmedStr(util::trimWhitespace(str)); +Maybe<int> tryParseSdkVersion(const StringPiece& str) { + StringPiece trimmedStr(util::trimWhitespace(str)); + + std::u16string str16 = util::utf8ToUtf16(trimmedStr); android::Res_value value; - if (android::ResTable::stringToInt(trimmedStr.data(), trimmedStr.size(), &value)) { + if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) { return static_cast<int>(value.data); } // Try parsing the code name. - std::pair<StringPiece16, int> entry = getDevelopmentSdkCodeNameAndVersion(); + std::pair<StringPiece, int> entry = getDevelopmentSdkCodeNameAndVersion(); if (entry.first == trimmedStr) { return entry.second; } return {}; } -std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str) { +std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece& str) { bool result = false; if (tryParseBool(str, &result)) { android::Res_value value = {}; @@ -434,17 +469,19 @@ std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str) { return {}; } -std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece16& str) { +std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece& str) { + std::u16string str16 = util::utf8ToUtf16(str); android::Res_value value; - if (!android::ResTable::stringToInt(str.data(), str.size(), &value)) { + if (!android::ResTable::stringToInt(str16.data(), str16.size(), &value)) { return {}; } return util::make_unique<BinaryPrimitive>(value); } -std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece16& str) { +std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece& str) { + std::u16string str16 = util::utf8ToUtf16(str); android::Res_value value; - if (!android::ResTable::stringToFloat(str.data(), str.size(), &value)) { + if (!android::ResTable::stringToFloat(str16.data(), str16.size(), &value)) { return {}; } return util::make_unique<BinaryPrimitive>(value); @@ -490,7 +527,8 @@ uint32_t androidTypeToAttributeTypeMask(uint16_t type) { } std::unique_ptr<Item> parseItemForAttribute( - const StringPiece16& value, uint32_t typeMask, + const StringPiece& value, + uint32_t typeMask, std::function<void(const ResourceName&)> onCreateReference) { std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value); if (nullOrEmpty) { @@ -549,7 +587,7 @@ std::unique_ptr<Item> parseItemForAttribute( * allows. */ std::unique_ptr<Item> parseItemForAttribute( - const StringPiece16& str, const Attribute* attr, + const StringPiece& str, const Attribute* attr, std::function<void(const ResourceName&)> onCreateReference) { const uint32_t typeMask = attr->typeMask; std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference); |