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