Loading tools/aapt2/link/ManifestFixer.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -127,9 +127,9 @@ static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) { diag->Error(DiagMessage(el->line_number) diag->Error(DiagMessage(el->line_number) << "attribute 'package' in <manifest> tag must not be a reference"); << "attribute 'package' in <manifest> tag must not be a reference"); return false; return false; } else if (!util::IsJavaPackageName(attr->value)) { } else if (!util::IsAndroidPackageName(attr->value)) { diag->Error(DiagMessage(el->line_number) diag->Error(DiagMessage(el->line_number) << "attribute 'package' in <manifest> tag is not a valid Java package name: '" << "attribute 'package' in <manifest> tag is not a valid Android package name: '" << attr->value << "'"); << attr->value << "'"); return false; return false; } } Loading tools/aapt2/text/Unicode.cpp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -85,7 +85,8 @@ bool IsJavaIdentifier(const StringPiece& str) { return false; return false; } } if (!IsXidStart(iter.Next())) { const char32_t first_codepoint = iter.Next(); if (!IsXidStart(first_codepoint) && first_codepoint != U'_' && first_codepoint != U'$') { return false; return false; } } Loading tools/aapt2/text/Unicode_test.cpp +3 −2 Original line number Original line Diff line number Diff line Loading @@ -44,10 +44,11 @@ TEST(UnicodeTest, IsXidContinue) { TEST(UnicodeTest, IsJavaIdentifier) { TEST(UnicodeTest, IsJavaIdentifier) { EXPECT_TRUE(IsJavaIdentifier("FøøBar_12")); EXPECT_TRUE(IsJavaIdentifier("FøøBar_12")); EXPECT_TRUE(IsJavaIdentifier("Føø$Bar")); EXPECT_TRUE(IsJavaIdentifier("Føø$Bar")); EXPECT_TRUE(IsJavaIdentifier("_FøøBar")); EXPECT_TRUE(IsJavaIdentifier("$Føø$Bar")); EXPECT_FALSE(IsJavaIdentifier("12FøøBar")); EXPECT_FALSE(IsJavaIdentifier("12FøøBar")); EXPECT_FALSE(IsJavaIdentifier("_FøøBar")); EXPECT_FALSE(IsJavaIdentifier(".Hello")); EXPECT_FALSE(IsJavaIdentifier("$Føø$Bar")); } } TEST(UnicodeTest, IsValidResourceEntryName) { TEST(UnicodeTest, IsValidResourceEntryName) { Loading tools/aapt2/util/Util.cpp +34 −50 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "androidfw/StringPiece.h" #include "androidfw/StringPiece.h" #include "utils/Unicode.h" #include "utils/Unicode.h" #include "text/Unicode.h" #include "text/Utf8Iterator.h" #include "text/Utf8Iterator.h" #include "util/BigBuffer.h" #include "util/BigBuffer.h" #include "util/Maybe.h" #include "util/Maybe.h" Loading Loading @@ -94,72 +95,55 @@ StringPiece TrimWhitespace(const StringPiece& str) { return StringPiece(start, end - start); return StringPiece(start, end - start); } } StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( static int IsJavaNameImpl(const StringPiece& str) { const StringPiece& str, const StringPiece& allowed_chars) { int pieces = 0; const auto end_iter = str.end(); for (const StringPiece& piece : Tokenize(str, '.')) { for (auto iter = str.begin(); iter != end_iter; ++iter) { pieces++; char c = *iter; if (!text::IsJavaIdentifier(piece)) { if ((c >= u'a' && c <= u'z') || (c >= u'A' && c <= u'Z') || return -1; (c >= u'0' && c <= u'9')) { continue; } } bool match = false; for (char i : allowed_chars) { if (c == i) { match = true; break; } } return pieces; } } if (!match) { bool IsJavaClassName(const StringPiece& str) { return iter; return IsJavaNameImpl(str) >= 2; } } } return end_iter; bool IsJavaPackageName(const StringPiece& str) { return IsJavaNameImpl(str) >= 1; } } bool IsJavaClassName(const StringPiece& str) { static int IsAndroidNameImpl(const StringPiece& str) { size_t pieces = 0; int pieces = 0; for (const StringPiece& piece : Tokenize(str, '.')) { for (const StringPiece& piece : Tokenize(str, '.')) { pieces++; if (piece.empty()) { if (piece.empty()) { return false; return -1; } } // Can't have starting or trailing $ character. const char first_character = piece.data()[0]; if (piece.data()[0] == '$' || piece.data()[piece.size() - 1] == '$') { if (!::isalpha(first_character)) { return false; return -1; } } if (FindNonAlphaNumericAndNotInSet(piece, "$_") != piece.end()) { bool valid = std::all_of(piece.begin() + 1, piece.end(), [](const char c) -> bool { return false; return ::isalnum(c) || c == '_'; } }); } return pieces >= 2; } bool IsJavaPackageName(const StringPiece& str) { if (!valid) { if (str.empty()) { return -1; return false; } } size_t pieces = 0; for (const StringPiece& piece : Tokenize(str, '.')) { pieces++; pieces++; if (piece.empty()) { return false; } } return pieces; if (piece.data()[0] == '_' || piece.data()[piece.size() - 1] == '_') { return false; } } if (FindNonAlphaNumericAndNotInSet(piece, "_") != piece.end()) { bool IsAndroidPackageName(const StringPiece& str) { return false; return IsAndroidNameImpl(str) > 1 || str == "android"; } } } return pieces >= 1; bool IsAndroidSplitName(const StringPiece& str) { return IsAndroidNameImpl(str) > 0; } } Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, Loading @@ -176,7 +160,7 @@ Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, return {}; return {}; } } std::string result(package.data(), package.size()); std::string result = package.to_string(); if (classname.data()[0] != '.') { if (classname.data()[0] != '.') { result += '.'; result += '.'; } } Loading tools/aapt2/util/Util.h +84 −105 Original line number Original line Diff line number Diff line Loading @@ -53,48 +53,40 @@ struct Range { std::vector<std::string> Split(const android::StringPiece& str, char sep); std::vector<std::string> Split(const android::StringPiece& str, char sep); std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); /** // Returns true if the string starts with prefix. * Returns true if the string starts with prefix. */ bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); /** // Returns true if the string ends with suffix. * Returns true if the string ends with suffix. */ bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); /** // Creates a new StringPiece16 that points to a substring of the original string without leading or * Creates a new StringPiece16 that points to a substring // trailing whitespace. * of the original string without leading or trailing whitespace. */ android::StringPiece TrimWhitespace(const android::StringPiece& str); android::StringPiece TrimWhitespace(const android::StringPiece& str); /** // Tests that the string is a valid Java class name. * Returns an iterator to the first character that is not alpha-numeric and that * is not in the allowedChars set. */ android::StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( const android::StringPiece& str, const android::StringPiece& allowed_chars); /** * Tests that the string is a valid Java class name. */ bool IsJavaClassName(const android::StringPiece& str); bool IsJavaClassName(const android::StringPiece& str); /** // Tests that the string is a valid Java package name. * Tests that the string is a valid Java package name. */ bool IsJavaPackageName(const android::StringPiece& str); bool IsJavaPackageName(const android::StringPiece& str); /** // Tests that the string is a valid Android package name. More strict than a Java package name. * Converts the class name to a fully qualified class name from the given // - First character of each component (separated by '.') must be an ASCII letter. * `package`. Ex: // - Subsequent characters of a component can be ASCII alphanumeric or an underscore. * // - Package must contain at least two components, unless it is 'android'. * asdf --> package.asdf bool IsAndroidPackageName(const android::StringPiece& str); * .asdf --> package.asdf * .a.b --> package.a.b // Tests that the string is a valid Android split name. * asdf.adsf --> asdf.adsf // - First character of each component (separated by '.') must be an ASCII letter. */ // - Subsequent characters of a component can be ASCII alphanumeric or an underscore. bool IsAndroidSplitName(const android::StringPiece& str); // Converts the class name to a fully qualified class name from the given // `package`. Ex: // // asdf --> package.asdf // .asdf --> package.asdf // .a.b --> package.a.b // asdf.adsf --> asdf.adsf Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, const android::StringPiece& class_name); const android::StringPiece& class_name); Loading @@ -108,23 +100,17 @@ typename std::enable_if<std::is_arithmetic<T>::value, int>::type compare(const T return 0; return 0; } } /** // Makes a std::unique_ptr<> with the template parameter inferred by the compiler. * Makes a std::unique_ptr<> with the template parameter inferred by the compiler. // This will be present in C++14 and can be removed then. * This will be present in C++14 and can be removed then. */ template <typename T, class... Args> template <typename T, class... Args> std::unique_ptr<T> make_unique(Args&&... args) { std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); } } /** // Writes a set of items to the std::ostream, joining the times with the provided separator. * Writes a set of items to the std::ostream, joining the times with the * provided * separator. */ template <typename Container> template <typename Container> ::std::function<::std::ostream&(::std::ostream&)> Joiner( ::std::function<::std::ostream&(::std::ostream&)> Joiner(const Container& container, const Container& container, const char* sep) { const char* sep) { using std::begin; using std::begin; using std::end; using std::end; const auto begin_iter = begin(container); const auto begin_iter = begin(container); Loading @@ -140,32 +126,19 @@ template <typename Container> }; }; } } /** // Helper method to extract a UTF-16 string from a StringPool. If the string is stored as UTF-8, * Helper method to extract a UTF-16 string from a StringPool. If the string is // the conversion to UTF-16 happens within ResStringPool. * stored as UTF-8, * the conversion to UTF-16 happens within ResStringPool. */ android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); /** // Helper method to extract a UTF-8 string from a StringPool. If the string is stored as UTF-16, * Helper method to extract a UTF-8 string from a StringPool. If the string is // the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is done by this method, * stored as UTF-16, // which maintains no state or cache. This means we must return an std::string copy. * the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is * done by this method, * which maintains no state or cache. This means we must return an std::string * copy. */ std::string GetString(const android::ResStringPool& pool, size_t idx); std::string GetString(const android::ResStringPool& pool, size_t idx); /** // Checks that the Java string format contains no non-positional arguments (arguments without * Checks that the Java string format contains no non-positional arguments // explicitly specifying an index) when there are more than one argument. This is an error * (arguments without // because translations may rearrange the order of the arguments in the string, which will * explicitly specifying an index) when there are more than one argument. This // break the string interpolation. * is an error * because translations may rearrange the order of the arguments in the string, * which will * break the string interpolation. */ bool VerifyJavaStringFormat(const android::StringPiece& str); bool VerifyJavaStringFormat(const android::StringPiece& str); class StringBuilder { class StringBuilder { Loading Loading @@ -194,36 +167,38 @@ class StringBuilder { std::string error_; std::string error_; }; }; inline const std::string& StringBuilder::ToString() const { return str_; } inline const std::string& StringBuilder::ToString() const { return str_; } inline const std::string& StringBuilder::Error() const { return error_; } inline const std::string& StringBuilder::Error() const { return error_; } inline bool StringBuilder::IsEmpty() const { return str_.empty(); } inline bool StringBuilder::IsEmpty() const { return str_.empty(); } inline size_t StringBuilder::Utf16Len() const { return utf16_len_; } inline size_t StringBuilder::Utf16Len() const { return utf16_len_; } inline StringBuilder::operator bool() const { return error_.empty(); } inline StringBuilder::operator bool() const { return error_.empty(); } /** // Converts a UTF8 string to a UTF16 string. * Converts a UTF8 string to a UTF16 string. */ std::u16string Utf8ToUtf16(const android::StringPiece& utf8); std::u16string Utf8ToUtf16(const android::StringPiece& utf8); std::string Utf16ToUtf8(const android::StringPiece16& utf16); std::string Utf16ToUtf8(const android::StringPiece16& utf16); /** // Writes the entire BigBuffer to the output stream. * Writes the entire BigBuffer to the output stream. */ bool WriteAll(std::ostream& out, const BigBuffer& buffer); bool WriteAll(std::ostream& out, const BigBuffer& buffer); /* // Copies the entire BigBuffer into a single buffer. * Copies the entire BigBuffer into a single buffer. */ std::unique_ptr<uint8_t[]> Copy(const BigBuffer& buffer); std::unique_ptr<uint8_t[]> Copy(const BigBuffer& buffer); /** // A Tokenizer implemented as an iterable collection. It does not allocate any memory on the heap * A Tokenizer implemented as an iterable collection. It does not allocate // nor use standard containers. * any memory on the heap nor use standard containers. */ class Tokenizer { class Tokenizer { public: public: class iterator { class iterator { Loading Loading @@ -269,37 +244,41 @@ class Tokenizer { const iterator end_; const iterator end_; }; }; inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } inline uint32_t HostToDevice32(uint32_t value) { return htodl(value); } inline uint32_t HostToDevice32(uint32_t value) { return htodl(value); } inline uint16_t DeviceToHost16(uint16_t value) { return dtohs(value); } inline uint16_t DeviceToHost16(uint16_t value) { return dtohs(value); } inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } /** // Given a path like: res/xml-sw600dp/foo.xml * Given a path like: res/xml-sw600dp/foo.xml // * // Extracts "res/xml-sw600dp/" into outPrefix. * Extracts "res/xml-sw600dp/" into outPrefix. // Extracts "foo" into outEntry. * Extracts "foo" into outEntry. // Extracts ".xml" into outSuffix. * Extracts ".xml" into outSuffix. // * // Returns true if successful. * Returns true if successful. */ bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, android::StringPiece* out_entry, android::StringPiece* out_suffix); android::StringPiece* out_entry, android::StringPiece* out_suffix); } // namespace util } // namespace util /** // Stream operator for functions. Calls the function with the stream as an argument. * Stream operator for functions. Calls the function with the stream as an // In the aapt namespace for lookup. * argument. inline ::std::ostream& operator<<(::std::ostream& out, * In the aapt namespace for lookup. */ inline ::std::ostream& operator<<( ::std::ostream& out, const ::std::function<::std::ostream&(::std::ostream&)>& f) { const ::std::function<::std::ostream&(::std::ostream&)>& f) { return f(out); return f(out); } } Loading Loading
tools/aapt2/link/ManifestFixer.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -127,9 +127,9 @@ static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) { diag->Error(DiagMessage(el->line_number) diag->Error(DiagMessage(el->line_number) << "attribute 'package' in <manifest> tag must not be a reference"); << "attribute 'package' in <manifest> tag must not be a reference"); return false; return false; } else if (!util::IsJavaPackageName(attr->value)) { } else if (!util::IsAndroidPackageName(attr->value)) { diag->Error(DiagMessage(el->line_number) diag->Error(DiagMessage(el->line_number) << "attribute 'package' in <manifest> tag is not a valid Java package name: '" << "attribute 'package' in <manifest> tag is not a valid Android package name: '" << attr->value << "'"); << attr->value << "'"); return false; return false; } } Loading
tools/aapt2/text/Unicode.cpp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -85,7 +85,8 @@ bool IsJavaIdentifier(const StringPiece& str) { return false; return false; } } if (!IsXidStart(iter.Next())) { const char32_t first_codepoint = iter.Next(); if (!IsXidStart(first_codepoint) && first_codepoint != U'_' && first_codepoint != U'$') { return false; return false; } } Loading
tools/aapt2/text/Unicode_test.cpp +3 −2 Original line number Original line Diff line number Diff line Loading @@ -44,10 +44,11 @@ TEST(UnicodeTest, IsXidContinue) { TEST(UnicodeTest, IsJavaIdentifier) { TEST(UnicodeTest, IsJavaIdentifier) { EXPECT_TRUE(IsJavaIdentifier("FøøBar_12")); EXPECT_TRUE(IsJavaIdentifier("FøøBar_12")); EXPECT_TRUE(IsJavaIdentifier("Føø$Bar")); EXPECT_TRUE(IsJavaIdentifier("Føø$Bar")); EXPECT_TRUE(IsJavaIdentifier("_FøøBar")); EXPECT_TRUE(IsJavaIdentifier("$Føø$Bar")); EXPECT_FALSE(IsJavaIdentifier("12FøøBar")); EXPECT_FALSE(IsJavaIdentifier("12FøøBar")); EXPECT_FALSE(IsJavaIdentifier("_FøøBar")); EXPECT_FALSE(IsJavaIdentifier(".Hello")); EXPECT_FALSE(IsJavaIdentifier("$Føø$Bar")); } } TEST(UnicodeTest, IsValidResourceEntryName) { TEST(UnicodeTest, IsValidResourceEntryName) { Loading
tools/aapt2/util/Util.cpp +34 −50 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "androidfw/StringPiece.h" #include "androidfw/StringPiece.h" #include "utils/Unicode.h" #include "utils/Unicode.h" #include "text/Unicode.h" #include "text/Utf8Iterator.h" #include "text/Utf8Iterator.h" #include "util/BigBuffer.h" #include "util/BigBuffer.h" #include "util/Maybe.h" #include "util/Maybe.h" Loading Loading @@ -94,72 +95,55 @@ StringPiece TrimWhitespace(const StringPiece& str) { return StringPiece(start, end - start); return StringPiece(start, end - start); } } StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( static int IsJavaNameImpl(const StringPiece& str) { const StringPiece& str, const StringPiece& allowed_chars) { int pieces = 0; const auto end_iter = str.end(); for (const StringPiece& piece : Tokenize(str, '.')) { for (auto iter = str.begin(); iter != end_iter; ++iter) { pieces++; char c = *iter; if (!text::IsJavaIdentifier(piece)) { if ((c >= u'a' && c <= u'z') || (c >= u'A' && c <= u'Z') || return -1; (c >= u'0' && c <= u'9')) { continue; } } bool match = false; for (char i : allowed_chars) { if (c == i) { match = true; break; } } return pieces; } } if (!match) { bool IsJavaClassName(const StringPiece& str) { return iter; return IsJavaNameImpl(str) >= 2; } } } return end_iter; bool IsJavaPackageName(const StringPiece& str) { return IsJavaNameImpl(str) >= 1; } } bool IsJavaClassName(const StringPiece& str) { static int IsAndroidNameImpl(const StringPiece& str) { size_t pieces = 0; int pieces = 0; for (const StringPiece& piece : Tokenize(str, '.')) { for (const StringPiece& piece : Tokenize(str, '.')) { pieces++; if (piece.empty()) { if (piece.empty()) { return false; return -1; } } // Can't have starting or trailing $ character. const char first_character = piece.data()[0]; if (piece.data()[0] == '$' || piece.data()[piece.size() - 1] == '$') { if (!::isalpha(first_character)) { return false; return -1; } } if (FindNonAlphaNumericAndNotInSet(piece, "$_") != piece.end()) { bool valid = std::all_of(piece.begin() + 1, piece.end(), [](const char c) -> bool { return false; return ::isalnum(c) || c == '_'; } }); } return pieces >= 2; } bool IsJavaPackageName(const StringPiece& str) { if (!valid) { if (str.empty()) { return -1; return false; } } size_t pieces = 0; for (const StringPiece& piece : Tokenize(str, '.')) { pieces++; pieces++; if (piece.empty()) { return false; } } return pieces; if (piece.data()[0] == '_' || piece.data()[piece.size() - 1] == '_') { return false; } } if (FindNonAlphaNumericAndNotInSet(piece, "_") != piece.end()) { bool IsAndroidPackageName(const StringPiece& str) { return false; return IsAndroidNameImpl(str) > 1 || str == "android"; } } } return pieces >= 1; bool IsAndroidSplitName(const StringPiece& str) { return IsAndroidNameImpl(str) > 0; } } Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, Loading @@ -176,7 +160,7 @@ Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, return {}; return {}; } } std::string result(package.data(), package.size()); std::string result = package.to_string(); if (classname.data()[0] != '.') { if (classname.data()[0] != '.') { result += '.'; result += '.'; } } Loading
tools/aapt2/util/Util.h +84 −105 Original line number Original line Diff line number Diff line Loading @@ -53,48 +53,40 @@ struct Range { std::vector<std::string> Split(const android::StringPiece& str, char sep); std::vector<std::string> Split(const android::StringPiece& str, char sep); std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); /** // Returns true if the string starts with prefix. * Returns true if the string starts with prefix. */ bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); /** // Returns true if the string ends with suffix. * Returns true if the string ends with suffix. */ bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); /** // Creates a new StringPiece16 that points to a substring of the original string without leading or * Creates a new StringPiece16 that points to a substring // trailing whitespace. * of the original string without leading or trailing whitespace. */ android::StringPiece TrimWhitespace(const android::StringPiece& str); android::StringPiece TrimWhitespace(const android::StringPiece& str); /** // Tests that the string is a valid Java class name. * Returns an iterator to the first character that is not alpha-numeric and that * is not in the allowedChars set. */ android::StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( const android::StringPiece& str, const android::StringPiece& allowed_chars); /** * Tests that the string is a valid Java class name. */ bool IsJavaClassName(const android::StringPiece& str); bool IsJavaClassName(const android::StringPiece& str); /** // Tests that the string is a valid Java package name. * Tests that the string is a valid Java package name. */ bool IsJavaPackageName(const android::StringPiece& str); bool IsJavaPackageName(const android::StringPiece& str); /** // Tests that the string is a valid Android package name. More strict than a Java package name. * Converts the class name to a fully qualified class name from the given // - First character of each component (separated by '.') must be an ASCII letter. * `package`. Ex: // - Subsequent characters of a component can be ASCII alphanumeric or an underscore. * // - Package must contain at least two components, unless it is 'android'. * asdf --> package.asdf bool IsAndroidPackageName(const android::StringPiece& str); * .asdf --> package.asdf * .a.b --> package.a.b // Tests that the string is a valid Android split name. * asdf.adsf --> asdf.adsf // - First character of each component (separated by '.') must be an ASCII letter. */ // - Subsequent characters of a component can be ASCII alphanumeric or an underscore. bool IsAndroidSplitName(const android::StringPiece& str); // Converts the class name to a fully qualified class name from the given // `package`. Ex: // // asdf --> package.asdf // .asdf --> package.asdf // .a.b --> package.a.b // asdf.adsf --> asdf.adsf Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, const android::StringPiece& class_name); const android::StringPiece& class_name); Loading @@ -108,23 +100,17 @@ typename std::enable_if<std::is_arithmetic<T>::value, int>::type compare(const T return 0; return 0; } } /** // Makes a std::unique_ptr<> with the template parameter inferred by the compiler. * Makes a std::unique_ptr<> with the template parameter inferred by the compiler. // This will be present in C++14 and can be removed then. * This will be present in C++14 and can be removed then. */ template <typename T, class... Args> template <typename T, class... Args> std::unique_ptr<T> make_unique(Args&&... args) { std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); } } /** // Writes a set of items to the std::ostream, joining the times with the provided separator. * Writes a set of items to the std::ostream, joining the times with the * provided * separator. */ template <typename Container> template <typename Container> ::std::function<::std::ostream&(::std::ostream&)> Joiner( ::std::function<::std::ostream&(::std::ostream&)> Joiner(const Container& container, const Container& container, const char* sep) { const char* sep) { using std::begin; using std::begin; using std::end; using std::end; const auto begin_iter = begin(container); const auto begin_iter = begin(container); Loading @@ -140,32 +126,19 @@ template <typename Container> }; }; } } /** // Helper method to extract a UTF-16 string from a StringPool. If the string is stored as UTF-8, * Helper method to extract a UTF-16 string from a StringPool. If the string is // the conversion to UTF-16 happens within ResStringPool. * stored as UTF-8, * the conversion to UTF-16 happens within ResStringPool. */ android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); /** // Helper method to extract a UTF-8 string from a StringPool. If the string is stored as UTF-16, * Helper method to extract a UTF-8 string from a StringPool. If the string is // the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is done by this method, * stored as UTF-16, // which maintains no state or cache. This means we must return an std::string copy. * the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is * done by this method, * which maintains no state or cache. This means we must return an std::string * copy. */ std::string GetString(const android::ResStringPool& pool, size_t idx); std::string GetString(const android::ResStringPool& pool, size_t idx); /** // Checks that the Java string format contains no non-positional arguments (arguments without * Checks that the Java string format contains no non-positional arguments // explicitly specifying an index) when there are more than one argument. This is an error * (arguments without // because translations may rearrange the order of the arguments in the string, which will * explicitly specifying an index) when there are more than one argument. This // break the string interpolation. * is an error * because translations may rearrange the order of the arguments in the string, * which will * break the string interpolation. */ bool VerifyJavaStringFormat(const android::StringPiece& str); bool VerifyJavaStringFormat(const android::StringPiece& str); class StringBuilder { class StringBuilder { Loading Loading @@ -194,36 +167,38 @@ class StringBuilder { std::string error_; std::string error_; }; }; inline const std::string& StringBuilder::ToString() const { return str_; } inline const std::string& StringBuilder::ToString() const { return str_; } inline const std::string& StringBuilder::Error() const { return error_; } inline const std::string& StringBuilder::Error() const { return error_; } inline bool StringBuilder::IsEmpty() const { return str_.empty(); } inline bool StringBuilder::IsEmpty() const { return str_.empty(); } inline size_t StringBuilder::Utf16Len() const { return utf16_len_; } inline size_t StringBuilder::Utf16Len() const { return utf16_len_; } inline StringBuilder::operator bool() const { return error_.empty(); } inline StringBuilder::operator bool() const { return error_.empty(); } /** // Converts a UTF8 string to a UTF16 string. * Converts a UTF8 string to a UTF16 string. */ std::u16string Utf8ToUtf16(const android::StringPiece& utf8); std::u16string Utf8ToUtf16(const android::StringPiece& utf8); std::string Utf16ToUtf8(const android::StringPiece16& utf16); std::string Utf16ToUtf8(const android::StringPiece16& utf16); /** // Writes the entire BigBuffer to the output stream. * Writes the entire BigBuffer to the output stream. */ bool WriteAll(std::ostream& out, const BigBuffer& buffer); bool WriteAll(std::ostream& out, const BigBuffer& buffer); /* // Copies the entire BigBuffer into a single buffer. * Copies the entire BigBuffer into a single buffer. */ std::unique_ptr<uint8_t[]> Copy(const BigBuffer& buffer); std::unique_ptr<uint8_t[]> Copy(const BigBuffer& buffer); /** // A Tokenizer implemented as an iterable collection. It does not allocate any memory on the heap * A Tokenizer implemented as an iterable collection. It does not allocate // nor use standard containers. * any memory on the heap nor use standard containers. */ class Tokenizer { class Tokenizer { public: public: class iterator { class iterator { Loading Loading @@ -269,37 +244,41 @@ class Tokenizer { const iterator end_; const iterator end_; }; }; inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } inline uint32_t HostToDevice32(uint32_t value) { return htodl(value); } inline uint32_t HostToDevice32(uint32_t value) { return htodl(value); } inline uint16_t DeviceToHost16(uint16_t value) { return dtohs(value); } inline uint16_t DeviceToHost16(uint16_t value) { return dtohs(value); } inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } /** // Given a path like: res/xml-sw600dp/foo.xml * Given a path like: res/xml-sw600dp/foo.xml // * // Extracts "res/xml-sw600dp/" into outPrefix. * Extracts "res/xml-sw600dp/" into outPrefix. // Extracts "foo" into outEntry. * Extracts "foo" into outEntry. // Extracts ".xml" into outSuffix. * Extracts ".xml" into outSuffix. // * // Returns true if successful. * Returns true if successful. */ bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, android::StringPiece* out_entry, android::StringPiece* out_suffix); android::StringPiece* out_entry, android::StringPiece* out_suffix); } // namespace util } // namespace util /** // Stream operator for functions. Calls the function with the stream as an argument. * Stream operator for functions. Calls the function with the stream as an // In the aapt namespace for lookup. * argument. inline ::std::ostream& operator<<(::std::ostream& out, * In the aapt namespace for lookup. */ inline ::std::ostream& operator<<( ::std::ostream& out, const ::std::function<::std::ostream&(::std::ostream&)>& f) { const ::std::function<::std::ostream&(::std::ostream&)>& f) { return f(out); return f(out); } } Loading