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(&current, end);
+                    Maybe<std::string> c = parseUnicodeCodepoint(&current, 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