bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRef) { StringPiece16 trimmedStr(util::trimWhitespace(str)); if (trimmedStr.empty()) { return false; } if (*trimmedStr.data() == u'?') { StringPiece16 package; StringPiece16 type; StringPiece16 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; }
/* * Style parent's are a bit different. We accept the following formats: * * @[[*]package:][style/]<entry> * ?[[*]package:]style/<entry> * <[*]package>:[style/]<entry> * [[*]package:style/]<entry> */ Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string* outError) { if (str.empty()) { return {}; } StringPiece16 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'?') { hasLeadingIdentifiers = true; name = name.substr(1, name.size() - 1); } if (name.data()[0] == u'*') { privateRef = true; name = name.substr(1, name.size() - 1); } ResourceNameRef ref; ref.type = ResourceType::kStyle; StringPiece16 typeStr; extractResourceName(name, &ref.package, &typeStr, &ref.entry); if (!typeStr.empty()) { // If we have a type, make sure it is a Style. const ResourceType* parsedType = parseResourceType(typeStr); if (!parsedType || *parsedType != ResourceType::kStyle) { std::stringstream err; err << "invalid resource type '" << typeStr << "' for parent of style"; *outError = err.str(); return {}; } } if (!hasLeadingIdentifiers && ref.package.empty() && !typeStr.empty()) { std::stringstream err; err << "invalid parent reference '" << str << "'"; *outError = err.str(); return {}; } Reference result(ref); result.privateReference = privateRef; return result; }
bool parseResourceName(const StringPiece16& str, ResourceNameRef* outRef, bool* outPrivate) { if (str.empty()) { return false; } size_t offset = 0; bool priv = false; if (str.data()[0] == u'*') { priv = true; offset = 1; } StringPiece16 package; StringPiece16 type; StringPiece16 entry; if (!extractResourceName(str.substr(offset, str.size() - offset), &package, &type, &entry)) { return false; } const ResourceType* parsedType = parseResourceType(type); if (!parsedType) { return false; } if (entry.empty()) { return false; } if (outRef) { outRef->package = package; outRef->type = *parsedType; outRef->entry = entry; } if (outPrivate) { *outPrivate = priv; } return true; }
Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package, const StringPiece16& className) { if (className.empty()) { return {}; } if (util::isJavaClassName(className)) { return className.toString(); } if (package.empty()) { return {}; } std::u16string result(package.data(), package.size()); if (className.data()[0] != u'.') { result += u'.'; } result.append(className.data(), className.size()); if (!isJavaClassName(result)) { return {}; } return result; }