blob: de938228b30db62b8ca3592683a3f8b81102a050 [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_STRING_PIECE_H
18#define AAPT_STRING_PIECE_H
19
Adam Lesinski32852a52016-06-15 10:56:41 -070020#include <utils/JenkinsHash.h>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080021#include <utils/String8.h>
22#include <utils/Unicode.h>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070023#include <ostream>
24#include <string>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080025
26namespace aapt {
27
28/**
29 * Read only wrapper around basic C strings.
30 * Prevents excessive copying.
31 *
32 * WARNING: When creating from std::basic_string<>, moving the original
33 * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
34 * BasicStringPiece<> should only be used transitively.
35 */
36template <typename TChar>
37class BasicStringPiece {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070038 public:
39 using const_iterator = const TChar*;
40 using difference_type = size_t;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 // End of string marker.
43 constexpr static const size_t npos = static_cast<size_t>(-1);
Adam Lesinski21efb682016-09-14 17:35:43 -070044
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 BasicStringPiece();
46 BasicStringPiece(const BasicStringPiece<TChar>& str);
47 BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit)
48 BasicStringPiece(const TChar* str); // NOLINT(implicit)
49 BasicStringPiece(const TChar* str, size_t len);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080050
Adam Lesinskicacb28f2016-10-19 12:18:14 -070051 BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
52 BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080053
Adam Lesinskicacb28f2016-10-19 12:18:14 -070054 BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const;
55 BasicStringPiece<TChar> substr(
56 BasicStringPiece<TChar>::const_iterator begin,
57 BasicStringPiece<TChar>::const_iterator end) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080058
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 const TChar* data() const;
60 size_t length() const;
61 size_t size() const;
62 bool empty() const;
63 std::basic_string<TChar> toString() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 bool contains(const BasicStringPiece<TChar>& rhs) const;
66 int compare(const BasicStringPiece<TChar>& rhs) const;
67 bool operator<(const BasicStringPiece<TChar>& rhs) const;
68 bool operator>(const BasicStringPiece<TChar>& rhs) const;
69 bool operator==(const BasicStringPiece<TChar>& rhs) const;
70 bool operator!=(const BasicStringPiece<TChar>& rhs) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080071
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 const_iterator begin() const;
73 const_iterator end() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080074
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 private:
76 const TChar* mData;
77 size_t mLength;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078};
79
80using StringPiece = BasicStringPiece<char>;
81using StringPiece16 = BasicStringPiece<char16_t>;
82
83//
84// BasicStringPiece implementation.
85//
86
87template <typename TChar>
Adam Lesinski21efb682016-09-14 17:35:43 -070088constexpr const size_t BasicStringPiece<TChar>::npos;
89
90template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070091inline BasicStringPiece<TChar>::BasicStringPiece()
92 : mData(nullptr), mLength(0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080093
94template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070095inline BasicStringPiece<TChar>::BasicStringPiece(
96 const BasicStringPiece<TChar>& str)
97 : mData(str.mData), mLength(str.mLength) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080098
99template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100inline BasicStringPiece<TChar>::BasicStringPiece(
101 const std::basic_string<TChar>& str)
102 : mData(str.data()), mLength(str.length()) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103
104template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105inline BasicStringPiece<char>::BasicStringPiece(const char* str)
106 : mData(str), mLength(str != nullptr ? strlen(str) : 0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800107
108template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700109inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str)
110 : mData(str), mLength(str != nullptr ? strlen16(str) : 0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800111
112template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len)
114 : mData(str), mLength(len) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800115
116template <typename TChar>
117inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700118 const BasicStringPiece<TChar>& rhs) {
119 mData = rhs.mData;
120 mLength = rhs.mLength;
121 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800122}
123
124template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700125inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(
126 const TChar* str, size_t len) {
127 mData = str;
128 mLength = len;
129 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800130}
131
132template <typename TChar>
133inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 size_t start, size_t len) const {
135 if (len == npos) {
136 len = mLength - start;
137 }
138
139 if (start > mLength || start + len > mLength) {
140 return BasicStringPiece<TChar>();
141 }
142 return BasicStringPiece<TChar>(mData + start, len);
143}
144
145template <typename TChar>
146inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
147 BasicStringPiece<TChar>::const_iterator begin,
148 BasicStringPiece<TChar>::const_iterator end) const {
149 return BasicStringPiece<TChar>(begin, end - begin);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800150}
151
152template <typename TChar>
153inline const TChar* BasicStringPiece<TChar>::data() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 return mData;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800155}
156
157template <typename TChar>
158inline size_t BasicStringPiece<TChar>::length() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700159 return mLength;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800160}
161
162template <typename TChar>
163inline size_t BasicStringPiece<TChar>::size() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164 return mLength;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800165}
166
167template <typename TChar>
168inline bool BasicStringPiece<TChar>::empty() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169 return mLength == 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800170}
171
172template <typename TChar>
173inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700174 return std::basic_string<TChar>(mData, mLength);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800175}
176
177template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700178inline bool BasicStringPiece<char>::contains(
179 const BasicStringPiece<char>& rhs) const {
180 if (!mData || !rhs.mData) {
181 return false;
182 }
183 if (rhs.mLength > mLength) {
184 return false;
185 }
186 return strstr(mData, rhs.mData) != nullptr;
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100187}
188
189template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700190inline int BasicStringPiece<char>::compare(
191 const BasicStringPiece<char>& rhs) const {
192 const char nullStr = '\0';
193 const char* b1 = mData != nullptr ? mData : &nullStr;
194 const char* e1 = b1 + mLength;
195 const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
196 const char* e2 = b2 + rhs.mLength;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800197
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700198 while (b1 < e1 && b2 < e2) {
199 const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
200 if (d) {
201 return d;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800202 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 }
204 return static_cast<int>(mLength - rhs.mLength);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800205}
206
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700207inline ::std::ostream& operator<<(::std::ostream& out,
208 const BasicStringPiece<char16_t>& str) {
209 android::String8 utf8(str.data(), str.size());
210 return out.write(utf8.string(), utf8.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800211}
212
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100213template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214inline bool BasicStringPiece<char16_t>::contains(
215 const BasicStringPiece<char16_t>& rhs) const {
216 if (!mData || !rhs.mData) {
217 return false;
218 }
219 if (rhs.mLength > mLength) {
220 return false;
221 }
222 return strstr16(mData, rhs.mData) != nullptr;
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100223}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800224
225template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700226inline int BasicStringPiece<char16_t>::compare(
227 const BasicStringPiece<char16_t>& rhs) const {
228 const char16_t nullStr = u'\0';
229 const char16_t* b1 = mData != nullptr ? mData : &nullStr;
230 const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
231 return strzcmp16(b1, mLength, b2, rhs.mLength);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800232}
233
234template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700235inline bool BasicStringPiece<TChar>::operator<(
236 const BasicStringPiece<TChar>& rhs) const {
237 return compare(rhs) < 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800238}
239
240template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241inline bool BasicStringPiece<TChar>::operator>(
242 const BasicStringPiece<TChar>& rhs) const {
243 return compare(rhs) > 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800244}
245
246template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247inline bool BasicStringPiece<TChar>::operator==(
248 const BasicStringPiece<TChar>& rhs) const {
249 return compare(rhs) == 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800250}
251
252template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253inline bool BasicStringPiece<TChar>::operator!=(
254 const BasicStringPiece<TChar>& rhs) const {
255 return compare(rhs) != 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800256}
257
258template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700259inline typename BasicStringPiece<TChar>::const_iterator
260BasicStringPiece<TChar>::begin() const {
261 return mData;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800262}
263
264template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700265inline typename BasicStringPiece<TChar>::const_iterator
266BasicStringPiece<TChar>::end() const {
267 return mData + mLength;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800268}
269
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700270inline ::std::ostream& operator<<(::std::ostream& out,
271 const BasicStringPiece<char>& str) {
272 return out.write(str.data(), str.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800273}
274
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700275} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800276
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700277inline ::std::ostream& operator<<(::std::ostream& out,
278 const std::u16string& str) {
279 android::String8 utf8(str.data(), str.size());
280 return out.write(utf8.string(), utf8.size());
Adam Lesinski90959882015-07-06 18:09:18 -0700281}
282
Adam Lesinski32852a52016-06-15 10:56:41 -0700283namespace std {
284
285template <typename TChar>
286struct hash<aapt::BasicStringPiece<TChar>> {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 size_t operator()(const aapt::BasicStringPiece<TChar>& str) const {
288 uint32_t hashCode = android::JenkinsHashMixBytes(
289 0, reinterpret_cast<const uint8_t*>(str.data()),
290 sizeof(TChar) * str.size());
291 return static_cast<size_t>(hashCode);
292 }
Adam Lesinski32852a52016-06-15 10:56:41 -0700293};
294
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700295} // namespace std
Adam Lesinski32852a52016-06-15 10:56:41 -0700296
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297#endif // AAPT_STRING_PIECE_H