|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 // Copied from strings/stringpiece.h with modifications |
|
5 // |
|
6 // A string-like object that points to a sized piece of memory. |
|
7 // |
|
8 // Functions or methods may use const StringPiece& parameters to accept either |
|
9 // a "const char*" or a "string" value that will be implicitly converted to |
|
10 // a StringPiece. The implicit conversion means that it is often appropriate |
|
11 // to include this .h file in other files rather than forward-declaring |
|
12 // StringPiece as would be appropriate for most other Google classes. |
|
13 // |
|
14 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary |
|
15 // conversions from "const char*" to "string" and back again. |
|
16 // |
|
17 // StringPiece16 is similar to StringPiece but for base::string16 instead of |
|
18 // std::string. We do not define as large of a subset of the STL functions |
|
19 // from basic_string as in StringPiece, but this can be changed if these |
|
20 // functions (find, find_first_of, etc.) are found to be useful in this context. |
|
21 // |
|
22 |
|
23 #ifndef BASE_STRINGS_STRING_PIECE_H_ |
|
24 #define BASE_STRINGS_STRING_PIECE_H_ |
|
25 |
|
26 #include <stddef.h> |
|
27 |
|
28 #include <iosfwd> |
|
29 #include <string> |
|
30 |
|
31 #include "base/base_export.h" |
|
32 #include "base/basictypes.h" |
|
33 #include "base/containers/hash_tables.h" |
|
34 #include "base/strings/string16.h" |
|
35 |
|
36 namespace base { |
|
37 |
|
38 template <typename STRING_TYPE> class BasicStringPiece; |
|
39 typedef BasicStringPiece<std::string> StringPiece; |
|
40 typedef BasicStringPiece<string16> StringPiece16; |
|
41 |
|
42 namespace internal { |
|
43 |
|
44 // Defines the types, methods, operators, and data members common to both |
|
45 // StringPiece and StringPiece16. Do not refer to this class directly, but |
|
46 // rather to BasicStringPiece, StringPiece, or StringPiece16. |
|
47 template <typename STRING_TYPE> class StringPieceDetail { |
|
48 public: |
|
49 // standard STL container boilerplate |
|
50 typedef size_t size_type; |
|
51 typedef typename STRING_TYPE::value_type value_type; |
|
52 typedef const value_type* pointer; |
|
53 typedef const value_type& reference; |
|
54 typedef const value_type& const_reference; |
|
55 typedef ptrdiff_t difference_type; |
|
56 typedef const value_type* const_iterator; |
|
57 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
|
58 |
|
59 static const size_type npos; |
|
60 |
|
61 public: |
|
62 // We provide non-explicit singleton constructors so users can pass |
|
63 // in a "const char*" or a "string" wherever a "StringPiece" is |
|
64 // expected (likewise for char16, string16, StringPiece16). |
|
65 StringPieceDetail() : ptr_(NULL), length_(0) {} |
|
66 StringPieceDetail(const value_type* str) |
|
67 : ptr_(str), |
|
68 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} |
|
69 StringPieceDetail(const STRING_TYPE& str) |
|
70 : ptr_(str.data()), length_(str.size()) {} |
|
71 StringPieceDetail(const value_type* offset, size_type len) |
|
72 : ptr_(offset), length_(len) {} |
|
73 StringPieceDetail(const typename STRING_TYPE::const_iterator& begin, |
|
74 const typename STRING_TYPE::const_iterator& end) |
|
75 : ptr_((end > begin) ? &(*begin) : NULL), |
|
76 length_((end > begin) ? (size_type)(end - begin) : 0) {} |
|
77 |
|
78 // data() may return a pointer to a buffer with embedded NULs, and the |
|
79 // returned buffer may or may not be null terminated. Therefore it is |
|
80 // typically a mistake to pass data() to a routine that expects a NUL |
|
81 // terminated string. |
|
82 const value_type* data() const { return ptr_; } |
|
83 size_type size() const { return length_; } |
|
84 size_type length() const { return length_; } |
|
85 bool empty() const { return length_ == 0; } |
|
86 |
|
87 void clear() { |
|
88 ptr_ = NULL; |
|
89 length_ = 0; |
|
90 } |
|
91 void set(const value_type* data, size_type len) { |
|
92 ptr_ = data; |
|
93 length_ = len; |
|
94 } |
|
95 void set(const value_type* str) { |
|
96 ptr_ = str; |
|
97 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; |
|
98 } |
|
99 |
|
100 value_type operator[](size_type i) const { return ptr_[i]; } |
|
101 |
|
102 void remove_prefix(size_type n) { |
|
103 ptr_ += n; |
|
104 length_ -= n; |
|
105 } |
|
106 |
|
107 void remove_suffix(size_type n) { |
|
108 length_ -= n; |
|
109 } |
|
110 |
|
111 int compare(const BasicStringPiece<STRING_TYPE>& x) const { |
|
112 int r = wordmemcmp( |
|
113 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); |
|
114 if (r == 0) { |
|
115 if (length_ < x.length_) r = -1; |
|
116 else if (length_ > x.length_) r = +1; |
|
117 } |
|
118 return r; |
|
119 } |
|
120 |
|
121 STRING_TYPE as_string() const { |
|
122 // std::string doesn't like to take a NULL pointer even with a 0 size. |
|
123 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); |
|
124 } |
|
125 |
|
126 const_iterator begin() const { return ptr_; } |
|
127 const_iterator end() const { return ptr_ + length_; } |
|
128 const_reverse_iterator rbegin() const { |
|
129 return const_reverse_iterator(ptr_ + length_); |
|
130 } |
|
131 const_reverse_iterator rend() const { |
|
132 return const_reverse_iterator(ptr_); |
|
133 } |
|
134 |
|
135 size_type max_size() const { return length_; } |
|
136 size_type capacity() const { return length_; } |
|
137 |
|
138 static int wordmemcmp(const value_type* p, |
|
139 const value_type* p2, |
|
140 size_type N) { |
|
141 return STRING_TYPE::traits_type::compare(p, p2, N); |
|
142 } |
|
143 |
|
144 protected: |
|
145 const value_type* ptr_; |
|
146 size_type length_; |
|
147 }; |
|
148 |
|
149 template <typename STRING_TYPE> |
|
150 const typename StringPieceDetail<STRING_TYPE>::size_type |
|
151 StringPieceDetail<STRING_TYPE>::npos = |
|
152 typename StringPieceDetail<STRING_TYPE>::size_type(-1); |
|
153 |
|
154 // MSVC doesn't like complex extern templates and DLLs. |
|
155 #if !defined(COMPILER_MSVC) |
|
156 extern template class BASE_EXPORT StringPieceDetail<std::string>; |
|
157 extern template class BASE_EXPORT StringPieceDetail<string16>; |
|
158 #endif |
|
159 |
|
160 BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); |
|
161 BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); |
|
162 BASE_EXPORT StringPieceDetail<std::string>::size_type copy( |
|
163 const StringPiece& self, |
|
164 char* buf, |
|
165 StringPieceDetail<std::string>::size_type n, |
|
166 StringPieceDetail<std::string>::size_type pos); |
|
167 BASE_EXPORT StringPieceDetail<std::string>::size_type find( |
|
168 const StringPiece& self, |
|
169 const StringPiece& s, |
|
170 StringPieceDetail<std::string>::size_type pos); |
|
171 BASE_EXPORT StringPieceDetail<std::string>::size_type find( |
|
172 const StringPiece& self, |
|
173 char c, |
|
174 StringPieceDetail<std::string>::size_type pos); |
|
175 BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( |
|
176 const StringPiece& self, |
|
177 const StringPiece& s, |
|
178 StringPieceDetail<std::string>::size_type pos); |
|
179 BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( |
|
180 const StringPiece& self, |
|
181 char c, |
|
182 StringPieceDetail<std::string>::size_type pos); |
|
183 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_of( |
|
184 const StringPiece& self, |
|
185 const StringPiece& s, |
|
186 StringPieceDetail<std::string>::size_type pos); |
|
187 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( |
|
188 const StringPiece& self, |
|
189 const StringPiece& s, |
|
190 StringPieceDetail<std::string>::size_type pos); |
|
191 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( |
|
192 const StringPiece& self, |
|
193 char c, |
|
194 StringPieceDetail<std::string>::size_type pos); |
|
195 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( |
|
196 const StringPiece& self, |
|
197 const StringPiece& s, |
|
198 StringPieceDetail<std::string>::size_type pos); |
|
199 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( |
|
200 const StringPiece& self, |
|
201 char c, |
|
202 StringPieceDetail<std::string>::size_type pos); |
|
203 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( |
|
204 const StringPiece& self, |
|
205 const StringPiece& s, |
|
206 StringPieceDetail<std::string>::size_type pos); |
|
207 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( |
|
208 const StringPiece& self, |
|
209 char c, |
|
210 StringPieceDetail<std::string>::size_type pos); |
|
211 BASE_EXPORT StringPiece substr(const StringPiece& self, |
|
212 StringPieceDetail<std::string>::size_type pos, |
|
213 StringPieceDetail<std::string>::size_type n); |
|
214 } // namespace internal |
|
215 |
|
216 // Defines the template type that is instantiated as either StringPiece or |
|
217 // StringPiece16. |
|
218 template <typename STRING_TYPE> class BasicStringPiece : |
|
219 public internal::StringPieceDetail<STRING_TYPE> { |
|
220 public: |
|
221 typedef typename internal::StringPieceDetail<STRING_TYPE>::value_type |
|
222 value_type; |
|
223 typedef typename internal::StringPieceDetail<STRING_TYPE>::size_type |
|
224 size_type; |
|
225 |
|
226 BasicStringPiece() {} |
|
227 BasicStringPiece(const value_type*str) |
|
228 : internal::StringPieceDetail<STRING_TYPE>(str) {} |
|
229 BasicStringPiece(const STRING_TYPE& str) |
|
230 : internal::StringPieceDetail<STRING_TYPE>(str) {} |
|
231 BasicStringPiece(const value_type* offset, size_type len) |
|
232 : internal::StringPieceDetail<STRING_TYPE>(offset, len) {} |
|
233 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, |
|
234 const typename STRING_TYPE::const_iterator& end) |
|
235 : internal::StringPieceDetail<STRING_TYPE>(begin, end) {} |
|
236 }; |
|
237 |
|
238 // Specializes BasicStringPiece for std::string to add a few operations that |
|
239 // are not needed for string16. |
|
240 template <> class BasicStringPiece<std::string> : |
|
241 public internal::StringPieceDetail<std::string> { |
|
242 public: |
|
243 BasicStringPiece() {} |
|
244 BasicStringPiece(const char* str) |
|
245 : internal::StringPieceDetail<std::string>(str) {} |
|
246 BasicStringPiece(const std::string& str) |
|
247 : internal::StringPieceDetail<std::string>(str) {} |
|
248 BasicStringPiece(const char* offset, size_type len) |
|
249 : internal::StringPieceDetail<std::string>(offset, len) {} |
|
250 BasicStringPiece(const std::string::const_iterator& begin, |
|
251 const std::string::const_iterator& end) |
|
252 : internal::StringPieceDetail<std::string>(begin, end) {} |
|
253 |
|
254 // Prevent the following overload of set() from hiding the definitions in the |
|
255 // base class. |
|
256 using internal::StringPieceDetail<std::string>::set; |
|
257 |
|
258 void set(const void* data, size_type len) { |
|
259 ptr_ = reinterpret_cast<const value_type*>(data); |
|
260 length_ = len; |
|
261 } |
|
262 |
|
263 void CopyToString(std::string* target) const { |
|
264 internal::CopyToString(*this, target); |
|
265 } |
|
266 |
|
267 void AppendToString(std::string* target) const { |
|
268 internal::AppendToString(*this, target); |
|
269 } |
|
270 |
|
271 // Does "this" start with "x" |
|
272 bool starts_with(const BasicStringPiece& x) const { |
|
273 return ((length_ >= x.length_) && |
|
274 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); |
|
275 } |
|
276 |
|
277 // Does "this" end with "x" |
|
278 bool ends_with(const BasicStringPiece& x) const { |
|
279 return ((length_ >= x.length_) && |
|
280 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); |
|
281 } |
|
282 |
|
283 size_type copy(char* buf, size_type n, size_type pos = 0) const { |
|
284 return internal::copy(*this, buf, n, pos); |
|
285 } |
|
286 |
|
287 size_type find(const BasicStringPiece& s, size_type pos = 0) const { |
|
288 return internal::find(*this, s, pos); |
|
289 } |
|
290 |
|
291 size_type find(char c, size_type pos = 0) const { |
|
292 return internal::find(*this, c, pos); |
|
293 } |
|
294 |
|
295 size_type rfind(const BasicStringPiece& s, size_type pos = npos) const { |
|
296 return internal::rfind(*this, s, pos); |
|
297 } |
|
298 |
|
299 size_type rfind(char c, size_type pos = npos) const { |
|
300 return internal::rfind(*this, c, pos); |
|
301 } |
|
302 |
|
303 size_type find_first_of(const BasicStringPiece& s, size_type pos = 0) const { |
|
304 return internal::find_first_of(*this, s, pos); |
|
305 } |
|
306 |
|
307 size_type find_first_of(char c, size_type pos = 0) const { |
|
308 return find(c, pos); |
|
309 } |
|
310 |
|
311 size_type find_first_not_of(const BasicStringPiece& s, |
|
312 size_type pos = 0) const { |
|
313 return internal::find_first_not_of(*this, s, pos); |
|
314 } |
|
315 |
|
316 size_type find_first_not_of(char c, size_type pos = 0) const { |
|
317 return internal::find_first_not_of(*this, c, pos); |
|
318 } |
|
319 |
|
320 size_type find_last_of(const BasicStringPiece& s, |
|
321 size_type pos = npos) const { |
|
322 return internal::find_last_of(*this, s, pos); |
|
323 } |
|
324 |
|
325 size_type find_last_of(char c, size_type pos = npos) const { |
|
326 return rfind(c, pos); |
|
327 } |
|
328 |
|
329 size_type find_last_not_of(const BasicStringPiece& s, |
|
330 size_type pos = npos) const { |
|
331 return internal::find_last_not_of(*this, s, pos); |
|
332 } |
|
333 |
|
334 size_type find_last_not_of(char c, size_type pos = npos) const { |
|
335 return internal::find_last_not_of(*this, c, pos); |
|
336 } |
|
337 |
|
338 BasicStringPiece substr(size_type pos, size_type n = npos) const { |
|
339 return internal::substr(*this, pos, n); |
|
340 } |
|
341 }; |
|
342 |
|
343 // MSVC doesn't like complex extern templates and DLLs. |
|
344 #if !defined(COMPILER_MSVC) |
|
345 // We can't explicitly declare the std::string instantiation here because it was |
|
346 // already instantiated when specialized, above. Not only is it a no-op, but |
|
347 // currently it also crashes Clang (see http://crbug.com/107412). |
|
348 extern template class BASE_EXPORT BasicStringPiece<string16>; |
|
349 #endif |
|
350 |
|
351 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); |
|
352 |
|
353 inline bool operator!=(const StringPiece& x, const StringPiece& y) { |
|
354 return !(x == y); |
|
355 } |
|
356 |
|
357 inline bool operator<(const StringPiece& x, const StringPiece& y) { |
|
358 const int r = StringPiece::wordmemcmp( |
|
359 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); |
|
360 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); |
|
361 } |
|
362 |
|
363 inline bool operator>(const StringPiece& x, const StringPiece& y) { |
|
364 return y < x; |
|
365 } |
|
366 |
|
367 inline bool operator<=(const StringPiece& x, const StringPiece& y) { |
|
368 return !(x > y); |
|
369 } |
|
370 |
|
371 inline bool operator>=(const StringPiece& x, const StringPiece& y) { |
|
372 return !(x < y); |
|
373 } |
|
374 |
|
375 inline bool operator==(const StringPiece16& x, const StringPiece16& y) { |
|
376 if (x.size() != y.size()) |
|
377 return false; |
|
378 |
|
379 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; |
|
380 } |
|
381 |
|
382 inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { |
|
383 return !(x == y); |
|
384 } |
|
385 |
|
386 inline bool operator<(const StringPiece16& x, const StringPiece16& y) { |
|
387 const int r = StringPiece16::wordmemcmp( |
|
388 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); |
|
389 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); |
|
390 } |
|
391 |
|
392 inline bool operator>(const StringPiece16& x, const StringPiece16& y) { |
|
393 return y < x; |
|
394 } |
|
395 |
|
396 inline bool operator<=(const StringPiece16& x, const StringPiece16& y) { |
|
397 return !(x > y); |
|
398 } |
|
399 |
|
400 inline bool operator>=(const StringPiece16& x, const StringPiece16& y) { |
|
401 return !(x < y); |
|
402 } |
|
403 |
|
404 BASE_EXPORT std::ostream& operator<<(std::ostream& o, |
|
405 const StringPiece& piece); |
|
406 |
|
407 } // namespace base |
|
408 |
|
409 // We provide appropriate hash functions so StringPiece and StringPiece16 can |
|
410 // be used as keys in hash sets and maps. |
|
411 |
|
412 // This hash function is copied from base/containers/hash_tables.h. We don't |
|
413 // use the ones already defined for string and string16 directly because it |
|
414 // would require the string constructors to be called, which we don't want. |
|
415 #define HASH_STRING_PIECE(StringPieceType, string_piece) \ |
|
416 std::size_t result = 0; \ |
|
417 for (StringPieceType::const_iterator i = string_piece.begin(); \ |
|
418 i != string_piece.end(); ++i) \ |
|
419 result = (result * 131) + *i; \ |
|
420 return result; \ |
|
421 |
|
422 namespace BASE_HASH_NAMESPACE { |
|
423 #if defined(COMPILER_GCC) |
|
424 |
|
425 template<> |
|
426 struct hash<base::StringPiece> { |
|
427 std::size_t operator()(const base::StringPiece& sp) const { |
|
428 HASH_STRING_PIECE(base::StringPiece, sp); |
|
429 } |
|
430 }; |
|
431 template<> |
|
432 struct hash<base::StringPiece16> { |
|
433 std::size_t operator()(const base::StringPiece16& sp16) const { |
|
434 HASH_STRING_PIECE(base::StringPiece16, sp16); |
|
435 } |
|
436 }; |
|
437 |
|
438 #elif defined(COMPILER_MSVC) |
|
439 |
|
440 inline size_t hash_value(const base::StringPiece& sp) { |
|
441 HASH_STRING_PIECE(base::StringPiece, sp); |
|
442 } |
|
443 inline size_t hash_value(const base::StringPiece16& sp16) { |
|
444 HASH_STRING_PIECE(base::StringPiece16, sp16); |
|
445 } |
|
446 |
|
447 #endif // COMPILER |
|
448 |
|
449 } // namespace BASE_HASH_NAMESPACE |
|
450 |
|
451 #endif // BASE_STRINGS_STRING_PIECE_H_ |