blob: 5144b1f1fd6a483b7cac4c100a4de989e453c8bd [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 Lesinskicacb28f2016-10-19 12:18:14 -070020#include <ostream>
21#include <string>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080022
Adam Lesinskice5e56e2016-10-21 17:56:45 -070023#include "utils/JenkinsHash.h"
24#include "utils/String8.h"
25#include "utils/Unicode.h"
26
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080027namespace aapt {
28
29/**
30 * Read only wrapper around basic C strings.
31 * Prevents excessive copying.
32 *
33 * WARNING: When creating from std::basic_string<>, moving the original
34 * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
35 * BasicStringPiece<> should only be used transitively.
36 */
37template <typename TChar>
38class BasicStringPiece {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 public:
40 using const_iterator = const TChar*;
41 using difference_type = size_t;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080042
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 // End of string marker.
44 constexpr static const size_t npos = static_cast<size_t>(-1);
Adam Lesinski21efb682016-09-14 17:35:43 -070045
Adam Lesinskicacb28f2016-10-19 12:18:14 -070046 BasicStringPiece();
47 BasicStringPiece(const BasicStringPiece<TChar>& str);
48 BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit)
49 BasicStringPiece(const TChar* str); // NOLINT(implicit)
50 BasicStringPiece(const TChar* str, size_t len);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080051
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
53 BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080054
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const;
56 BasicStringPiece<TChar> substr(
57 BasicStringPiece<TChar>::const_iterator begin,
58 BasicStringPiece<TChar>::const_iterator end) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080059
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 const TChar* data() const;
61 size_t length() const;
62 size_t size() const;
63 bool empty() const;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 std::basic_string<TChar> ToString() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080065
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 bool contains(const BasicStringPiece<TChar>& rhs) const;
67 int compare(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;
71 bool operator!=(const BasicStringPiece<TChar>& rhs) const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080072
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073 const_iterator begin() const;
74 const_iterator end() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080075
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 const TChar* data_;
78 size_t length_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080079};
80
81using StringPiece = BasicStringPiece<char>;
82using StringPiece16 = BasicStringPiece<char16_t>;
83
84//
85// BasicStringPiece implementation.
86//
87
88template <typename TChar>
Adam Lesinski21efb682016-09-14 17:35:43 -070089constexpr const size_t BasicStringPiece<TChar>::npos;
90
91template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092inline BasicStringPiece<TChar>::BasicStringPiece()
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 : data_(nullptr), length_(0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080094
95template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096inline BasicStringPiece<TChar>::BasicStringPiece(
97 const BasicStringPiece<TChar>& str)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 : data_(str.data_), length_(str.length_) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080099
100template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101inline BasicStringPiece<TChar>::BasicStringPiece(
102 const std::basic_string<TChar>& str)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 : data_(str.data()), length_(str.length()) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800104
105template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700106inline BasicStringPiece<char>::BasicStringPiece(const char* str)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 : data_(str), length_(str != nullptr ? strlen(str) : 0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108
109template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111 : data_(str), length_(str != nullptr ? strlen16(str) : 0) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112
113template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 : data_(str), length_(len) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800116
117template <typename TChar>
118inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 const BasicStringPiece<TChar>& rhs) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 data_ = rhs.data_;
121 length_ = rhs.length_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700122 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800123}
124
125template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(
127 const TChar* str, size_t len) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 data_ = str;
129 length_ = len;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800131}
132
133template <typename TChar>
134inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700135 size_t start, size_t len) const {
136 if (len == npos) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700137 len = length_ - start;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700138 }
139
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700140 if (start > length_ || start + len > length_) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 return BasicStringPiece<TChar>();
142 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 return BasicStringPiece<TChar>(data_ + start, len);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144}
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);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800151}
152
153template <typename TChar>
154inline const TChar* BasicStringPiece<TChar>::data() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700155 return data_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800156}
157
158template <typename TChar>
159inline size_t BasicStringPiece<TChar>::length() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 return length_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800161}
162
163template <typename TChar>
164inline size_t BasicStringPiece<TChar>::size() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 return length_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166}
167
168template <typename TChar>
169inline bool BasicStringPiece<TChar>::empty() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700170 return length_ == 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800171}
172
173template <typename TChar>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174inline std::basic_string<TChar> BasicStringPiece<TChar>::ToString() const {
175 return std::basic_string<TChar>(data_, length_);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800176}
177
178template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179inline bool BasicStringPiece<char>::contains(
180 const BasicStringPiece<char>& rhs) const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 if (!data_ || !rhs.data_) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700182 return false;
183 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 if (rhs.length_ > length_) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700185 return false;
186 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700187 return strstr(data_, rhs.data_) != nullptr;
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100188}
189
190template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191inline int BasicStringPiece<char>::compare(
192 const BasicStringPiece<char>& rhs) const {
193 const char nullStr = '\0';
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700194 const char* b1 = data_ != nullptr ? data_ : &nullStr;
195 const char* e1 = b1 + length_;
196 const char* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr;
197 const char* e2 = b2 + rhs.length_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800198
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 while (b1 < e1 && b2 < e2) {
200 const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
201 if (d) {
202 return d;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800203 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700205 return static_cast<int>(length_ - rhs.length_);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800206}
207
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700208inline ::std::ostream& operator<<(::std::ostream& out,
209 const BasicStringPiece<char16_t>& str) {
210 android::String8 utf8(str.data(), str.size());
211 return out.write(utf8.string(), utf8.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800212}
213
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100214template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700215inline bool BasicStringPiece<char16_t>::contains(
216 const BasicStringPiece<char16_t>& rhs) const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700217 if (!data_ || !rhs.data_) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700218 return false;
219 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700220 if (rhs.length_ > length_) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221 return false;
222 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223 return strstr16(data_, rhs.data_) != nullptr;
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100224}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225
226template <>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700227inline int BasicStringPiece<char16_t>::compare(
228 const BasicStringPiece<char16_t>& rhs) const {
229 const char16_t nullStr = u'\0';
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700230 const char16_t* b1 = data_ != nullptr ? data_ : &nullStr;
231 const char16_t* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr;
232 return strzcmp16(b1, length_, b2, rhs.length_);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800233}
234
235template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700236inline bool BasicStringPiece<TChar>::operator<(
237 const BasicStringPiece<TChar>& rhs) const {
238 return compare(rhs) < 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800239}
240
241template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700242inline bool BasicStringPiece<TChar>::operator>(
243 const BasicStringPiece<TChar>& rhs) const {
244 return compare(rhs) > 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800245}
246
247template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700248inline bool BasicStringPiece<TChar>::operator==(
249 const BasicStringPiece<TChar>& rhs) const {
250 return compare(rhs) == 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800251}
252
253template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700254inline bool BasicStringPiece<TChar>::operator!=(
255 const BasicStringPiece<TChar>& rhs) const {
256 return compare(rhs) != 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800257}
258
259template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260inline typename BasicStringPiece<TChar>::const_iterator
261BasicStringPiece<TChar>::begin() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700262 return data_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263}
264
265template <typename TChar>
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700266inline typename BasicStringPiece<TChar>::const_iterator
267BasicStringPiece<TChar>::end() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700268 return data_ + length_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800269}
270
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700271inline ::std::ostream& operator<<(::std::ostream& out,
272 const BasicStringPiece<char>& str) {
273 return out.write(str.data(), str.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800274}
275
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800277
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278inline ::std::ostream& operator<<(::std::ostream& out,
279 const std::u16string& str) {
280 android::String8 utf8(str.data(), str.size());
281 return out.write(utf8.string(), utf8.size());
Adam Lesinski90959882015-07-06 18:09:18 -0700282}
283
Adam Lesinski32852a52016-06-15 10:56:41 -0700284namespace std {
285
286template <typename TChar>
287struct hash<aapt::BasicStringPiece<TChar>> {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288 size_t operator()(const aapt::BasicStringPiece<TChar>& str) const {
289 uint32_t hashCode = android::JenkinsHashMixBytes(
290 0, reinterpret_cast<const uint8_t*>(str.data()),
291 sizeof(TChar) * str.size());
292 return static_cast<size_t>(hashCode);
293 }
Adam Lesinski32852a52016-06-15 10:56:41 -0700294};
295
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700296} // namespace std
Adam Lesinski32852a52016-06-15 10:56:41 -0700297
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700298#endif // AAPT_STRING_PIECE_H