Util.h revision a1ad4a812a87642ad259ff4478159e8cc8194680
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 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "BigBuffer.h" 2124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski#include "Maybe.h" 226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "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 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * UTF-16 isspace(). It basically checks for lower range characters that are 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * whitespace. 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool isspace16(char16_t c) { 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return c < 0x0080 && isspace(c); 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Returns an iterator to the first character that is not alpha-numeric and that 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * is not in the allowedChars set. 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiStringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str, 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const StringPiece16& allowedChars); 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 81a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Tests that the string is a valid Java class name. 82a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski */ 83a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskibool isJavaClassName(const StringPiece16& str); 84a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 85a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski/** 86a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Converts the class name to a fully qualified class name from the given `package`. Ex: 87a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * 88a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * asdf --> package.asdf 89a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * .asdf --> package.asdf 90a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * .a.b --> package.a.b 91a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * asdf.adsf --> asdf.adsf 92a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski */ 93a1ad4a812a87642ad259ff4478159e8cc8194680Adam LesinskiMaybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package, 94a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski const StringPiece16& className); 95a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 96a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski 97a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski/** 986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Makes a std::unique_ptr<> with the template parameter inferred by the compiler. 996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * This will be present in C++14 and can be removed then. 1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T, class... Args> 1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<T> make_unique(Args&&... args) { 1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); 1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes a set of items to the std::ostream, joining the times with the provided 1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * separator. 1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Iterator> 1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end, 1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char* sep) { 1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return [begin, end, sep](::std::ostream& out) -> ::std::ostream& { 1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski for (auto iter = begin; iter != end; ++iter) { 1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (iter != begin) { 1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << sep; 1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << *iter; 1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return out; 1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) { 1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return [size](::std::ostream& out) -> ::std::ostream& { 126ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski constexpr size_t K = 1024u; 1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski constexpr size_t M = K * K; 1281fce4f9c898d8053f4721e0f6ed85c9d07589f24Greg Hackmann constexpr size_t G = M * K; 1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (size < K) { 1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << size << "B"; 1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (size < M) { 1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / K) << " KiB"; 1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (size < G) { 1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / M) << " MiB"; 1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else { 1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski out << (double(size) / G) << " GiB"; 1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return out; 1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Helper method to extract a string from a StringPool. 1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) { 1466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski size_t len; 1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const char16_t* str = pool.stringAt(idx, &len); 1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (str != nullptr) { 1496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return StringPiece16(str, len); 1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return StringPiece16(); 1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass StringBuilder { 1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic: 1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski StringBuilder& append(const StringPiece16& str); 1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::u16string& str() const; 1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::string& error() const; 1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski operator bool() const; 1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate: 1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::u16string mStr; 1636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool mQuote = false; 1646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool mTrailingSpace = false; 1656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::string mError; 1666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 1676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::u16string& StringBuilder::str() const { 1696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mStr; 1706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::string& StringBuilder::error() const { 1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mError; 1746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringBuilder::operator bool() const { 1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mError.empty(); 1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Converts a UTF8 string to a UTF16 string. 1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::u16string utf8ToUtf16(const StringPiece& utf8); 1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::string utf16ToUtf8(const StringPiece16& utf8); 1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes the entire BigBuffer to the output stream. 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskibool writeAll(std::ostream& out, const BigBuffer& buffer); 1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copies the entire BigBuffer into a single buffer. 1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer); 1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * A Tokenizer implemented as an iterable collection. It does not allocate 1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * any memory on the heap nor use standard containers. 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass Tokenizer { 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic: 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski class iterator { 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski public: 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator(const iterator&) = default; 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator& operator=(const iterator&) = default; 2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator& operator++(); 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BasicStringPiece<Char> operator*(); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool operator==(const iterator& rhs) const; 2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski bool operator!=(const iterator& rhs) const; 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski private: 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski friend class Tokenizer<Char>; 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok); 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BasicStringPiece<Char> str; 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Char separator; 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BasicStringPiece<Char> token; 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Tokenizer(BasicStringPiece<Char> str, Char sep); 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator begin(); 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski iterator end(); 2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate: 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const iterator mBegin; 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const iterator mEnd; 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) { 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return Tokenizer<Char>(str, sep); 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitypename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() { 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const Char* start = token.end(); 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const Char* end = str.end(); 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (start == end) { 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski token.assign(token.end(), 0); 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski start += 1; 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const Char* current = start; 2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski while (current != end) { 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (*current == separator) { 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski token.assign(start, current - start); 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ++current; 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski token.assign(start, end - start); 2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return *this; 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() { 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return token; 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const { 2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We check equality here a bit differently. 2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We need to know that the addresses are the same. 2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return token.begin() == rhs.token.begin() && token.end() == rhs.token.end(); 2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const { 2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return !(*this == rhs); 2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep, 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BasicStringPiece<Char> tok) : 2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski str(s), separator(sep), token(tok) { 2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() { 2846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mBegin; 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() { 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mEnd; 2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char> 2936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) : 2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0))), 2956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0)) { 2966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 29824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski/** 29924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * Returns a package name if the namespace URI is of the form: 30024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * http://schemas.android.com/apk/res/<package> 30124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * 30224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto, 30324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * returns an empty package name. 30424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski */ 30524aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<std::u16string> extractPackageFromNamespace(const std::u16string& namespaceUri); 30624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace util 3086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 3106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Stream operator for functions. Calls the function with the stream as an argument. 3116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * In the aapt namespace for lookup. 3126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 3136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::ostream& operator<<(::std::ostream& out, 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ::std::function<::std::ostream&(::std::ostream&)> f) { 3156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return f(out); 3166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_UTIL_H 321