16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "BigBuffer.h" 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "Maybe.h" 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "StringPiece.h" 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "Util.h" 216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <algorithm> 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <ostream> 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <utils/Unicode.h> 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <vector> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace util { 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiconstexpr const char16_t* kSchemaAuto = u"http://schemas.android.com/apk/res-auto"; 3224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiconstexpr const char16_t* kSchemaPrefix = u"http://schemas.android.com/apk/res/"; 3324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistatic std::vector<std::string> splitAndTransform(const StringPiece& str, char sep, 356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::function<char(char)>& f) { 366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::vector<std::string> parts; 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const StringPiece::const_iterator end = std::end(str); 386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski StringPiece::const_iterator start = std::begin(str); 396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski StringPiece::const_iterator current; 406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski do { 416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski current = std::find(start, end, sep); 426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski parts.emplace_back(str.substr(start, current).toString()); 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (f) { 446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::string& part = parts.back(); 456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::transform(part.begin(), part.end(), part.begin(), f); 466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start = current + 1; 486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } while (current != end); 496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return parts; 506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::vector<std::string> split(const StringPiece& str, char sep) { 536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return splitAndTransform(str, sep, nullptr); 546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::vector<std::string> splitAndLowercase(const StringPiece& str, char sep) { 576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return splitAndTransform(str, sep, ::tolower); 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringPiece16 trimWhitespace(const StringPiece16& str) { 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (str.size() == 0 || str.data() == nullptr) { 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return str; 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* start = str.data(); 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* end = str.data() + str.length(); 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski while (start != end && util::isspace16(*start)) { 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start++; 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski while (end != start && util::isspace16(*(end - 1))) { 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski end--; 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return StringPiece16(start, end - start); 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str, 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const StringPiece16& allowedChars) { 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const auto endIter = str.end(); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (auto iter = str.begin(); iter != endIter; ++iter) { 836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski char16_t c = *iter; 846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if ((c >= u'a' && c <= u'z') || 856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski (c >= u'A' && c <= u'Z') || 866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski (c >= u'0' && c <= u'9')) { 876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski continue; 886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool match = false; 916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (char16_t i : allowedChars) { 926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (c == i) { 936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski match = true; 946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!match) { 996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return iter; 1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return endIter; 1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 105a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskibool isJavaClassName(const StringPiece16& str) { 106a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski size_t pieces = 0; 107a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski for (const StringPiece16& piece : tokenize(str, u'.')) { 108a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski pieces++; 109a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (piece.empty()) { 110a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return false; 111a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 112a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 113a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski // Can't have starting or trailing $ character. 114a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (piece.data()[0] == u'$' || piece.data()[piece.size() - 1] == u'$') { 115a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return false; 116a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 117a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 118a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (findNonAlphaNumericAndNotInSet(piece, u"$_") != piece.end()) { 119a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return false; 120a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 121a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 122a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return pieces >= 2; 123a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski} 124a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 125a1ad4a812a87642ad259ff4478159e8cc8194680Adam LesinskiMaybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package, 126a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski const StringPiece16& className) { 127a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (className.empty()) { 128a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return {}; 129a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 130a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 131a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (util::isJavaClassName(className)) { 132a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return className.toString(); 133a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 134a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 135a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (package.empty()) { 136a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return {}; 137a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 138a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 139a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski std::u16string result(package.data(), package.size()); 140a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (className.data()[0] != u'.') { 141a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski result += u'.'; 142a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 143a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski result.append(className.data(), className.size()); 144a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski if (!isJavaClassName(result)) { 145a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return {}; 146a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski } 147a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski return result; 148a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski} 149a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistatic Maybe<char16_t> parseUnicodeCodepoint(const char16_t** start, const char16_t* end) { 1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski char16_t code = 0; 1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (size_t i = 0; i < 4 && *start != end; i++, (*start)++) { 1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski char16_t c = **start; 1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski int a; 1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (c >= '0' && c <= '9') { 1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski a = c - '0'; 1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (c >= 'a' && c <= 'f') { 1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski a = c - 'a' + 10; 1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (c >= 'A' && c <= 'F') { 1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski a = c - 'A' + 10; 1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else { 1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return make_nothing<char16_t>(); 1636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski code = (code << 4) | a; 1656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return make_value(code); 1676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringBuilder& StringBuilder::append(const StringPiece16& str) { 1706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mError.empty()) { 1716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 1726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* const end = str.end(); 1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* start = str.begin(); 1766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* current = start; 1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski while (current != end) { 1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (*current == u'"') { 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mQuote && mTrailingSpace) { 1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We found an opening quote, and we have 1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // trailing space, so we should append that 1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // space now. 1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (mTrailingSpace) { 1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We had trailing whitespace, so 1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // replace with a single space. 1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mStr.empty()) { 1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u' '; 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mTrailingSpace = false; 1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mQuote = !mQuote; 1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr.append(start, current - start); 1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start = current + 1; 1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (*current == u'\'' && !mQuote) { 1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // This should be escaped. 1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mError = "unescaped apostrophe"; 1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (*current == u'\\') { 2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // This is an escape sequence, convert to the real value. 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mQuote && mTrailingSpace) { 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We had trailing whitespace, so 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // replace with a single space. 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mStr.empty()) { 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u' '; 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mTrailingSpace = false; 2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr.append(start, current - start); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start = current + 1; 2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski current++; 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (current != end) { 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski switch (*current) { 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u't': 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'\t'; 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'n': 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'\n'; 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'#': 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'#'; 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'@': 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'@'; 2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'?': 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'?'; 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'"': 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'"'; 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'\'': 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'\''; 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'\\': 2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u'\\'; 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski case u'u': { 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski current++; 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Maybe<char16_t> c = parseUnicodeCodepoint(¤t, end); 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!c) { 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mError = "invalid unicode escape sequence"; 2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += c.value(); 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski current -= 1; 2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski default: 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Ignore. 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski break; 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start = current + 1; 2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (!mQuote) { 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // This is not quoted text, so look for whitespace. 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (isspace16(*current)) { 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We found whitespace, see if we have seen some 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // before. 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mTrailingSpace) { 2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We didn't see a previous adjacent space, 2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // so mark that we did. 2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mTrailingSpace = true; 2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr.append(start, current - start); 2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Keep skipping whitespace. 2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start = current + 1; 2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (mTrailingSpace) { 2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We saw trailing space before, so replace all 2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // that trailing space with one space. 2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!mStr.empty()) { 2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr += u' '; 2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mTrailingSpace = false; 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski current++; 2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mStr.append(start, end - start); 2836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::u16string utf8ToUtf16(const StringPiece& utf8) { 2876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ssize_t utf16Length = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(utf8.data()), 2886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski utf8.length()); 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (utf16Length <= 0) { 2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return {}; 2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::u16string utf16; 2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski utf16.resize(utf16Length); 2956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length(), &*utf16.begin()); 2966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return utf16; 2976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::string utf16ToUtf8(const StringPiece16& utf16) { 3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ssize_t utf8Length = utf16_to_utf8_length(utf16.data(), utf16.length()); 3016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (utf8Length <= 0) { 3026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return {}; 3036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::string utf8; 3066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski utf8.resize(utf8Length); 3076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin()); 3086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return utf8; 3096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskibool writeAll(std::ostream& out, const BigBuffer& buffer) { 3126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (const auto& b : buffer) { 3136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (!out.write(reinterpret_cast<const char*>(b.buffer.get()), b.size)) { 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return true; 3186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer) { 3216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[buffer.size()]); 3226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski uint8_t* p = data.get(); 3236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (const auto& block : buffer) { 3246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski memcpy(p, block.buffer.get(), block.size); 3256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski p += block.size; 3266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return data; 3286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 33024aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<std::u16string> extractPackageFromNamespace(const std::u16string& namespaceUri) { 33124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski if (stringStartsWith<char16_t>(namespaceUri, kSchemaPrefix)) { 33224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski StringPiece16 schemaPrefix = kSchemaPrefix; 33324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski StringPiece16 package = namespaceUri; 33424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski return package.substr(schemaPrefix.size(), package.size() - schemaPrefix.size()) 33524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski .toString(); 33624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski } else if (namespaceUri == kSchemaAuto) { 33724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski return std::u16string(); 33824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski } 33924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski return {}; 34024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 34124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace util 3436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 344