• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // internal --------------------------------------------------------------------
43 
44 // Many of the StringPiece functions use different implementations for the
45 // 8-bit and 16-bit versions, and we don't want lots of template expansions in
46 // this (very common) header that will slow down compilation.
47 //
48 // So here we define overloaded functions called by the StringPiece template.
49 // For those that share an implementation, the two versions will expand to a
50 // template internal to the .cc file.
51 namespace internal {
52 
53 BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target);
54 BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target);
55 
56 BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target);
57 BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target);
58 
59 BASE_EXPORT size_t copy(const StringPiece& self,
60                         char* buf,
61                         size_t n,
62                         size_t pos);
63 BASE_EXPORT size_t copy(const StringPiece16& self,
64                         char16* buf,
65                         size_t n,
66                         size_t pos);
67 
68 BASE_EXPORT size_t find(const StringPiece& self,
69                         const StringPiece& s,
70                         size_t pos);
71 BASE_EXPORT size_t find(const StringPiece16& self,
72                         const StringPiece16& s,
73                         size_t pos);
74 BASE_EXPORT size_t find(const StringPiece& self,
75                         char c,
76                         size_t pos);
77 BASE_EXPORT size_t find(const StringPiece16& self,
78                         char16 c,
79                         size_t pos);
80 
81 BASE_EXPORT size_t rfind(const StringPiece& self,
82                          const StringPiece& s,
83                          size_t pos);
84 BASE_EXPORT size_t rfind(const StringPiece16& self,
85                          const StringPiece16& s,
86                          size_t pos);
87 BASE_EXPORT size_t rfind(const StringPiece& self,
88                          char c,
89                          size_t pos);
90 BASE_EXPORT size_t rfind(const StringPiece16& self,
91                          char16 c,
92                          size_t pos);
93 
94 BASE_EXPORT size_t find_first_of(const StringPiece& self,
95                                  const StringPiece& s,
96                                  size_t pos);
97 BASE_EXPORT size_t find_first_of(const StringPiece16& self,
98                                  const StringPiece16& s,
99                                  size_t pos);
100 
101 BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
102                                      const StringPiece& s,
103                                      size_t pos);
104 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
105                                      const StringPiece16& s,
106                                      size_t pos);
107 BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
108                                      char c,
109                                      size_t pos);
110 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
111                                      char16 c,
112                                      size_t pos);
113 
114 BASE_EXPORT size_t find_last_of(const StringPiece& self,
115                                 const StringPiece& s,
116                                 size_t pos);
117 BASE_EXPORT size_t find_last_of(const StringPiece16& self,
118                                 const StringPiece16& s,
119                                 size_t pos);
120 BASE_EXPORT size_t find_last_of(const StringPiece& self,
121                                 char c,
122                                 size_t pos);
123 BASE_EXPORT size_t find_last_of(const StringPiece16& self,
124                                 char16 c,
125                                 size_t pos);
126 
127 BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
128                                     const StringPiece& s,
129                                     size_t pos);
130 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
131                                     const StringPiece16& s,
132                                     size_t pos);
133 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
134                                     char16 c,
135                                     size_t pos);
136 BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
137                                     char c,
138                                     size_t pos);
139 
140 BASE_EXPORT StringPiece substr(const StringPiece& self,
141                                size_t pos,
142                                size_t n);
143 BASE_EXPORT StringPiece16 substr(const StringPiece16& self,
144                                  size_t pos,
145                                  size_t n);
146 
147 }  // namespace internal
148 
149 // BasicStringPiece ------------------------------------------------------------
150 
151 // Defines the types, methods, operators, and data members common to both
152 // StringPiece and StringPiece16. Do not refer to this class directly, but
153 // rather to BasicStringPiece, StringPiece, or StringPiece16.
154 //
155 // This is templatized by string class type rather than character type, so
156 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
157 template <typename STRING_TYPE> class BasicStringPiece {
158  public:
159   // Standard STL container boilerplate.
160   typedef size_t size_type;
161   typedef typename STRING_TYPE::value_type value_type;
162   typedef const value_type* pointer;
163   typedef const value_type& reference;
164   typedef const value_type& const_reference;
165   typedef ptrdiff_t difference_type;
166   typedef const value_type* const_iterator;
167   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
168 
169   static const size_type npos;
170 
171  public:
172   // We provide non-explicit singleton constructors so users can pass
173   // in a "const char*" or a "string" wherever a "StringPiece" is
174   // expected (likewise for char16, string16, StringPiece16).
BasicStringPiece()175   BasicStringPiece() : ptr_(NULL), length_(0) {}
BasicStringPiece(const value_type * str)176   BasicStringPiece(const value_type* str)
177       : ptr_(str),
178         length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
BasicStringPiece(const STRING_TYPE & str)179   BasicStringPiece(const STRING_TYPE& str)
180       : ptr_(str.data()), length_(str.size()) {}
BasicStringPiece(const value_type * offset,size_type len)181   BasicStringPiece(const value_type* offset, size_type len)
182       : ptr_(offset), length_(len) {}
BasicStringPiece(const typename STRING_TYPE::const_iterator & begin,const typename STRING_TYPE::const_iterator & end)183   BasicStringPiece(const typename STRING_TYPE::const_iterator& begin,
184                     const typename STRING_TYPE::const_iterator& end)
185       : ptr_((end > begin) ? &(*begin) : NULL),
186         length_((end > begin) ? (size_type)(end - begin) : 0) {}
187 
188   // data() may return a pointer to a buffer with embedded NULs, and the
189   // returned buffer may or may not be null terminated.  Therefore it is
190   // typically a mistake to pass data() to a routine that expects a NUL
191   // terminated string.
data()192   const value_type* data() const { return ptr_; }
size()193   size_type size() const { return length_; }
length()194   size_type length() const { return length_; }
empty()195   bool empty() const { return length_ == 0; }
196 
clear()197   void clear() {
198     ptr_ = NULL;
199     length_ = 0;
200   }
set(const value_type * data,size_type len)201   void set(const value_type* data, size_type len) {
202     ptr_ = data;
203     length_ = len;
204   }
set(const value_type * str)205   void set(const value_type* str) {
206     ptr_ = str;
207     length_ = str ? STRING_TYPE::traits_type::length(str) : 0;
208   }
209 
210   value_type operator[](size_type i) const { return ptr_[i]; }
211 
remove_prefix(size_type n)212   void remove_prefix(size_type n) {
213     ptr_ += n;
214     length_ -= n;
215   }
216 
remove_suffix(size_type n)217   void remove_suffix(size_type n) {
218     length_ -= n;
219   }
220 
compare(const BasicStringPiece<STRING_TYPE> & x)221   int compare(const BasicStringPiece<STRING_TYPE>& x) const {
222     int r = wordmemcmp(
223         ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
224     if (r == 0) {
225       if (length_ < x.length_) r = -1;
226       else if (length_ > x.length_) r = +1;
227     }
228     return r;
229   }
230 
as_string()231   STRING_TYPE as_string() const {
232     // std::string doesn't like to take a NULL pointer even with a 0 size.
233     return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
234   }
235 
begin()236   const_iterator begin() const { return ptr_; }
end()237   const_iterator end() const { return ptr_ + length_; }
rbegin()238   const_reverse_iterator rbegin() const {
239     return const_reverse_iterator(ptr_ + length_);
240   }
rend()241   const_reverse_iterator rend() const {
242     return const_reverse_iterator(ptr_);
243   }
244 
max_size()245   size_type max_size() const { return length_; }
capacity()246   size_type capacity() const { return length_; }
247 
wordmemcmp(const value_type * p,const value_type * p2,size_type N)248   static int wordmemcmp(const value_type* p,
249                         const value_type* p2,
250                         size_type N) {
251     return STRING_TYPE::traits_type::compare(p, p2, N);
252   }
253 
254   // Sets the value of the given string target type to be the current string.
255   // This saves a temporary over doing |a = b.as_string()|
CopyToString(STRING_TYPE * target)256   void CopyToString(STRING_TYPE* target) const {
257     internal::CopyToString(*this, target);
258   }
259 
AppendToString(STRING_TYPE * target)260   void AppendToString(STRING_TYPE* target) const {
261     internal::AppendToString(*this, target);
262   }
263 
264   size_type copy(value_type* buf, size_type n, size_type pos = 0) const {
265     return internal::copy(*this, buf, n, pos);
266   }
267 
268   // Does "this" start with "x"
starts_with(const BasicStringPiece & x)269   bool starts_with(const BasicStringPiece& x) const {
270     return ((this->length_ >= x.length_) &&
271             (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0));
272   }
273 
274   // Does "this" end with "x"
ends_with(const BasicStringPiece & x)275   bool ends_with(const BasicStringPiece& x) const {
276     return ((this->length_ >= x.length_) &&
277             (wordmemcmp(this->ptr_ + (this->length_-x.length_),
278                         x.ptr_, x.length_) == 0));
279   }
280 
281   // find: Search for a character or substring at a given offset.
282   size_type find(const BasicStringPiece<STRING_TYPE>& s,
283                  size_type pos = 0) const {
284     return internal::find(*this, s, pos);
285   }
286   size_type find(value_type c, size_type pos = 0) const {
287     return internal::find(*this, c, pos);
288   }
289 
290   // rfind: Reverse find.
291   size_type rfind(const BasicStringPiece& s,
292                   size_type pos = BasicStringPiece::npos) const {
293     return internal::rfind(*this, s, pos);
294   }
295   size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const {
296     return internal::rfind(*this, c, pos);
297   }
298 
299   // find_first_of: Find the first occurence of one of a set of characters.
300   size_type find_first_of(const BasicStringPiece& s,
301                           size_type pos = 0) const {
302     return internal::find_first_of(*this, s, pos);
303   }
304   size_type find_first_of(value_type c, size_type pos = 0) const {
305     return find(c, pos);
306   }
307 
308   // find_first_not_of: Find the first occurence not of a set of characters.
309   size_type find_first_not_of(const BasicStringPiece& s,
310                               size_type pos = 0) const {
311     return internal::find_first_not_of(*this, s, pos);
312   }
313   size_type find_first_not_of(value_type c, size_type pos = 0) const {
314     return internal::find_first_not_of(*this, c, pos);
315   }
316 
317   // find_last_of: Find the last occurence of one of a set of characters.
318   size_type find_last_of(const BasicStringPiece& s,
319                          size_type pos = BasicStringPiece::npos) const {
320     return internal::find_last_of(*this, s, pos);
321   }
322   size_type find_last_of(value_type c,
323                          size_type pos = BasicStringPiece::npos) const {
324     return rfind(c, pos);
325   }
326 
327   // find_last_not_of: Find the last occurence not of a set of characters.
328   size_type find_last_not_of(const BasicStringPiece& s,
329                              size_type pos = BasicStringPiece::npos) const {
330     return internal::find_last_not_of(*this, s, pos);
331   }
332   size_type find_last_not_of(value_type c,
333                              size_type pos = BasicStringPiece::npos) const {
334     return internal::find_last_not_of(*this, c, pos);
335   }
336 
337   // substr.
338   BasicStringPiece substr(size_type pos,
339                           size_type n = BasicStringPiece::npos) const {
340     return internal::substr(*this, pos, n);
341   }
342 
343  protected:
344   const value_type* ptr_;
345   size_type     length_;
346 };
347 
348 template <typename STRING_TYPE>
349 const typename BasicStringPiece<STRING_TYPE>::size_type
350 BasicStringPiece<STRING_TYPE>::npos =
351     typename BasicStringPiece<STRING_TYPE>::size_type(-1);
352 
353 // MSVC doesn't like complex extern templates and DLLs.
354 #if !defined(COMPILER_MSVC)
355 extern template class BASE_EXPORT BasicStringPiece<std::string>;
356 extern template class BASE_EXPORT BasicStringPiece<string16>;
357 #endif
358 
359 // StingPiece operators --------------------------------------------------------
360 
361 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
362 
363 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
364   return !(x == y);
365 }
366 
367 inline bool operator<(const StringPiece& x, const StringPiece& y) {
368   const int r = StringPiece::wordmemcmp(
369       x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
370   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
371 }
372 
373 inline bool operator>(const StringPiece& x, const StringPiece& y) {
374   return y < x;
375 }
376 
377 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
378   return !(x > y);
379 }
380 
381 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
382   return !(x < y);
383 }
384 
385 // StringPiece16 operators -----------------------------------------------------
386 
387 inline bool operator==(const StringPiece16& x, const StringPiece16& y) {
388   if (x.size() != y.size())
389     return false;
390 
391   return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0;
392 }
393 
394 inline bool operator!=(const StringPiece16& x, const StringPiece16& y) {
395   return !(x == y);
396 }
397 
398 inline bool operator<(const StringPiece16& x, const StringPiece16& y) {
399   const int r = StringPiece16::wordmemcmp(
400       x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
401   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
402 }
403 
404 inline bool operator>(const StringPiece16& x, const StringPiece16& y) {
405   return y < x;
406 }
407 
408 inline bool operator<=(const StringPiece16& x, const StringPiece16& y) {
409   return !(x > y);
410 }
411 
412 inline bool operator>=(const StringPiece16& x, const StringPiece16& y) {
413   return !(x < y);
414 }
415 
416 BASE_EXPORT std::ostream& operator<<(std::ostream& o,
417                                      const StringPiece& piece);
418 
419 }  // namespace base
420 
421 // Hashing ---------------------------------------------------------------------
422 
423 // We provide appropriate hash functions so StringPiece and StringPiece16 can
424 // be used as keys in hash sets and maps.
425 
426 // This hash function is copied from base/containers/hash_tables.h. We don't
427 // use the ones already defined for string and string16 directly because it
428 // would require the string constructors to be called, which we don't want.
429 #define HASH_STRING_PIECE(StringPieceType, string_piece)                \
430   std::size_t result = 0;                                               \
431   for (StringPieceType::const_iterator i = string_piece.begin();        \
432        i != string_piece.end(); ++i)                                    \
433     result = (result * 131) + *i;                                       \
434   return result;                                                        \
435 
436 namespace BASE_HASH_NAMESPACE {
437 #if defined(COMPILER_GCC)
438 
439 template<>
440 struct hash<base::StringPiece> {
441   std::size_t operator()(const base::StringPiece& sp) const {
442     HASH_STRING_PIECE(base::StringPiece, sp);
443   }
444 };
445 template<>
446 struct hash<base::StringPiece16> {
447   std::size_t operator()(const base::StringPiece16& sp16) const {
448     HASH_STRING_PIECE(base::StringPiece16, sp16);
449   }
450 };
451 
452 #elif defined(COMPILER_MSVC)
453 
454 inline size_t hash_value(const base::StringPiece& sp) {
455   HASH_STRING_PIECE(base::StringPiece, sp);
456 }
457 inline size_t hash_value(const base::StringPiece16& sp16) {
458   HASH_STRING_PIECE(base::StringPiece16, sp16);
459 }
460 
461 #endif  // COMPILER
462 
463 }  // namespace BASE_HASH_NAMESPACE
464 
465 #endif  // BASE_STRINGS_STRING_PIECE_H_
466