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