blob: 266c003ec264af51fa6aa23ac8869da4ef1d0f54 [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
20#include <ostream>
21#include <string>
Adam Lesinski32852a52016-06-15 10:56:41 -070022#include <utils/JenkinsHash.h>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080023#include <utils/String8.h>
24#include <utils/Unicode.h>
25
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 {
38public:
39 using const_iterator = const TChar*;
Adam Lesinskica5638f2015-10-21 14:42:43 -070040 using difference_type = size_t;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041
Adam Lesinski21efb682016-09-14 17:35:43 -070042 // End of string marker.
43 constexpr static const size_t npos = static_cast<size_t>(-1);
44
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080045 BasicStringPiece();
46 BasicStringPiece(const BasicStringPiece<TChar>& str);
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070047 BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit)
48 BasicStringPiece(const TChar* str); // NOLINT(implicit)
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080049 BasicStringPiece(const TChar* str, size_t len);
50
51 BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
52 BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
53
Adam Lesinski21efb682016-09-14 17:35:43 -070054 BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080055 BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
56 BasicStringPiece<TChar>::const_iterator end) const;
57
58 const TChar* data() const;
59 size_t length() const;
60 size_t size() const;
61 bool empty() const;
62 std::basic_string<TChar> toString() const;
63
Michael Wrightfeaf99f2016-05-06 17:16:06 +010064 bool contains(const BasicStringPiece<TChar>& rhs) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080065 int compare(const BasicStringPiece<TChar>& rhs) const;
66 bool operator<(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
71 const_iterator begin() const;
72 const_iterator end() const;
73
74private:
75 const TChar* mData;
76 size_t mLength;
77};
78
79using StringPiece = BasicStringPiece<char>;
80using StringPiece16 = BasicStringPiece<char16_t>;
81
82//
83// BasicStringPiece implementation.
84//
85
86template <typename TChar>
Adam Lesinski21efb682016-09-14 17:35:43 -070087constexpr const size_t BasicStringPiece<TChar>::npos;
88
89template <typename TChar>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080090inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
91}
92
93template <typename TChar>
94inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
95 mData(str.mData), mLength(str.mLength) {
96}
97
98template <typename TChar>
99inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
100 mData(str.data()), mLength(str.length()) {
101}
102
103template <>
104inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
105 mData(str), mLength(str != nullptr ? strlen(str) : 0) {
106}
107
108template <>
109inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
110 mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
111}
112
113template <typename TChar>
114inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
115 mData(str), mLength(len) {
116}
117
118template <typename TChar>
119inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
120 const BasicStringPiece<TChar>& rhs) {
121 mData = rhs.mData;
122 mLength = rhs.mLength;
123 return *this;
124}
125
126template <typename TChar>
127inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
128 mData = str;
129 mLength = len;
130 return *this;
131}
132
133
134template <typename TChar>
135inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
Adam Lesinski21efb682016-09-14 17:35:43 -0700136 if (len == npos) {
137 len = mLength - start;
138 }
139
140 if (start > mLength || start + len > mLength) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141 return BasicStringPiece<TChar>();
142 }
143 return BasicStringPiece<TChar>(mData + start, len);
144}
145
146template <typename TChar>
147inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
148 BasicStringPiece<TChar>::const_iterator begin,
149 BasicStringPiece<TChar>::const_iterator end) const {
150 return BasicStringPiece<TChar>(begin, end - begin);
151}
152
153template <typename TChar>
154inline const TChar* BasicStringPiece<TChar>::data() const {
155 return mData;
156}
157
158template <typename TChar>
159inline size_t BasicStringPiece<TChar>::length() const {
160 return mLength;
161}
162
163template <typename TChar>
164inline size_t BasicStringPiece<TChar>::size() const {
165 return mLength;
166}
167
168template <typename TChar>
169inline bool BasicStringPiece<TChar>::empty() const {
170 return mLength == 0;
171}
172
173template <typename TChar>
174inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
175 return std::basic_string<TChar>(mData, mLength);
176}
177
178template <>
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100179inline bool BasicStringPiece<char>::contains(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;
187}
188
189template <>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800190inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
191 const char nullStr = '\0';
192 const char* b1 = mData != nullptr ? mData : &nullStr;
193 const char* e1 = b1 + mLength;
194 const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
195 const char* e2 = b2 + rhs.mLength;
196
197 while (b1 < e1 && b2 < e2) {
198 const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
199 if (d) {
200 return d;
201 }
202 }
203 return static_cast<int>(mLength - rhs.mLength);
204}
205
206inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
207 android::String8 utf8(str.data(), str.size());
208 return out.write(utf8.string(), utf8.size());
209}
210
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100211template <>
212inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const {
213 if (!mData || !rhs.mData) {
214 return false;
215 }
216 if (rhs.mLength > mLength) {
217 return false;
218 }
219 return strstr16(mData, rhs.mData) != nullptr;
220}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800221
222template <>
223inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
224 const char16_t nullStr = u'\0';
225 const char16_t* b1 = mData != nullptr ? mData : &nullStr;
226 const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
227 return strzcmp16(b1, mLength, b2, rhs.mLength);
228}
229
230template <typename TChar>
231inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
232 return compare(rhs) < 0;
233}
234
235template <typename TChar>
236inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
237 return compare(rhs) > 0;
238}
239
240template <typename TChar>
241inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
242 return compare(rhs) == 0;
243}
244
245template <typename TChar>
246inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
247 return compare(rhs) != 0;
248}
249
250template <typename TChar>
251inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
252 return mData;
253}
254
255template <typename TChar>
256inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
257 return mData + mLength;
258}
259
260inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
261 return out.write(str.data(), str.size());
262}
263
264} // namespace aapt
265
Adam Lesinski90959882015-07-06 18:09:18 -0700266inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
267 android::String8 utf8(str.data(), str.size());
268 return out.write(utf8.string(), utf8.size());
269}
270
Adam Lesinski32852a52016-06-15 10:56:41 -0700271namespace std {
272
273template <typename TChar>
274struct hash<aapt::BasicStringPiece<TChar>> {
275 size_t operator()(const aapt::BasicStringPiece<TChar>& str) const {
276 uint32_t hashCode = android::JenkinsHashMixBytes(
277 0, reinterpret_cast<const uint8_t*>(str.data()), sizeof(TChar) * str.size());
278 return static_cast<size_t>(hashCode);
279 }
280};
281
282} // namespace std
283
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800284#endif // AAPT_STRING_PIECE_H