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#ifndef AAPT_UTIL_H 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_UTIL_H 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/BigBuffer.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Maybe.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/StringPiece.h" 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <androidfw/ResourceTypes.h> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <functional> 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <memory> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <ostream> 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <vector> 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace util { 336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::vector<std::string> split(const StringPiece& str, char sep); 356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::vector<std::string> splitAndLowercase(const StringPiece& str, char sep); 366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 384d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski * Returns true if the string starts with prefix. 394d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski */ 404d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinskitemplate <typename T> 414d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinskibool stringStartsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& prefix) { 424d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski if (str.size() < prefix.size()) { 434d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski return false; 444d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski } 454d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski return str.substr(0, prefix.size()) == prefix; 464d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski} 474d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski 484d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski/** 496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Returns true if the string ends with suffix. 506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 514d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinskitemplate <typename T> 524d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinskibool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& suffix) { 534d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski if (str.size() < suffix.size()) { 544d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski return false; 554d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski } 564d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski return str.substr(str.size() - suffix.size(), suffix.size()) == suffix; 574d3a987694f6f6b95d8a0f1542618223ce253e6dAdam Lesinski} 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Creates a new StringPiece16 that points to a substring 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * of the original string without leading or trailing whitespace. 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringPiece16 trimWhitespace(const StringPiece16& str); 646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 653b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam LesinskiStringPiece trimWhitespace(const StringPiece& str); 663b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * UTF-16 isspace(). It basically checks for lower range characters that are 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * whitespace. 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool isspace16(char16_t c) { 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return c < 0x0080 && isspace(c); 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Returns an iterator to the first character that is not alpha-numeric and that 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * is not in the allowedChars set. 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str, 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const StringPiece16& allowedChars); 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 83a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Tests that the string is a valid Java class name. 84a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski */ 85a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskibool isJavaClassName(const StringPiece16& str); 86a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 87a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski/** 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Tests that the string is a valid Java package name. 891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskibool isJavaPackageName(const StringPiece16& str); 911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/** 93a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Converts the class name to a fully qualified class name from the given `package`. Ex: 94a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * 95a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * asdf --> package.asdf 96a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * .asdf --> package.asdf 97a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * .a.b --> package.a.b 98a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * asdf.adsf --> asdf.adsf 99a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski */ 100a1ad4a812a87642ad259ff4478159e8cc8194680Adam LesinskiMaybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package, 101a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski const StringPiece16& className); 102a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 103a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 104a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski/** 1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Makes a std::unique_ptr<> with the template parameter inferred by the compiler. 1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * This will be present in C++14 and can be removed then. 1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T, class... Args> 1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<T> make_unique(Args&&... args) { 1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); 1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes a set of items to the std::ostream, joining the times with the provided 1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * separator. 1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Iterator> 1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end, 1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char* sep) { 1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return [begin, end, sep](::std::ostream& out) -> ::std::ostream& { 1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (auto iter = begin; iter != end; ++iter) { 1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (iter != begin) { 1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << sep; 1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << *iter; 1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return out; 1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) { 1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return [size](::std::ostream& out) -> ::std::ostream& { 133ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski constexpr size_t K = 1024u; 1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski constexpr size_t M = K * K; 1351fce4f9c898d8053f4721e0f6ed85c9d07589f24Greg Hackmann constexpr size_t G = M * K; 1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (size < K) { 1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << size << "B"; 1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (size < M) { 1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / K) << " KiB"; 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (size < G) { 1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / M) << " MiB"; 1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else { 1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / G) << " GiB"; 1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return out; 1466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Helper method to extract a string from a StringPool. 1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) { 1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski size_t len; 1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* str = pool.stringAt(idx, &len); 1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (str != nullptr) { 1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return StringPiece16(str, len); 1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return StringPiece16(); 1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 16128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinskiinline StringPiece getString8(const android::ResStringPool& pool, size_t idx) { 16228cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski size_t len; 16328cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski const char* str = pool.string8At(idx, &len); 16428cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (str != nullptr) { 16528cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski return StringPiece(str, len); 16628cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski } 16728cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski return StringPiece(); 16828cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski} 16928cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski 170b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski/** 171b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski * Checks that the Java string format contains no non-positional arguments (arguments without 172b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski * explicitly specifying an index) when there are more than one argument. This is an error 173b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski * because translations may rearrange the order of the arguments in the string, which will 174b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski * break the string interpolation. 175b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski */ 176b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinskibool verifyJavaStringFormat(const StringPiece16& str); 177b23f1e077b02a1d62bcf5e34655e8dc979e124faAdam Lesinski 1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass StringBuilder { 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic: 1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski StringBuilder& append(const StringPiece16& str); 1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::u16string& str() const; 1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::string& error() const; 1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski operator bool() const; 1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate: 1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::u16string mStr; 1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool mQuote = false; 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool mTrailingSpace = false; 18990959887e9a61ff83097b2789f8b3243ad817decAdam Lesinski bool mLastCharWasEscape = false; 1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::string mError; 1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::u16string& StringBuilder::str() const { 1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mStr; 1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::string& StringBuilder::error() const { 1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mError; 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringBuilder::operator bool() const { 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mError.empty(); 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Converts a UTF8 string to a UTF16 string. 2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::u16string utf8ToUtf16(const StringPiece& utf8); 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::string utf16ToUtf8(const StringPiece16& utf8); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes the entire BigBuffer to the output stream. 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskibool writeAll(std::ostream& out, const BigBuffer& buffer); 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copies the entire BigBuffer into a single buffer. 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer); 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * A Tokenizer implemented as an iterable collection. It does not allocate 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * any memory on the heap nor use standard containers. 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass Tokenizer { 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic: 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski class iterator { 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski public: 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator(const iterator&) = default; 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator& operator=(const iterator&) = default; 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator& operator++(); 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BasicStringPiece<Char> operator*(); 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool operator==(const iterator& rhs) const; 2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool operator!=(const iterator& rhs) const; 2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski private: 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski friend class Tokenizer<Char>; 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 241cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok, bool end); 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 243cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski BasicStringPiece<Char> mStr; 244cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski Char mSeparator; 245cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski BasicStringPiece<Char> mToken; 246cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski bool mEnd; 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Tokenizer(BasicStringPiece<Char> str, Char sep); 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator begin(); 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator end(); 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate: 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const iterator mBegin; 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const iterator mEnd; 2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) { 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return Tokenizer<Char>(str, sep); 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitypename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() { 265cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski const Char* start = mToken.end(); 266cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski const Char* end = mStr.end(); 2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (start == end) { 268cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mEnd = true; 269cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mToken.assign(mToken.end(), 0); 2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start += 1; 2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const Char* current = start; 2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski while (current != end) { 276cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski if (*current == mSeparator) { 277cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mToken.assign(start, current - start); 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ++current; 2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 282cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mToken.assign(start, end - start); 2836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() { 288cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski return mToken; 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const { 2936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We check equality here a bit differently. 2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We need to know that the addresses are the same. 295cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() && 296cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mEnd == rhs.mEnd; 2976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const { 3016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return !(*this == rhs); 3026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 3056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep, 306cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski BasicStringPiece<Char> tok, bool end) : 307cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mStr(s), mSeparator(sep), mToken(tok), mEnd(end) { 3086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 3116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() { 3126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mBegin; 3136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 3166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() { 3176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mEnd; 3186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 3216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) : 322cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0), false)), 323cf95a580149ec03588b1c75f036c924730f83615Adam Lesinski mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0), true) { 3246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline uint16_t hostToDevice16(uint16_t value) { 3271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return htods(value); 3281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline uint32_t hostToDevice32(uint32_t value) { 3311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return htodl(value); 3321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline uint16_t deviceToHost16(uint16_t value) { 3351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return dtohs(value); 3361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline uint32_t deviceToHost32(uint32_t value) { 3391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return dtohl(value); 3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 34224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski/** 3431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Given a path like: res/xml-sw600dp/foo.xml 3441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 3451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Extracts "res/xml-sw600dp/" into outPrefix. 3461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Extracts "foo" into outEntry. 3471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Extracts ".xml" into outSuffix. 3481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Returns true if successful. 3501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 3511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskibool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix, 3521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski StringPiece16* outEntry, StringPiece16* outSuffix); 3531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace util 3556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 3576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Stream operator for functions. Calls the function with the stream as an argument. 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * In the aapt namespace for lookup. 3596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 3606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::ostream& operator<<(::std::ostream& out, 3616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ::std::function<::std::ostream&(::std::ostream&)> f) { 3626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return f(out); 3636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 3666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_UTIL_H 368