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/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).
    182   BasicStringPiece() : ptr_(NULL), length_(0) {}
    183   BasicStringPiece(const value_type* str)
    184       : ptr_(str),
    185         length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
    186   BasicStringPiece(const STRING_TYPE& str)
    187       : ptr_(str.data()), length_(str.size()) {}
    188   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   const value_type* data() const { return ptr_; }
    209   size_type size() const { return length_; }
    210   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   value_type operator[](size_type i) const { return ptr_[i]; }
    227 
    228   void remove_prefix(size_type n) {
    229     ptr_ += n;
    230     length_ -= n;
    231   }
    232 
    233   void remove_suffix(size_type n) {
    234     length_ -= n;
    235   }
    236 
    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 
    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 
    252   const_iterator begin() const { return ptr_; }
    253   const_iterator end() const { return ptr_ + length_; }
    254   const_reverse_iterator rbegin() const {
    255     return const_reverse_iterator(ptr_ + length_);
    256   }
    257   const_reverse_iterator rend() const {
    258     return const_reverse_iterator(ptr_);
    259   }
    260 
    261   size_type max_size() const { return length_; }
    262   size_type capacity() const { return length_; }
    263 
    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()|
    272   void CopyToString(STRING_TYPE* target) const {
    273     internal::CopyToString(*this, target);
    274   }
    275 
    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"
    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"
    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