AAPT2: Remove usage of u16string
For legacy reasons, we kept around the use of UTF-16 internally
in AAPT2. We don't need this and this CL removes all instances of
std::u16string and StringPiece16. The only places still needed
are when interacting with the ResTable APIs that only operate in
UTF16.
Change-Id: I492475b84bb9014fa13bf992cff447ee7a5fe588
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index f5e49f1..c9b3811 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -157,7 +157,7 @@
std::string packageToPath(const StringPiece& package) {
std::string outPath;
- for (StringPiece part : util::tokenize<char>(package, '.')) {
+ for (StringPiece part : util::tokenize(package, '.')) {
appendPath(&outPath, part);
}
return outPath;
@@ -199,7 +199,7 @@
return false;
}
- for (StringPiece line : util::tokenize<char>(contents, ' ')) {
+ for (StringPiece line : util::tokenize(contents, ' ')) {
line = util::trimWhitespace(line);
if (!line.empty()) {
outArgList->push_back(line.toString());
diff --git a/tools/aapt2/util/StringPiece_test.cpp b/tools/aapt2/util/StringPiece_test.cpp
index 853a9a4..a87065a 100644
--- a/tools/aapt2/util/StringPiece_test.cpp
+++ b/tools/aapt2/util/StringPiece_test.cpp
@@ -34,16 +34,16 @@
}
TEST(StringPieceTest, PiecesHaveCorrectSortOrder) {
- std::u16string testing(u"testing");
- std::u16string banana(u"banana");
- std::u16string car(u"car");
+ std::string testing("testing");
+ std::string banana("banana");
+ std::string car("car");
- EXPECT_TRUE(StringPiece16(testing) > banana);
- EXPECT_TRUE(StringPiece16(testing) > car);
- EXPECT_TRUE(StringPiece16(banana) < testing);
- EXPECT_TRUE(StringPiece16(banana) < car);
- EXPECT_TRUE(StringPiece16(car) < testing);
- EXPECT_TRUE(StringPiece16(car) > banana);
+ EXPECT_TRUE(StringPiece(testing) > banana);
+ EXPECT_TRUE(StringPiece(testing) > car);
+ EXPECT_TRUE(StringPiece(banana) < testing);
+ EXPECT_TRUE(StringPiece(banana) < car);
+ EXPECT_TRUE(StringPiece(car) < testing);
+ EXPECT_TRUE(StringPiece(car) > banana);
}
TEST(StringPieceTest, PiecesHaveCorrectSortOrderUtf8) {
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index c41eb05..3c0e9bde 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -54,23 +54,18 @@
return splitAndTransform(str, sep, ::tolower);
}
-StringPiece16 trimWhitespace(const StringPiece16& str) {
- if (str.size() == 0 || str.data() == nullptr) {
- return str;
+bool stringStartsWith(const StringPiece& str, const StringPiece& prefix) {
+ if (str.size() < prefix.size()) {
+ return false;
}
+ return str.substr(0, prefix.size()) == prefix;
+}
- const char16_t* start = str.data();
- const char16_t* end = str.data() + str.length();
-
- while (start != end && util::isspace16(*start)) {
- start++;
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix) {
+ if (str.size() < suffix.size()) {
+ return false;
}
-
- while (end != start && util::isspace16(*(end - 1))) {
- end--;
- }
-
- return StringPiece16(start, end - start);
+ return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
}
StringPiece trimWhitespace(const StringPiece& str) {
@@ -92,11 +87,11 @@
return StringPiece(start, end - start);
}
-StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
- const StringPiece16& allowedChars) {
+StringPiece::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece& str,
+ const StringPiece& allowedChars) {
const auto endIter = str.end();
for (auto iter = str.begin(); iter != endIter; ++iter) {
- char16_t c = *iter;
+ char c = *iter;
if ((c >= u'a' && c <= u'z') ||
(c >= u'A' && c <= u'Z') ||
(c >= u'0' && c <= u'9')) {
@@ -104,7 +99,7 @@
}
bool match = false;
- for (char16_t i : allowedChars) {
+ for (char i : allowedChars) {
if (c == i) {
match = true;
break;
@@ -118,51 +113,51 @@
return endIter;
}
-bool isJavaClassName(const StringPiece16& str) {
+bool isJavaClassName(const StringPiece& str) {
size_t pieces = 0;
- for (const StringPiece16& piece : tokenize(str, u'.')) {
+ for (const StringPiece& piece : tokenize(str, '.')) {
pieces++;
if (piece.empty()) {
return false;
}
// Can't have starting or trailing $ character.
- if (piece.data()[0] == u'$' || piece.data()[piece.size() - 1] == u'$') {
+ if (piece.data()[0] == '$' || piece.data()[piece.size() - 1] == '$') {
return false;
}
- if (findNonAlphaNumericAndNotInSet(piece, u"$_") != piece.end()) {
+ if (findNonAlphaNumericAndNotInSet(piece, "$_") != piece.end()) {
return false;
}
}
return pieces >= 2;
}
-bool isJavaPackageName(const StringPiece16& str) {
+bool isJavaPackageName(const StringPiece& str) {
if (str.empty()) {
return false;
}
size_t pieces = 0;
- for (const StringPiece16& piece : tokenize(str, u'.')) {
+ for (const StringPiece& piece : tokenize(str, '.')) {
pieces++;
if (piece.empty()) {
return false;
}
- if (piece.data()[0] == u'_' || piece.data()[piece.size() - 1] == u'_') {
+ if (piece.data()[0] == '_' || piece.data()[piece.size() - 1] == '_') {
return false;
}
- if (findNonAlphaNumericAndNotInSet(piece, u"_") != piece.end()) {
+ if (findNonAlphaNumericAndNotInSet(piece, "_") != piece.end()) {
return false;
}
}
return pieces >= 1;
}
-Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
- const StringPiece16& className) {
+Maybe<std::string> getFullyQualifiedClassName(const StringPiece& package,
+ const StringPiece& className) {
if (className.empty()) {
return {};
}
@@ -175,9 +170,9 @@
return {};
}
- std::u16string result(package.data(), package.size());
- if (className.data()[0] != u'.') {
- result += u'.';
+ std::string result(package.data(), package.size());
+ if (className.data()[0] != '.') {
+ result += '.';
}
result.append(className.data(), className.size());
@@ -187,23 +182,23 @@
return result;
}
-static size_t consumeDigits(const char16_t* start, const char16_t* end) {
- const char16_t* c = start;
- for (; c != end && *c >= u'0' && *c <= u'9'; c++) {}
+static size_t consumeDigits(const char* start, const char* end) {
+ const char* c = start;
+ for (; c != end && *c >= '0' && *c <= '9'; c++) {}
return static_cast<size_t>(c - start);
}
-bool verifyJavaStringFormat(const StringPiece16& str) {
- const char16_t* c = str.begin();
- const char16_t* const end = str.end();
+bool verifyJavaStringFormat(const StringPiece& str) {
+ const char* c = str.begin();
+ const char* const end = str.end();
size_t argCount = 0;
bool nonpositional = false;
while (c != end) {
- if (*c == u'%' && c + 1 < end) {
+ if (*c == '%' && c + 1 < end) {
c++;
- if (*c == u'%') {
+ if (*c == '%') {
c++;
continue;
}
@@ -213,11 +208,11 @@
size_t numDigits = consumeDigits(c, end);
if (numDigits > 0) {
c += numDigits;
- if (c != end && *c != u'$') {
+ if (c != end && *c != '$') {
// The digits were a size, but not a positional argument.
nonpositional = true;
}
- } else if (*c == u'<') {
+ } else if (*c == '<') {
// Reusing last argument, bad idea since positions can be moved around
// during translation.
nonpositional = true;
@@ -225,7 +220,7 @@
c++;
// Optionally we can have a $ after
- if (c != end && *c == u'$') {
+ if (c != end && *c == '$') {
c++;
}
} else {
@@ -233,13 +228,13 @@
}
// Ignore size, width, flags, etc.
- while (c != end && (*c == u'-' ||
- *c == u'#' ||
- *c == u'+' ||
- *c == u' ' ||
- *c == u',' ||
- *c == u'(' ||
- (*c >= u'0' && *c <= '9'))) {
+ while (c != end && (*c == '-' ||
+ *c == '#' ||
+ *c == '+' ||
+ *c == ' ' ||
+ *c == ',' ||
+ *c == '(' ||
+ (*c >= '0' && *c <= '9'))) {
c++;
}
@@ -286,11 +281,11 @@
return true;
}
-static Maybe<char16_t> parseUnicodeCodepoint(const char16_t** start, const char16_t* end) {
- char16_t code = 0;
+static Maybe<std::string> parseUnicodeCodepoint(const char** start, const char* end) {
+ char32_t code = 0;
for (size_t i = 0; i < 4 && *start != end; i++, (*start)++) {
- char16_t c = **start;
- int a;
+ char c = **start;
+ char32_t a;
if (c >= '0' && c <= '9') {
a = c - '0';
} else if (c >= 'a' && c <= 'f') {
@@ -298,51 +293,60 @@
} else if (c >= 'A' && c <= 'F') {
a = c - 'A' + 10;
} else {
- return make_nothing<char16_t>();
+ return {};
}
code = (code << 4) | a;
}
- return make_value(code);
+
+ ssize_t len = utf32_to_utf8_length(&code, 1);
+ if (len < 0) {
+ return {};
+ }
+
+ std::string resultUtf8;
+ resultUtf8.resize(len);
+ utf32_to_utf8(&code, 1, &*resultUtf8.begin(), len + 1);
+ return resultUtf8;
}
-StringBuilder& StringBuilder::append(const StringPiece16& str) {
+StringBuilder& StringBuilder::append(const StringPiece& str) {
if (!mError.empty()) {
return *this;
}
- const char16_t* const end = str.end();
- const char16_t* start = str.begin();
- const char16_t* current = start;
+ const char* const end = str.end();
+ const char* start = str.begin();
+ const char* current = start;
while (current != end) {
if (mLastCharWasEscape) {
switch (*current) {
- case u't':
- mStr += u'\t';
+ case 't':
+ mStr += '\t';
break;
- case u'n':
- mStr += u'\n';
+ case 'n':
+ mStr += '\n';
break;
- case u'#':
- mStr += u'#';
+ case '#':
+ mStr += '#';
break;
- case u'@':
- mStr += u'@';
+ case '@':
+ mStr += '@';
break;
- case u'?':
- mStr += u'?';
+ case '?':
+ mStr += '?';
break;
- case u'"':
- mStr += u'"';
+ case '"':
+ mStr += '"';
break;
- case u'\'':
- mStr += u'\'';
+ case '\'':
+ mStr += '\'';
break;
- case u'\\':
- mStr += u'\\';
+ case '\\':
+ mStr += '\\';
break;
- case u'u': {
+ case 'u': {
current++;
- Maybe<char16_t> c = parseUnicodeCodepoint(¤t, end);
+ Maybe<std::string> c = parseUnicodeCodepoint(¤t, end);
if (!c) {
mError = "invalid unicode escape sequence";
return *this;
@@ -358,7 +362,7 @@
}
mLastCharWasEscape = false;
start = current + 1;
- } else if (*current == u'"') {
+ } else if (*current == '"') {
if (!mQuote && mTrailingSpace) {
// We found an opening quote, and we have
// trailing space, so we should append that
@@ -367,7 +371,7 @@
// We had trailing whitespace, so
// replace with a single space.
if (!mStr.empty()) {
- mStr += u' ';
+ mStr += ' ';
}
mTrailingSpace = false;
}
@@ -375,17 +379,17 @@
mQuote = !mQuote;
mStr.append(start, current - start);
start = current + 1;
- } else if (*current == u'\'' && !mQuote) {
+ } else if (*current == '\'' && !mQuote) {
// This should be escaped.
mError = "unescaped apostrophe";
return *this;
- } else if (*current == u'\\') {
+ } else if (*current == '\\') {
// This is an escape sequence, convert to the real value.
if (!mQuote && mTrailingSpace) {
// We had trailing whitespace, so
// replace with a single space.
if (!mStr.empty()) {
- mStr += u' ';
+ mStr += ' ';
}
mTrailingSpace = false;
}
@@ -394,7 +398,7 @@
mLastCharWasEscape = true;
} else if (!mQuote) {
// This is not quoted text, so look for whitespace.
- if (isspace16(*current)) {
+ if (isspace(*current)) {
// We found whitespace, see if we have seen some
// before.
if (!mTrailingSpace) {
@@ -410,7 +414,7 @@
// We saw trailing space before, so replace all
// that trailing space with one space.
if (!mStr.empty()) {
- mStr += u' ';
+ mStr += ' ';
}
mTrailingSpace = false;
}
@@ -441,10 +445,8 @@
}
std::string utf8;
- // Make room for '\0' explicitly.
- utf8.resize(utf8Length + 1);
- utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1);
utf8.resize(utf8Length);
+ utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1);
return utf8;
}
@@ -467,15 +469,58 @@
return data;
}
-bool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix,
- StringPiece16* outEntry, StringPiece16* outSuffix) {
- if (!stringStartsWith<char16_t>(path, u"res/")) {
+typename Tokenizer::iterator& Tokenizer::iterator::operator++() {
+ const char* start = mToken.end();
+ const char* end = mStr.end();
+ if (start == end) {
+ mEnd = true;
+ mToken.assign(mToken.end(), 0);
+ return *this;
+ }
+
+ start += 1;
+ const char* current = start;
+ while (current != end) {
+ if (*current == mSeparator) {
+ mToken.assign(start, current - start);
+ return *this;
+ }
+ ++current;
+ }
+ mToken.assign(start, end - start);
+ return *this;
+}
+
+bool Tokenizer::iterator::operator==(const iterator& rhs) const {
+ // We check equality here a bit differently.
+ // We need to know that the addresses are the same.
+ return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() &&
+ mEnd == rhs.mEnd;
+}
+
+bool Tokenizer::iterator::operator!=(const iterator& rhs) const {
+ return !(*this == rhs);
+}
+
+Tokenizer::iterator::iterator(StringPiece s, char sep, StringPiece tok, bool end) :
+ mStr(s), mSeparator(sep), mToken(tok), mEnd(end) {
+}
+
+Tokenizer::Tokenizer(StringPiece str, char sep) :
+ mBegin(++iterator(str, sep, StringPiece(str.begin() - 1, 0), false)),
+ mEnd(str, sep, StringPiece(str.end(), 0), true) {
+}
+
+bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
+ StringPiece* outEntry, StringPiece* outSuffix) {
+ const StringPiece resPrefix("res/");
+ if (!stringStartsWith(path, resPrefix)) {
return false;
}
- StringPiece16::const_iterator lastOccurence = path.end();
- for (auto iter = path.begin() + StringPiece16(u"res/").size(); iter != path.end(); ++iter) {
- if (*iter == u'/') {
+ StringPiece::const_iterator lastOccurence = path.end();
+ for (auto iter = path.begin() + resPrefix.size(); iter != path.end(); ++iter) {
+ if (*iter == '/') {
lastOccurence = iter;
}
}
@@ -484,12 +529,30 @@
return false;
}
- auto iter = std::find(lastOccurence, path.end(), u'.');
- *outSuffix = StringPiece16(iter, path.end() - iter);
- *outEntry = StringPiece16(lastOccurence + 1, iter - lastOccurence - 1);
- *outPrefix = StringPiece16(path.begin(), lastOccurence - path.begin() + 1);
+ auto iter = std::find(lastOccurence, path.end(), '.');
+ *outSuffix = StringPiece(iter, path.end() - iter);
+ *outEntry = StringPiece(lastOccurence + 1, iter - lastOccurence - 1);
+ *outPrefix = StringPiece(path.begin(), lastOccurence - path.begin() + 1);
return true;
}
+StringPiece16 getString16(const android::ResStringPool& pool, size_t idx) {
+ size_t len;
+ const char16_t* str = pool.stringAt(idx, &len);
+ if (str != nullptr) {
+ return StringPiece16(str, len);
+ }
+ return StringPiece16();
+}
+
+std::string getString(const android::ResStringPool& pool, size_t idx) {
+ size_t len;
+ const char* str = pool.string8At(idx, &len);
+ if (str != nullptr) {
+ return std::string(str, len);
+ }
+ return utf16ToUtf8(getString16(pool, idx));
+}
+
} // namespace util
} // namespace aapt
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 0dacbd7..4a10987 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -37,30 +37,18 @@
/**
* Returns true if the string starts with prefix.
*/
-template <typename T>
-bool stringStartsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& prefix) {
- if (str.size() < prefix.size()) {
- return false;
- }
- return str.substr(0, prefix.size()) == prefix;
-}
+bool stringStartsWith(const StringPiece& str, const StringPiece& prefix);
/**
* Returns true if the string ends with suffix.
*/
-template <typename T>
-bool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& suffix) {
- if (str.size() < suffix.size()) {
- return false;
- }
- return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
-}
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix);
/**
* Creates a new StringPiece16 that points to a substring
* of the original string without leading or trailing whitespace.
*/
-StringPiece16 trimWhitespace(const StringPiece16& str);
+StringPiece trimWhitespace(const StringPiece& str);
StringPiece trimWhitespace(const StringPiece& str);
@@ -76,18 +64,18 @@
* Returns an iterator to the first character that is not alpha-numeric and that
* is not in the allowedChars set.
*/
-StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
- const StringPiece16& allowedChars);
+StringPiece::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece& str,
+ const StringPiece& allowedChars);
/**
* Tests that the string is a valid Java class name.
*/
-bool isJavaClassName(const StringPiece16& str);
+bool isJavaClassName(const StringPiece& str);
/**
* Tests that the string is a valid Java package name.
*/
-bool isJavaPackageName(const StringPiece16& str);
+bool isJavaPackageName(const StringPiece& str);
/**
* Converts the class name to a fully qualified class name from the given `package`. Ex:
@@ -97,9 +85,8 @@
* .a.b --> package.a.b
* asdf.adsf --> asdf.adsf
*/
-Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
- const StringPiece16& className);
-
+Maybe<std::string> getFullyQualifiedClassName(const StringPiece& package,
+ const StringPiece& className);
/**
* Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
@@ -147,25 +134,17 @@
}
/**
- * Helper method to extract a string from a StringPool.
+ * Helper method to extract a UTF-16 string from a StringPool. If the string is stored as UTF-8,
+ * the conversion to UTF-16 happens within ResStringPool.
*/
-inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
- size_t len;
- const char16_t* str = pool.stringAt(idx, &len);
- if (str != nullptr) {
- return StringPiece16(str, len);
- }
- return StringPiece16();
-}
+StringPiece16 getString16(const android::ResStringPool& pool, size_t idx);
-inline StringPiece getString8(const android::ResStringPool& pool, size_t idx) {
- size_t len;
- const char* str = pool.string8At(idx, &len);
- if (str != nullptr) {
- return StringPiece(str, len);
- }
- return StringPiece();
-}
+/**
+ * Helper method to extract a UTF-8 string from a StringPool. If the string is stored as UTF-16,
+ * 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);
/**
* Checks that the Java string format contains no non-positional arguments (arguments without
@@ -173,24 +152,24 @@
* because translations may rearrange the order of the arguments in the string, which will
* break the string interpolation.
*/
-bool verifyJavaStringFormat(const StringPiece16& str);
+bool verifyJavaStringFormat(const StringPiece& str);
class StringBuilder {
public:
- StringBuilder& append(const StringPiece16& str);
- const std::u16string& str() const;
+ StringBuilder& append(const StringPiece& str);
+ const std::string& str() const;
const std::string& error() const;
operator bool() const;
private:
- std::u16string mStr;
+ std::string mStr;
bool mQuote = false;
bool mTrailingSpace = false;
bool mLastCharWasEscape = false;
std::string mError;
};
-inline const std::u16string& StringBuilder::str() const {
+inline const std::string& StringBuilder::str() const {
return mStr;
}
@@ -206,7 +185,7 @@
* Converts a UTF8 string to a UTF16 string.
*/
std::u16string utf8ToUtf16(const StringPiece& utf8);
-std::string utf16ToUtf8(const StringPiece16& utf8);
+std::string utf16ToUtf8(const StringPiece16& utf16);
/**
* Writes the entire BigBuffer to the output stream.
@@ -222,7 +201,6 @@
* A Tokenizer implemented as an iterable collection. It does not allocate
* any memory on the heap nor use standard containers.
*/
-template <typename Char>
class Tokenizer {
public:
class iterator {
@@ -231,96 +209,41 @@
iterator& operator=(const iterator&) = default;
iterator& operator++();
- BasicStringPiece<Char> operator*();
+
+ StringPiece operator*() {
+ return mToken;
+ }
bool operator==(const iterator& rhs) const;
bool operator!=(const iterator& rhs) const;
private:
- friend class Tokenizer<Char>;
+ friend class Tokenizer;
- iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok, bool end);
+ iterator(StringPiece s, char sep, StringPiece tok, bool end);
- BasicStringPiece<Char> mStr;
- Char mSeparator;
- BasicStringPiece<Char> mToken;
+ StringPiece mStr;
+ char mSeparator;
+ StringPiece mToken;
bool mEnd;
};
- Tokenizer(BasicStringPiece<Char> str, Char sep);
- iterator begin();
- iterator end();
+ Tokenizer(StringPiece str, char sep);
+
+ iterator begin() {
+ return mBegin;
+ }
+
+ iterator end() {
+ return mEnd;
+ }
private:
const iterator mBegin;
const iterator mEnd;
};
-template <typename Char>
-inline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
- return Tokenizer<Char>(str, sep);
-}
-
-template <typename Char>
-typename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
- const Char* start = mToken.end();
- const Char* end = mStr.end();
- if (start == end) {
- mEnd = true;
- mToken.assign(mToken.end(), 0);
- return *this;
- }
-
- start += 1;
- const Char* current = start;
- while (current != end) {
- if (*current == mSeparator) {
- mToken.assign(start, current - start);
- return *this;
- }
- ++current;
- }
- mToken.assign(start, end - start);
- return *this;
-}
-
-template <typename Char>
-inline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
- return mToken;
-}
-
-template <typename Char>
-inline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
- // We check equality here a bit differently.
- // We need to know that the addresses are the same.
- return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() &&
- mEnd == rhs.mEnd;
-}
-
-template <typename Char>
-inline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
- return !(*this == rhs);
-}
-
-template <typename Char>
-inline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
- BasicStringPiece<Char> tok, bool end) :
- mStr(s), mSeparator(sep), mToken(tok), mEnd(end) {
-}
-
-template <typename Char>
-inline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
- return mBegin;
-}
-
-template <typename Char>
-inline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
- return mEnd;
-}
-
-template <typename Char>
-inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
- mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0), false)),
- mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0), true) {
+inline Tokenizer tokenize(StringPiece str, char sep) {
+ return Tokenizer(str, sep);
}
inline uint16_t hostToDevice16(uint16_t value) {
@@ -348,8 +271,8 @@
*
* Returns true if successful.
*/
-bool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix,
- StringPiece16* outEntry, StringPiece16* outSuffix);
+bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
+ StringPiece* outEntry, StringPiece* outSuffix);
} // namespace util
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index fad1afb..0e27213 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -14,192 +14,191 @@
* limitations under the License.
*/
-#include "test/Common.h"
+#include "test/Test.h"
#include "util/StringPiece.h"
#include "util/Util.h"
-#include <gtest/gtest.h>
#include <string>
namespace aapt {
TEST(UtilTest, TrimOnlyWhitespace) {
- const std::u16string full = u"\n ";
+ const std::string full = "\n ";
- StringPiece16 trimmed = util::trimWhitespace(full);
+ StringPiece trimmed = util::trimWhitespace(full);
EXPECT_TRUE(trimmed.empty());
EXPECT_EQ(0u, trimmed.size());
}
TEST(UtilTest, StringEndsWith) {
- EXPECT_TRUE(util::stringEndsWith<char>("hello.xml", ".xml"));
+ EXPECT_TRUE(util::stringEndsWith("hello.xml", ".xml"));
}
TEST(UtilTest, StringStartsWith) {
- EXPECT_TRUE(util::stringStartsWith<char>("hello.xml", "he"));
+ EXPECT_TRUE(util::stringStartsWith("hello.xml", "he"));
}
TEST(UtilTest, StringBuilderSplitEscapeSequence) {
- EXPECT_EQ(StringPiece16(u"this is a new\nline."),
- util::StringBuilder().append(u"this is a new\\")
- .append(u"nline.")
+ EXPECT_EQ(StringPiece("this is a new\nline."),
+ util::StringBuilder().append("this is a new\\")
+ .append("nline.")
.str());
}
TEST(UtilTest, StringBuilderWhitespaceRemoval) {
- EXPECT_EQ(StringPiece16(u"hey guys this is so cool"),
- util::StringBuilder().append(u" hey guys ")
- .append(u" this is so cool ")
+ EXPECT_EQ(StringPiece("hey guys this is so cool"),
+ util::StringBuilder().append(" hey guys ")
+ .append(" this is so cool ")
.str());
- EXPECT_EQ(StringPiece16(u" wow, so many \t spaces. what?"),
- util::StringBuilder().append(u" \" wow, so many \t ")
- .append(u"spaces. \"what? ")
+ EXPECT_EQ(StringPiece(" wow, so many \t spaces. what?"),
+ util::StringBuilder().append(" \" wow, so many \t ")
+ .append("spaces. \"what? ")
.str());
- EXPECT_EQ(StringPiece16(u"where is the pie?"),
- util::StringBuilder().append(u" where \t ")
- .append(u" \nis the "" pie?")
+ EXPECT_EQ(StringPiece("where is the pie?"),
+ util::StringBuilder().append(" where \t ")
+ .append(" \nis the "" pie?")
.str());
}
TEST(UtilTest, StringBuilderEscaping) {
- EXPECT_EQ(StringPiece16(u"hey guys\n this \t is so\\ cool"),
- util::StringBuilder().append(u" hey guys\\n ")
- .append(u" this \\t is so\\\\ cool ")
+ EXPECT_EQ(StringPiece("hey guys\n this \t is so\\ cool"),
+ util::StringBuilder().append(" hey guys\\n ")
+ .append(" this \\t is so\\\\ cool ")
.str());
- EXPECT_EQ(StringPiece16(u"@?#\\\'"),
- util::StringBuilder().append(u"\\@\\?\\#\\\\\\'")
+ EXPECT_EQ(StringPiece("@?#\\\'"),
+ util::StringBuilder().append("\\@\\?\\#\\\\\\'")
.str());
}
TEST(UtilTest, StringBuilderMisplacedQuote) {
util::StringBuilder builder{};
- EXPECT_FALSE(builder.append(u"they're coming!"));
+ EXPECT_FALSE(builder.append("they're coming!"));
}
TEST(UtilTest, StringBuilderUnicodeCodes) {
- EXPECT_EQ(StringPiece16(u"\u00AF\u0AF0 woah"),
- util::StringBuilder().append(u"\\u00AF\\u0AF0 woah")
+ EXPECT_EQ(std::string("\u00AF\u0AF0 woah"),
+ util::StringBuilder().append("\\u00AF\\u0AF0 woah")
.str());
- EXPECT_FALSE(util::StringBuilder().append(u"\\u00 yo"));
+ EXPECT_FALSE(util::StringBuilder().append("\\u00 yo"));
}
TEST(UtilTest, TokenizeInput) {
- auto tokenizer = util::tokenize(StringPiece16(u"this| is|the|end"), u'|');
+ auto tokenizer = util::tokenize(StringPiece("this| is|the|end"), '|');
auto iter = tokenizer.begin();
- ASSERT_EQ(*iter, StringPiece16(u"this"));
+ ASSERT_EQ(*iter, StringPiece("this"));
++iter;
- ASSERT_EQ(*iter, StringPiece16(u" is"));
+ ASSERT_EQ(*iter, StringPiece(" is"));
++iter;
- ASSERT_EQ(*iter, StringPiece16(u"the"));
+ ASSERT_EQ(*iter, StringPiece("the"));
++iter;
- ASSERT_EQ(*iter, StringPiece16(u"end"));
+ ASSERT_EQ(*iter, StringPiece("end"));
++iter;
ASSERT_EQ(tokenizer.end(), iter);
}
TEST(UtilTest, TokenizeEmptyString) {
- auto tokenizer = util::tokenize(StringPiece16(u""), u'|');
+ auto tokenizer = util::tokenize(StringPiece(""), '|');
auto iter = tokenizer.begin();
ASSERT_NE(tokenizer.end(), iter);
- ASSERT_EQ(StringPiece16(), *iter);
+ ASSERT_EQ(StringPiece(), *iter);
++iter;
ASSERT_EQ(tokenizer.end(), iter);
}
TEST(UtilTest, TokenizeAtEnd) {
- auto tokenizer = util::tokenize(StringPiece16(u"one."), u'.');
+ auto tokenizer = util::tokenize(StringPiece("one."), '.');
auto iter = tokenizer.begin();
- ASSERT_EQ(*iter, StringPiece16(u"one"));
+ ASSERT_EQ(*iter, StringPiece("one"));
++iter;
ASSERT_NE(iter, tokenizer.end());
- ASSERT_EQ(*iter, StringPiece16());
+ ASSERT_EQ(*iter, StringPiece());
}
TEST(UtilTest, IsJavaClassName) {
- EXPECT_TRUE(util::isJavaClassName(u"android.test.Class"));
- EXPECT_TRUE(util::isJavaClassName(u"android.test.Class$Inner"));
- EXPECT_TRUE(util::isJavaClassName(u"android_test.test.Class"));
- EXPECT_TRUE(util::isJavaClassName(u"_android_.test._Class_"));
- EXPECT_FALSE(util::isJavaClassName(u"android.test.$Inner"));
- EXPECT_FALSE(util::isJavaClassName(u"android.test.Inner$"));
- EXPECT_FALSE(util::isJavaClassName(u".test.Class"));
- EXPECT_FALSE(util::isJavaClassName(u"android"));
+ EXPECT_TRUE(util::isJavaClassName("android.test.Class"));
+ EXPECT_TRUE(util::isJavaClassName("android.test.Class$Inner"));
+ EXPECT_TRUE(util::isJavaClassName("android_test.test.Class"));
+ EXPECT_TRUE(util::isJavaClassName("_android_.test._Class_"));
+ EXPECT_FALSE(util::isJavaClassName("android.test.$Inner"));
+ EXPECT_FALSE(util::isJavaClassName("android.test.Inner$"));
+ EXPECT_FALSE(util::isJavaClassName(".test.Class"));
+ EXPECT_FALSE(util::isJavaClassName("android"));
}
TEST(UtilTest, IsJavaPackageName) {
- EXPECT_TRUE(util::isJavaPackageName(u"android"));
- EXPECT_TRUE(util::isJavaPackageName(u"android.test"));
- EXPECT_TRUE(util::isJavaPackageName(u"android.test_thing"));
- EXPECT_FALSE(util::isJavaPackageName(u"_android"));
- EXPECT_FALSE(util::isJavaPackageName(u"android_"));
- EXPECT_FALSE(util::isJavaPackageName(u"android."));
- EXPECT_FALSE(util::isJavaPackageName(u".android"));
- EXPECT_FALSE(util::isJavaPackageName(u"android._test"));
- EXPECT_FALSE(util::isJavaPackageName(u".."));
+ EXPECT_TRUE(util::isJavaPackageName("android"));
+ EXPECT_TRUE(util::isJavaPackageName("android.test"));
+ EXPECT_TRUE(util::isJavaPackageName("android.test_thing"));
+ EXPECT_FALSE(util::isJavaPackageName("_android"));
+ EXPECT_FALSE(util::isJavaPackageName("android_"));
+ EXPECT_FALSE(util::isJavaPackageName("android."));
+ EXPECT_FALSE(util::isJavaPackageName(".android"));
+ EXPECT_FALSE(util::isJavaPackageName("android._test"));
+ EXPECT_FALSE(util::isJavaPackageName(".."));
}
TEST(UtilTest, FullyQualifiedClassName) {
- Maybe<std::u16string> res = util::getFullyQualifiedClassName(u"android", u".asdf");
+ Maybe<std::string> res = util::getFullyQualifiedClassName("android", ".asdf");
AAPT_ASSERT_TRUE(res);
- EXPECT_EQ(res.value(), u"android.asdf");
+ EXPECT_EQ(res.value(), "android.asdf");
- res = util::getFullyQualifiedClassName(u"android", u".a.b");
+ res = util::getFullyQualifiedClassName("android", ".a.b");
AAPT_ASSERT_TRUE(res);
- EXPECT_EQ(res.value(), u"android.a.b");
+ EXPECT_EQ(res.value(), "android.a.b");
- res = util::getFullyQualifiedClassName(u"android", u"a.b");
+ res = util::getFullyQualifiedClassName("android", "a.b");
AAPT_ASSERT_TRUE(res);
- EXPECT_EQ(res.value(), u"a.b");
+ EXPECT_EQ(res.value(), "a.b");
- res = util::getFullyQualifiedClassName(u"", u"a.b");
+ res = util::getFullyQualifiedClassName("", "a.b");
AAPT_ASSERT_TRUE(res);
- EXPECT_EQ(res.value(), u"a.b");
+ EXPECT_EQ(res.value(), "a.b");
- res = util::getFullyQualifiedClassName(u"android", u"Class");
+ res = util::getFullyQualifiedClassName("android", "Class");
AAPT_ASSERT_TRUE(res);
- EXPECT_EQ(res.value(), u"android.Class");
+ EXPECT_EQ(res.value(), "android.Class");
- res = util::getFullyQualifiedClassName(u"", u"");
+ res = util::getFullyQualifiedClassName("", "");
AAPT_ASSERT_FALSE(res);
- res = util::getFullyQualifiedClassName(u"android", u"./Apple");
+ res = util::getFullyQualifiedClassName("android", "./Apple");
AAPT_ASSERT_FALSE(res);
}
TEST(UtilTest, ExtractResourcePathComponents) {
- StringPiece16 prefix, entry, suffix;
- ASSERT_TRUE(util::extractResFilePathParts(u"res/xml-sw600dp/entry.xml", &prefix, &entry,
+ StringPiece prefix, entry, suffix;
+ ASSERT_TRUE(util::extractResFilePathParts("res/xml-sw600dp/entry.xml", &prefix, &entry,
&suffix));
- EXPECT_EQ(prefix, u"res/xml-sw600dp/");
- EXPECT_EQ(entry, u"entry");
- EXPECT_EQ(suffix, u".xml");
+ EXPECT_EQ(prefix, "res/xml-sw600dp/");
+ EXPECT_EQ(entry, "entry");
+ EXPECT_EQ(suffix, ".xml");
- ASSERT_TRUE(util::extractResFilePathParts(u"res/xml-sw600dp/entry.9.png", &prefix, &entry,
+ ASSERT_TRUE(util::extractResFilePathParts("res/xml-sw600dp/entry.9.png", &prefix, &entry,
&suffix));
- EXPECT_EQ(prefix, u"res/xml-sw600dp/");
- EXPECT_EQ(entry, u"entry");
- EXPECT_EQ(suffix, u".9.png");
+ EXPECT_EQ(prefix, "res/xml-sw600dp/");
+ EXPECT_EQ(entry, "entry");
+ EXPECT_EQ(suffix, ".9.png");
- EXPECT_FALSE(util::extractResFilePathParts(u"AndroidManifest.xml", &prefix, &entry, &suffix));
- EXPECT_FALSE(util::extractResFilePathParts(u"res/.xml", &prefix, &entry, &suffix));
+ EXPECT_FALSE(util::extractResFilePathParts("AndroidManifest.xml", &prefix, &entry, &suffix));
+ EXPECT_FALSE(util::extractResFilePathParts("res/.xml", &prefix, &entry, &suffix));
- ASSERT_TRUE(util::extractResFilePathParts(u"res//.", &prefix, &entry, &suffix));
- EXPECT_EQ(prefix, u"res//");
- EXPECT_EQ(entry, u"");
- EXPECT_EQ(suffix, u".");
+ ASSERT_TRUE(util::extractResFilePathParts("res//.", &prefix, &entry, &suffix));
+ EXPECT_EQ(prefix, "res//");
+ EXPECT_EQ(entry, "");
+ EXPECT_EQ(suffix, ".");
}
TEST(UtilTest, VerifyJavaStringFormat) {
- ASSERT_TRUE(util::verifyJavaStringFormat(u"%09.34f"));
- ASSERT_TRUE(util::verifyJavaStringFormat(u"%9$.34f %8$"));
- ASSERT_TRUE(util::verifyJavaStringFormat(u"%% %%"));
- ASSERT_FALSE(util::verifyJavaStringFormat(u"%09$f %f"));
- ASSERT_FALSE(util::verifyJavaStringFormat(u"%09f %08s"));
+ ASSERT_TRUE(util::verifyJavaStringFormat("%09.34f"));
+ ASSERT_TRUE(util::verifyJavaStringFormat("%9$.34f %8$"));
+ ASSERT_TRUE(util::verifyJavaStringFormat("%% %%"));
+ ASSERT_FALSE(util::verifyJavaStringFormat("%09$f %f"));
+ ASSERT_FALSE(util::verifyJavaStringFormat("%09f %08s"));
}
} // namespace aapt