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