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/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).
    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.
    184   constexpr BasicStringPiece(const value_type* str)
    185       : ptr_(str), length_(!str ? 0 : CharTraits<value_type>::length(str)) {}
    186   BasicStringPiece(const STRING_TYPE& str)
    187       : ptr_(str.data()), length_(str.size()) {}
    188   constexpr BasicStringPiece(const value_type* offset, size_type len)
    189       : ptr_(offset), length_(len) {}
    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.
    208   constexpr const value_type* data() const { return ptr_; }
    209   constexpr size_type size() const { return length_; }
    210   constexpr size_type length() const { return length_; }
    211   bool empty() const { return length_ == 0; }
    212 
    213   void clear() {
    214     ptr_ = NULL;
    215     length_ = 0;
    216   }
    217   void set(const value_type* data, size_type len) {
    218     ptr_ = data;
    219     length_ = len;
    220   }
    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 
    231   value_type front() const {
    232     CHECK_NE(0UL, length_);
    233     return ptr_[0];
    234   }
    235 
    236   value_type back() const {
    237     CHECK_NE(0UL, length_);
    238     return ptr_[length_ - 1];
    239   }
    240 
    241   constexpr void remove_prefix(size_type n) {
    242     CHECK(n <= length_);
    243     ptr_ += n;
    244     length_ -= n;
    245   }
    246 
    247   constexpr void remove_suffix(size_type n) {
    248     CHECK(n <= length_);
    249     length_ -= n;
    250   }
    251 
    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.
    263   explicit operator STRING_TYPE() const { return as_string(); }
    264 
    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 
    270   const_iterator begin() const { return ptr_; }
    271   const_iterator end() const { return ptr_ + length_; }
    272   const_reverse_iterator rbegin() const {
    273     return const_reverse_iterator(ptr_ + length_);
    274   }
    275   const_reverse_iterator rend() const {
    276     return const_reverse_iterator(ptr_);
    277   }
    278 
    279   size_type max_size() const { return length_; }
    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()|
    284   void CopyToString(STRING_TYPE* target) const {
    285     internal::CopyToString(*this, target);
    286   }
    287 
    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"
    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"
    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 {
    466   std::size_t operator()(const StringPiece& sp) const {
    467     HASH_STRING_PIECE(StringPiece, sp);
    468   }
    469 };
    470 struct StringPiece16Hash {
    471   std::size_t operator()(const StringPiece16& sp16) const {
    472     HASH_STRING_PIECE(StringPiece16, sp16);
    473   }
    474 };
    475 struct WStringPieceHash {
    476   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