blob: 112437dc7bdee1e285d691b378c810307180ebe5 [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef AAPT_UTIL_H
18#define AAPT_UTIL_H
19
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "util/BigBuffer.h"
21#include "util/Maybe.h"
22#include "util/StringPiece.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080023
24#include <androidfw/ResourceTypes.h>
25#include <functional>
26#include <memory>
27#include <ostream>
28#include <string>
29#include <vector>
30
31namespace aapt {
32namespace util {
33
34std::vector<std::string> split(const StringPiece& str, char sep);
35std::vector<std::string> splitAndLowercase(const StringPiece& str, char sep);
36
37/**
Adam Lesinski4d3a9872015-04-09 19:53:22 -070038 * Returns true if the string starts with prefix.
39 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070040bool stringStartsWith(const StringPiece& str, const StringPiece& prefix);
Adam Lesinski4d3a9872015-04-09 19:53:22 -070041
42/**
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080043 * Returns true if the string ends with suffix.
44 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070045bool stringEndsWith(const StringPiece& str, const StringPiece& suffix);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080046
47/**
48 * Creates a new StringPiece16 that points to a substring
49 * of the original string without leading or trailing whitespace.
50 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070051StringPiece trimWhitespace(const StringPiece& str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080052
Adam Lesinski3b4cd942015-10-30 16:31:42 -070053StringPiece trimWhitespace(const StringPiece& str);
54
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080055/**
56 * UTF-16 isspace(). It basically checks for lower range characters that are
57 * whitespace.
58 */
59inline bool isspace16(char16_t c) {
60 return c < 0x0080 && isspace(c);
61}
62
63/**
64 * Returns an iterator to the first character that is not alpha-numeric and that
65 * is not in the allowedChars set.
66 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070067StringPiece::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece& str,
68 const StringPiece& allowedChars);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069
70/**
Adam Lesinskia1ad4a82015-06-08 11:41:09 -070071 * Tests that the string is a valid Java class name.
72 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070073bool isJavaClassName(const StringPiece& str);
Adam Lesinskia1ad4a82015-06-08 11:41:09 -070074
75/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -070076 * Tests that the string is a valid Java package name.
77 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070078bool isJavaPackageName(const StringPiece& str);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070079
80/**
Adam Lesinskia1ad4a82015-06-08 11:41:09 -070081 * Converts the class name to a fully qualified class name from the given `package`. Ex:
82 *
83 * asdf --> package.asdf
84 * .asdf --> package.asdf
85 * .a.b --> package.a.b
86 * asdf.adsf --> asdf.adsf
87 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -070088Maybe<std::string> getFullyQualifiedClassName(const StringPiece& package,
89 const StringPiece& className);
Adam Lesinskia1ad4a82015-06-08 11:41:09 -070090
91/**
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080092 * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
93 * This will be present in C++14 and can be removed then.
94 */
95template <typename T, class... Args>
96std::unique_ptr<T> make_unique(Args&&... args) {
97 return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
98}
99
100/**
101 * Writes a set of items to the std::ostream, joining the times with the provided
102 * separator.
103 */
104template <typename Iterator>
105::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
106 const char* sep) {
107 return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
108 for (auto iter = begin; iter != end; ++iter) {
109 if (iter != begin) {
110 out << sep;
111 }
112 out << *iter;
113 }
114 return out;
115 };
116}
117
118inline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) {
119 return [size](::std::ostream& out) -> ::std::ostream& {
Adam Lesinskica2fc352015-04-03 12:08:26 -0700120 constexpr size_t K = 1024u;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800121 constexpr size_t M = K * K;
Greg Hackmann1fce4f92015-04-02 20:23:22 -0700122 constexpr size_t G = M * K;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800123 if (size < K) {
124 out << size << "B";
125 } else if (size < M) {
126 out << (double(size) / K) << " KiB";
127 } else if (size < G) {
128 out << (double(size) / M) << " MiB";
129 } else {
130 out << (double(size) / G) << " GiB";
131 }
132 return out;
133 };
134}
135
136/**
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700137 * Helper method to extract a UTF-16 string from a StringPool. If the string is stored as UTF-8,
138 * the conversion to UTF-16 happens within ResStringPool.
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800139 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700140StringPiece16 getString16(const android::ResStringPool& pool, size_t idx);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700142/**
143 * Helper method to extract a UTF-8 string from a StringPool. If the string is stored as UTF-16,
144 * the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is done by this method,
145 * which maintains no state or cache. This means we must return an std::string copy.
146 */
147std::string getString(const android::ResStringPool& pool, size_t idx);
Adam Lesinski28cacf02015-11-23 14:22:47 -0800148
Adam Lesinskib23f1e02015-11-03 12:24:17 -0800149/**
150 * Checks that the Java string format contains no non-positional arguments (arguments without
151 * explicitly specifying an index) when there are more than one argument. This is an error
152 * because translations may rearrange the order of the arguments in the string, which will
153 * break the string interpolation.
154 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700155bool verifyJavaStringFormat(const StringPiece& str);
Adam Lesinskib23f1e02015-11-03 12:24:17 -0800156
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800157class StringBuilder {
158public:
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700159 StringBuilder& append(const StringPiece& str);
160 const std::string& str() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800161 const std::string& error() const;
162 operator bool() const;
163
164private:
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700165 std::string mStr;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166 bool mQuote = false;
167 bool mTrailingSpace = false;
Adam Lesinski90959882015-07-06 18:09:18 -0700168 bool mLastCharWasEscape = false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800169 std::string mError;
170};
171
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700172inline const std::string& StringBuilder::str() const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800173 return mStr;
174}
175
176inline const std::string& StringBuilder::error() const {
177 return mError;
178}
179
180inline StringBuilder::operator bool() const {
181 return mError.empty();
182}
183
184/**
185 * Converts a UTF8 string to a UTF16 string.
186 */
187std::u16string utf8ToUtf16(const StringPiece& utf8);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700188std::string utf16ToUtf8(const StringPiece16& utf16);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800189
190/**
191 * Writes the entire BigBuffer to the output stream.
192 */
193bool writeAll(std::ostream& out, const BigBuffer& buffer);
194
195/*
196 * Copies the entire BigBuffer into a single buffer.
197 */
198std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer);
199
200/**
201 * A Tokenizer implemented as an iterable collection. It does not allocate
202 * any memory on the heap nor use standard containers.
203 */
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800204class Tokenizer {
205public:
206 class iterator {
207 public:
208 iterator(const iterator&) = default;
209 iterator& operator=(const iterator&) = default;
210
211 iterator& operator++();
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700212
213 StringPiece operator*() {
214 return mToken;
215 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800216 bool operator==(const iterator& rhs) const;
217 bool operator!=(const iterator& rhs) const;
218
219 private:
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700220 friend class Tokenizer;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800221
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700222 iterator(StringPiece s, char sep, StringPiece tok, bool end);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800223
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700224 StringPiece mStr;
225 char mSeparator;
226 StringPiece mToken;
Adam Lesinskicf95a582015-11-16 15:37:30 -0800227 bool mEnd;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800228 };
229
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700230 Tokenizer(StringPiece str, char sep);
231
232 iterator begin() {
233 return mBegin;
234 }
235
236 iterator end() {
237 return mEnd;
238 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800239
240private:
241 const iterator mBegin;
242 const iterator mEnd;
243};
244
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -0700245inline Tokenizer tokenize(const StringPiece& str, char sep) {
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700246 return Tokenizer(str, sep);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800247}
248
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700249inline uint16_t hostToDevice16(uint16_t value) {
250 return htods(value);
251}
252
253inline uint32_t hostToDevice32(uint32_t value) {
254 return htodl(value);
255}
256
257inline uint16_t deviceToHost16(uint16_t value) {
258 return dtohs(value);
259}
260
261inline uint32_t deviceToHost32(uint32_t value) {
262 return dtohl(value);
263}
264
Adam Lesinski24aad162015-04-24 19:19:30 -0700265/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700266 * Given a path like: res/xml-sw600dp/foo.xml
267 *
268 * Extracts "res/xml-sw600dp/" into outPrefix.
269 * Extracts "foo" into outEntry.
270 * Extracts ".xml" into outSuffix.
271 *
272 * Returns true if successful.
273 */
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700274bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
275 StringPiece* outEntry, StringPiece* outSuffix);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700276
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800277} // namespace util
278
279/**
280 * Stream operator for functions. Calls the function with the stream as an argument.
281 * In the aapt namespace for lookup.
282 */
283inline ::std::ostream& operator<<(::std::ostream& out,
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -0700284 const ::std::function<::std::ostream&(::std::ostream&)>& f) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800285 return f(out);
286}
287
288} // namespace aapt
289
290#endif // AAPT_UTIL_H