Util.h revision 24aad163bc88cb10d2275385e9afc3de7f342d65
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/**
816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * This will be present in C++14 and can be removed then.
836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T, class... Args>
856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<T> make_unique(Args&&... args) {
866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes a set of items to the std::ostream, joining the times with the provided
916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * separator.
926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Iterator>
946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        const char* sep) {
966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        for (auto iter = begin; iter != end; ++iter) {
986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            if (iter != begin) {
996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                out << sep;
1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            }
1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            out << *iter;
1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        }
1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return out;
1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    };
1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) {
1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return [size](::std::ostream& out) -> ::std::ostream& {
109ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski        constexpr size_t K = 1024u;
1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        constexpr size_t M = K * K;
1111fce4f9c898d8053f4721e0f6ed85c9d07589f24Greg Hackmann        constexpr size_t G = M * K;
1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        if (size < K) {
1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            out << size << "B";
1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        } else if (size < M) {
1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            out << (double(size) / K) << " KiB";
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        } else if (size < G) {
1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            out << (double(size) / M) << " MiB";
1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        } else {
1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            out << (double(size) / G) << " GiB";
1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        }
1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return out;
1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    };
1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Helper method to extract a string from a StringPool.
1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    size_t len;
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const char16_t* str = pool.stringAt(idx, &len);
1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (str != nullptr) {
1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return StringPiece16(str, len);
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return StringPiece16();
1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass StringBuilder {
1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    StringBuilder& append(const StringPiece16& str);
1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const std::u16string& str() const;
1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const std::string& error() const;
1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    operator bool() const;
1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate:
1456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::u16string mStr;
1466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool mQuote = false;
1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool mTrailingSpace = false;
1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::string mError;
1496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::u16string& StringBuilder::str() const {
1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return mStr;
1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::string& StringBuilder::error() const {
1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return mError;
1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline StringBuilder::operator bool() const {
1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return mError.empty();
1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
1646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Converts a UTF8 string to a UTF16 string.
1656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::u16string utf8ToUtf16(const StringPiece& utf8);
1676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::string utf16ToUtf8(const StringPiece16& utf8);
1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
1706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Writes the entire BigBuffer to the output stream.
1716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskibool writeAll(std::ostream& out, const BigBuffer& buffer);
1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copies the entire BigBuffer into a single buffer.
1766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistd::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer);
1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * A Tokenizer implemented as an iterable collection. It does not allocate
1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * any memory on the heap nor use standard containers.
1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass Tokenizer {
1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    class iterator {
1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    public:
1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        iterator(const iterator&) = default;
1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        iterator& operator=(const iterator&) = default;
1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        iterator& operator++();
1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        BasicStringPiece<Char> operator*();
1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        bool operator==(const iterator& rhs) const;
1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        bool operator!=(const iterator& rhs) const;
1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    private:
1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        friend class Tokenizer<Char>;
1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok);
2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        BasicStringPiece<Char> str;
2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        Char separator;
2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        BasicStringPiece<Char> token;
2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    };
2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    Tokenizer(BasicStringPiece<Char> str, Char sep);
2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    iterator begin();
2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    iterator end();
2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate:
2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const iterator mBegin;
2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const iterator mEnd;
2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return Tokenizer<Char>(str, sep);
2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitypename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const Char* start = token.end();
2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const Char* end = str.end();
2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (start == end) {
2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        token.assign(token.end(), 0);
2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return *this;
2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    start += 1;
2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const Char* current = start;
2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    while (current != end) {
2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        if (*current == separator) {
2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            token.assign(start, current - start);
2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            return *this;
2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        }
2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        ++current;
2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    token.assign(start, end - start);
2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return *this;
2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return token;
2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // We check equality here a bit differently.
2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // We need to know that the addresses are the same.
2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return token.begin() == rhs.token.begin() && token.end() == rhs.token.end();
2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return !(*this == rhs);
2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                                           BasicStringPiece<Char> tok) :
2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        str(s), separator(sep), token(tok) {
2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return mBegin;
2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return mEnd;
2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename Char>
2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0))),
2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0)) {
2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
28124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski/**
28224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * Returns a package name if the namespace URI is of the form:
28324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * http://schemas.android.com/apk/res/<package>
28424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski *
28524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto,
28624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski * returns an empty package name.
28724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski */
28824aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<std::u16string> extractPackageFromNamespace(const std::u16string& namespaceUri);
28924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace util
2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
2936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Stream operator for functions. Calls the function with the stream as an argument.
2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * In the aapt namespace for lookup.
2956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
2966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::ostream& operator<<(::std::ostream& out,
2976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                                  ::std::function<::std::ostream&(::std::ostream&)> f) {
2986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return f(out);
2996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
3016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt
3026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
3036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_UTIL_H
304