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