blob: 4300a67d3581d299088c4abc6d09bc90d47bfc8c [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
42 BasicStringPiece();
43 BasicStringPiece(const BasicStringPiece<TChar>& str);
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070044 BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit)
45 BasicStringPiece(const TChar* str); // NOLINT(implicit)
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080046 BasicStringPiece(const TChar* str, size_t len);
47
48 BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
49 BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
50
51 BasicStringPiece<TChar> substr(size_t start, size_t len) const;
52 BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
53 BasicStringPiece<TChar>::const_iterator end) const;
54
55 const TChar* data() const;
56 size_t length() const;
57 size_t size() const;
58 bool empty() const;
59 std::basic_string<TChar> toString() const;
60
Michael Wrightfeaf99f2016-05-06 17:16:06 +010061 bool contains(const BasicStringPiece<TChar>& rhs) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080062 int compare(const BasicStringPiece<TChar>& rhs) const;
63 bool operator<(const BasicStringPiece<TChar>& rhs) const;
64 bool operator>(const BasicStringPiece<TChar>& rhs) const;
65 bool operator==(const BasicStringPiece<TChar>& rhs) const;
66 bool operator!=(const BasicStringPiece<TChar>& rhs) const;
67
68 const_iterator begin() const;
69 const_iterator end() const;
70
71private:
72 const TChar* mData;
73 size_t mLength;
74};
75
76using StringPiece = BasicStringPiece<char>;
77using StringPiece16 = BasicStringPiece<char16_t>;
78
79//
80// BasicStringPiece implementation.
81//
82
83template <typename TChar>
84inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
85}
86
87template <typename TChar>
88inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
89 mData(str.mData), mLength(str.mLength) {
90}
91
92template <typename TChar>
93inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
94 mData(str.data()), mLength(str.length()) {
95}
96
97template <>
98inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
99 mData(str), mLength(str != nullptr ? strlen(str) : 0) {
100}
101
102template <>
103inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
104 mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
105}
106
107template <typename TChar>
108inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
109 mData(str), mLength(len) {
110}
111
112template <typename TChar>
113inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
114 const BasicStringPiece<TChar>& rhs) {
115 mData = rhs.mData;
116 mLength = rhs.mLength;
117 return *this;
118}
119
120template <typename TChar>
121inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
122 mData = str;
123 mLength = len;
124 return *this;
125}
126
127
128template <typename TChar>
129inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
130 if (start + len > mLength) {
131 return BasicStringPiece<TChar>();
132 }
133 return BasicStringPiece<TChar>(mData + start, len);
134}
135
136template <typename TChar>
137inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
138 BasicStringPiece<TChar>::const_iterator begin,
139 BasicStringPiece<TChar>::const_iterator end) const {
140 return BasicStringPiece<TChar>(begin, end - begin);
141}
142
143template <typename TChar>
144inline const TChar* BasicStringPiece<TChar>::data() const {
145 return mData;
146}
147
148template <typename TChar>
149inline size_t BasicStringPiece<TChar>::length() const {
150 return mLength;
151}
152
153template <typename TChar>
154inline size_t BasicStringPiece<TChar>::size() const {
155 return mLength;
156}
157
158template <typename TChar>
159inline bool BasicStringPiece<TChar>::empty() const {
160 return mLength == 0;
161}
162
163template <typename TChar>
164inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
165 return std::basic_string<TChar>(mData, mLength);
166}
167
168template <>
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100169inline bool BasicStringPiece<char>::contains(const BasicStringPiece<char>& rhs) const {
170 if (!mData || !rhs.mData) {
171 return false;
172 }
173 if (rhs.mLength > mLength) {
174 return false;
175 }
176 return strstr(mData, rhs.mData) != nullptr;
177}
178
179template <>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800180inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
181 const char nullStr = '\0';
182 const char* b1 = mData != nullptr ? mData : &nullStr;
183 const char* e1 = b1 + mLength;
184 const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
185 const char* e2 = b2 + rhs.mLength;
186
187 while (b1 < e1 && b2 < e2) {
188 const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
189 if (d) {
190 return d;
191 }
192 }
193 return static_cast<int>(mLength - rhs.mLength);
194}
195
196inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
197 android::String8 utf8(str.data(), str.size());
198 return out.write(utf8.string(), utf8.size());
199}
200
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100201template <>
202inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const {
203 if (!mData || !rhs.mData) {
204 return false;
205 }
206 if (rhs.mLength > mLength) {
207 return false;
208 }
209 return strstr16(mData, rhs.mData) != nullptr;
210}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800211
212template <>
213inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
214 const char16_t nullStr = u'\0';
215 const char16_t* b1 = mData != nullptr ? mData : &nullStr;
216 const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
217 return strzcmp16(b1, mLength, b2, rhs.mLength);
218}
219
220template <typename TChar>
221inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
222 return compare(rhs) < 0;
223}
224
225template <typename TChar>
226inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
227 return compare(rhs) > 0;
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 typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
242 return mData;
243}
244
245template <typename TChar>
246inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
247 return mData + mLength;
248}
249
250inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
251 return out.write(str.data(), str.size());
252}
253
254} // namespace aapt
255
Adam Lesinski90959882015-07-06 18:09:18 -0700256inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
257 android::String8 utf8(str.data(), str.size());
258 return out.write(utf8.string(), utf8.size());
259}
260
Adam Lesinski32852a52016-06-15 10:56:41 -0700261namespace std {
262
263template <typename TChar>
264struct hash<aapt::BasicStringPiece<TChar>> {
265 size_t operator()(const aapt::BasicStringPiece<TChar>& str) const {
266 uint32_t hashCode = android::JenkinsHashMixBytes(
267 0, reinterpret_cast<const uint8_t*>(str.data()), sizeof(TChar) * str.size());
268 return static_cast<size_t>(hashCode);
269 }
270};
271
272} // namespace std
273
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800274#endif // AAPT_STRING_PIECE_H