• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
22 #include <utils/String8.h>
23 #include <utils/Unicode.h>
24 
25 namespace aapt {
26 
27 /**
28  * Read only wrapper around basic C strings.
29  * Prevents excessive copying.
30  *
31  * WARNING: When creating from std::basic_string<>, moving the original
32  * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
33  * BasicStringPiece<> should only be used transitively.
34  */
35 template <typename TChar>
36 class BasicStringPiece {
37 public:
38     using const_iterator = const TChar*;
39     using difference_type = size_t;
40 
41     BasicStringPiece();
42     BasicStringPiece(const BasicStringPiece<TChar>& str);
43     BasicStringPiece(const std::basic_string<TChar>& str);
44     BasicStringPiece(const TChar* str);
45     BasicStringPiece(const TChar* str, size_t len);
46 
47     BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
48     BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
49 
50     BasicStringPiece<TChar> substr(size_t start, size_t len) const;
51     BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
52                                    BasicStringPiece<TChar>::const_iterator end) const;
53 
54     const TChar* data() const;
55     size_t length() const;
56     size_t size() const;
57     bool empty() const;
58     std::basic_string<TChar> toString() const;
59 
60     bool contains(const BasicStringPiece<TChar>& rhs) const;
61     int compare(const BasicStringPiece<TChar>& rhs) const;
62     bool operator<(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 
67     const_iterator begin() const;
68     const_iterator end() const;
69 
70 private:
71     const TChar* mData;
72     size_t mLength;
73 };
74 
75 using StringPiece = BasicStringPiece<char>;
76 using StringPiece16 = BasicStringPiece<char16_t>;
77 
78 //
79 // BasicStringPiece implementation.
80 //
81 
82 template <typename TChar>
BasicStringPiece()83 inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
84 }
85 
86 template <typename TChar>
BasicStringPiece(const BasicStringPiece<TChar> & str)87 inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
88         mData(str.mData), mLength(str.mLength) {
89 }
90 
91 template <typename TChar>
BasicStringPiece(const std::basic_string<TChar> & str)92 inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
93         mData(str.data()), mLength(str.length()) {
94 }
95 
96 template <>
BasicStringPiece(const char * str)97 inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
98         mData(str), mLength(str != nullptr ? strlen(str) : 0) {
99 }
100 
101 template <>
BasicStringPiece(const char16_t * str)102 inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
103         mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
104 }
105 
106 template <typename TChar>
BasicStringPiece(const TChar * str,size_t len)107 inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
108         mData(str), mLength(len) {
109 }
110 
111 template <typename TChar>
112 inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
113         const BasicStringPiece<TChar>& rhs) {
114     mData = rhs.mData;
115     mLength = rhs.mLength;
116     return *this;
117 }
118 
119 template <typename TChar>
assign(const TChar * str,size_t len)120 inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
121     mData = str;
122     mLength = len;
123     return *this;
124 }
125 
126 
127 template <typename TChar>
substr(size_t start,size_t len)128 inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
129     if (start + len > mLength) {
130         return BasicStringPiece<TChar>();
131     }
132     return BasicStringPiece<TChar>(mData + start, len);
133 }
134 
135 template <typename TChar>
substr(BasicStringPiece<TChar>::const_iterator begin,BasicStringPiece<TChar>::const_iterator end)136 inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
137         BasicStringPiece<TChar>::const_iterator begin,
138         BasicStringPiece<TChar>::const_iterator end) const {
139     return BasicStringPiece<TChar>(begin, end - begin);
140 }
141 
142 template <typename TChar>
data()143 inline const TChar* BasicStringPiece<TChar>::data() const {
144     return mData;
145 }
146 
147 template <typename TChar>
length()148 inline size_t BasicStringPiece<TChar>::length() const {
149     return mLength;
150 }
151 
152 template <typename TChar>
size()153 inline size_t BasicStringPiece<TChar>::size() const {
154     return mLength;
155 }
156 
157 template <typename TChar>
empty()158 inline bool BasicStringPiece<TChar>::empty() const {
159     return mLength == 0;
160 }
161 
162 template <typename TChar>
toString()163 inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
164     return std::basic_string<TChar>(mData, mLength);
165 }
166 
167 template <>
contains(const BasicStringPiece<char> & rhs)168 inline bool BasicStringPiece<char>::contains(const BasicStringPiece<char>& rhs) const {
169     if (!mData || !rhs.mData) {
170         return false;
171     }
172     if (rhs.mLength > mLength) {
173         return false;
174     }
175     return strstr(mData, rhs.mData) != nullptr;
176 }
177 
178 template <>
compare(const BasicStringPiece<char> & rhs)179 inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
180     const char nullStr = '\0';
181     const char* b1 = mData != nullptr ? mData : &nullStr;
182     const char* e1 = b1 + mLength;
183     const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
184     const char* e2 = b2 + rhs.mLength;
185 
186     while (b1 < e1 && b2 < e2) {
187         const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
188         if (d) {
189             return d;
190         }
191     }
192     return static_cast<int>(mLength - rhs.mLength);
193 }
194 
195 inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
196     android::String8 utf8(str.data(), str.size());
197     return out.write(utf8.string(), utf8.size());
198 }
199 
200 template <>
contains(const BasicStringPiece<char16_t> & rhs)201 inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const {
202     if (!mData || !rhs.mData) {
203         return false;
204     }
205     if (rhs.mLength > mLength) {
206         return false;
207     }
208     return strstr16(mData, rhs.mData) != nullptr;
209 }
210 
211 template <>
compare(const BasicStringPiece<char16_t> & rhs)212 inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
213     const char16_t nullStr = u'\0';
214     const char16_t* b1 = mData != nullptr ? mData : &nullStr;
215     const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
216     return strzcmp16(b1, mLength, b2, rhs.mLength);
217 }
218 
219 template <typename TChar>
220 inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
221     return compare(rhs) < 0;
222 }
223 
224 template <typename TChar>
225 inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
226     return compare(rhs) > 0;
227 }
228 
229 template <typename TChar>
230 inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
231     return compare(rhs) == 0;
232 }
233 
234 template <typename TChar>
235 inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
236     return compare(rhs) != 0;
237 }
238 
239 template <typename TChar>
begin()240 inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
241     return mData;
242 }
243 
244 template <typename TChar>
end()245 inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
246     return mData + mLength;
247 }
248 
249 inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
250     return out.write(str.data(), str.size());
251 }
252 
253 } // namespace aapt
254 
255 inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
256     android::String8 utf8(str.data(), str.size());
257     return out.write(utf8.string(), utf8.size());
258 }
259 
260 #endif // AAPT_STRING_PIECE_H
261