File: Util.h

package info (click to toggle)
android-platform-frameworks-base 1%3A7.0.0%2Br33-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 137,116 kB
  • sloc: java: 704,370; cpp: 206,670; xml: 185,778; python: 2,626; ansic: 486; sh: 291; makefile: 48; sed: 19
file content (367 lines) | stat: -rw-r--r-- 10,265 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef AAPT_UTIL_H
#define AAPT_UTIL_H

#include "util/BigBuffer.h"
#include "util/Maybe.h"
#include "util/StringPiece.h"

#include <androidfw/ResourceTypes.h>
#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <vector>

namespace aapt {
namespace util {

std::vector<std::string> split(const StringPiece& str, char sep);
std::vector<std::string> splitAndLowercase(const StringPiece& str, char sep);

/**
 * Returns true if the string starts with prefix.
 */
template <typename T>
bool stringStartsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& prefix) {
    if (str.size() < prefix.size()) {
        return false;
    }
    return str.substr(0, prefix.size()) == prefix;
}

/**
 * Returns true if the string ends with suffix.
 */
template <typename T>
bool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& suffix) {
    if (str.size() < suffix.size()) {
        return false;
    }
    return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
}

/**
 * Creates a new StringPiece16 that points to a substring
 * of the original string without leading or trailing whitespace.
 */
StringPiece16 trimWhitespace(const StringPiece16& str);

StringPiece trimWhitespace(const StringPiece& str);

/**
 * UTF-16 isspace(). It basically checks for lower range characters that are
 * whitespace.
 */
inline bool isspace16(char16_t c) {
    return c < 0x0080 && isspace(c);
}

/**
 * Returns an iterator to the first character that is not alpha-numeric and that
 * is not in the allowedChars set.
 */
StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
        const StringPiece16& allowedChars);

/**
 * Tests that the string is a valid Java class name.
 */
bool isJavaClassName(const StringPiece16& str);

/**
 * Tests that the string is a valid Java package name.
 */
bool isJavaPackageName(const StringPiece16& str);

/**
 * Converts the class name to a fully qualified class name from the given `package`. Ex:
 *
 * asdf         --> package.asdf
 * .asdf        --> package.asdf
 * .a.b         --> package.a.b
 * asdf.adsf    --> asdf.adsf
 */
Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
                                                 const StringPiece16& className);


/**
 * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
 * This will be present in C++14 and can be removed then.
 */
template <typename T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
}

/**
 * Writes a set of items to the std::ostream, joining the times with the provided
 * separator.
 */
template <typename Iterator>
::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
        const char* sep) {
    return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
        for (auto iter = begin; iter != end; ++iter) {
            if (iter != begin) {
                out << sep;
            }
            out << *iter;
        }
        return out;
    };
}

inline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) {
    return [size](::std::ostream& out) -> ::std::ostream& {
        constexpr size_t K = 1024u;
        constexpr size_t M = K * K;
        constexpr size_t G = M * K;
        if (size < K) {
            out << size << "B";
        } else if (size < M) {
            out << (double(size) / K) << " KiB";
        } else if (size < G) {
            out << (double(size) / M) << " MiB";
        } else {
            out << (double(size) / G) << " GiB";
        }
        return out;
    };
}

/**
 * Helper method to extract a string from a StringPool.
 */
inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
    size_t len;
    const char16_t* str = pool.stringAt(idx, &len);
    if (str != nullptr) {
        return StringPiece16(str, len);
    }
    return StringPiece16();
}

inline StringPiece getString8(const android::ResStringPool& pool, size_t idx) {
    size_t len;
    const char* str = pool.string8At(idx, &len);
    if (str != nullptr) {
        return StringPiece(str, len);
    }
    return StringPiece();
}

/**
 * Checks that the Java string format contains no non-positional arguments (arguments without
 * explicitly specifying an index) when there are more than one argument. This is an error
 * because translations may rearrange the order of the arguments in the string, which will
 * break the string interpolation.
 */
bool verifyJavaStringFormat(const StringPiece16& str);

class StringBuilder {
public:
    StringBuilder& append(const StringPiece16& str);
    const std::u16string& str() const;
    const std::string& error() const;
    operator bool() const;

private:
    std::u16string mStr;
    bool mQuote = false;
    bool mTrailingSpace = false;
    bool mLastCharWasEscape = false;
    std::string mError;
};

inline const std::u16string& StringBuilder::str() const {
    return mStr;
}

inline const std::string& StringBuilder::error() const {
    return mError;
}

inline StringBuilder::operator bool() const {
    return mError.empty();
}

/**
 * Converts a UTF8 string to a UTF16 string.
 */
std::u16string utf8ToUtf16(const StringPiece& utf8);
std::string utf16ToUtf8(const StringPiece16& utf8);

/**
 * Writes the entire BigBuffer to the output stream.
 */
bool writeAll(std::ostream& out, const BigBuffer& buffer);

/*
 * Copies the entire BigBuffer into a single buffer.
 */
std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer);

/**
 * A Tokenizer implemented as an iterable collection. It does not allocate
 * any memory on the heap nor use standard containers.
 */
template <typename Char>
class Tokenizer {
public:
    class iterator {
    public:
        iterator(const iterator&) = default;
        iterator& operator=(const iterator&) = default;

        iterator& operator++();
        BasicStringPiece<Char> operator*();
        bool operator==(const iterator& rhs) const;
        bool operator!=(const iterator& rhs) const;

    private:
        friend class Tokenizer<Char>;

        iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok, bool end);

        BasicStringPiece<Char> mStr;
        Char mSeparator;
        BasicStringPiece<Char> mToken;
        bool mEnd;
    };

    Tokenizer(BasicStringPiece<Char> str, Char sep);
    iterator begin();
    iterator end();

private:
    const iterator mBegin;
    const iterator mEnd;
};

template <typename Char>
inline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
    return Tokenizer<Char>(str, sep);
}

template <typename Char>
typename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
    const Char* start = mToken.end();
    const Char* end = mStr.end();
    if (start == end) {
        mEnd = true;
        mToken.assign(mToken.end(), 0);
        return *this;
    }

    start += 1;
    const Char* current = start;
    while (current != end) {
        if (*current == mSeparator) {
            mToken.assign(start, current - start);
            return *this;
        }
        ++current;
    }
    mToken.assign(start, end - start);
    return *this;
}

template <typename Char>
inline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
    return mToken;
}

template <typename Char>
inline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
    // We check equality here a bit differently.
    // We need to know that the addresses are the same.
    return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() &&
            mEnd == rhs.mEnd;
}

template <typename Char>
inline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
    return !(*this == rhs);
}

template <typename Char>
inline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
                                           BasicStringPiece<Char> tok, bool end) :
        mStr(s), mSeparator(sep), mToken(tok), mEnd(end) {
}

template <typename Char>
inline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
    return mBegin;
}

template <typename Char>
inline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
    return mEnd;
}

template <typename Char>
inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
        mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0), false)),
        mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0), true) {
}

inline uint16_t hostToDevice16(uint16_t value) {
    return htods(value);
}

inline uint32_t hostToDevice32(uint32_t value) {
    return htodl(value);
}

inline uint16_t deviceToHost16(uint16_t value) {
    return dtohs(value);
}

inline uint32_t deviceToHost32(uint32_t value) {
    return dtohl(value);
}

/**
 * Given a path like: res/xml-sw600dp/foo.xml
 *
 * Extracts "res/xml-sw600dp/" into outPrefix.
 * Extracts "foo" into outEntry.
 * Extracts ".xml" into outSuffix.
 *
 * Returns true if successful.
 */
bool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix,
                             StringPiece16* outEntry, StringPiece16* outSuffix);

} // namespace util

/**
 * Stream operator for functions. Calls the function with the stream as an argument.
 * In the aapt namespace for lookup.
 */
inline ::std::ostream& operator<<(::std::ostream& out,
                                  ::std::function<::std::ostream&(::std::ostream&)> f) {
    return f(out);
}

} // namespace aapt

#endif // AAPT_UTIL_H