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