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