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 
     33 namespace base {
     34 
     35 template <typename STRING_TYPE> class BasicStringPiece;
     36 typedef BasicStringPiece<std::string> StringPiece;
     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 void CopyToString(const StringPiece& self, std::string* target);
     50 
     51 void AppendToString(const StringPiece& self, std::string* target);
     52 
     53 size_t copy(const StringPiece& self, char* buf, size_t n, size_t pos);
     54 
     55 size_t find(const StringPiece& self, const StringPiece& s, size_t pos);
     56 size_t find(const StringPiece& self, char c, size_t pos);
     57 
     58 size_t rfind(const StringPiece& self, const StringPiece& s, size_t pos);
     59 size_t rfind(const StringPiece& self, char c, size_t pos);
     60 
     61 size_t find_first_of(const StringPiece& self, const StringPiece& s, size_t pos);
     62 
     63 size_t find_first_not_of(const StringPiece& self,
     64                          const StringPiece& s,
     65                          size_t pos);
     66 size_t find_first_not_of(const StringPiece& self, char c, size_t pos);
     67 
     68 size_t find_last_of(const StringPiece& self, const StringPiece& s, size_t pos);
     69 size_t find_last_of(const StringPiece& self, char c, size_t pos);
     70 
     71 size_t find_last_not_of(const StringPiece& self,
     72                         const StringPiece& s,
     73                         size_t pos);
     74 size_t find_last_not_of(const StringPiece& self, char c, size_t pos);
     75 
     76 StringPiece substr(const StringPiece& self, size_t pos, size_t n);
     77 
     78 }  // namespace internal
     79 
     80 // BasicStringPiece ------------------------------------------------------------
     81 
     82 // Defines the types, methods, operators, and data members common to both
     83 // StringPiece and StringPiece16. Do not refer to this class directly, but
     84 // rather to BasicStringPiece, StringPiece, or StringPiece16.
     85 //
     86 // This is templatized by string class type rather than character type, so
     87 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
     88 template <typename STRING_TYPE> class BasicStringPiece {
     89  public:
     90   // Standard STL container boilerplate.
     91   typedef size_t size_type;
     92   typedef typename STRING_TYPE::value_type value_type;
     93   typedef const value_type* pointer;
     94   typedef const value_type& reference;
     95   typedef const value_type& const_reference;
     96   typedef ptrdiff_t difference_type;
     97   typedef const value_type* const_iterator;
     98   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     99 
    100   static const size_type npos;
    101 
    102  public:
    103   // We provide non-explicit singleton constructors so users can pass
    104   // in a "const char*" or a "string" wherever a "StringPiece" is
    105   // expected (likewise for char16, string16, StringPiece16).
    106   BasicStringPiece() : ptr_(NULL), length_(0) {}
    107   BasicStringPiece(const value_type* str)
    108       : ptr_(str),
    109         length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
    110   BasicStringPiece(const STRING_TYPE& str)
    111       : ptr_(str.data()), length_(str.size()) {}
    112   BasicStringPiece(const value_type* offset, size_type len)
    113       : ptr_(offset), length_(len) {}
    114   BasicStringPiece(const typename STRING_TYPE::const_iterator& begin,
    115                    const typename STRING_TYPE::const_iterator& end) {
    116     length_ = static_cast<size_t>(std::distance(begin, end));
    117 
    118     // The length test before assignment is to avoid dereferencing an iterator
    119     // that may point to the end() of a string.
    120     ptr_ = length_ > 0 ? &*begin : nullptr;
    121   }
    122 
    123   // data() may return a pointer to a buffer with embedded NULs, and the
    124   // returned buffer may or may not be null terminated.  Therefore it is
    125   // typically a mistake to pass data() to a routine that expects a NUL
    126   // terminated string.
    127   const value_type* data() const { return ptr_; }
    128   size_type size() const { return length_; }
    129   size_type length() const { return length_; }
    130   bool empty() const { return length_ == 0; }
    131 
    132   void clear() {
    133     ptr_ = NULL;
    134     length_ = 0;
    135   }
    136   void set(const value_type* data, size_type len) {
    137     ptr_ = data;
    138     length_ = len;
    139   }
    140   void set(const value_type* str) {
    141     ptr_ = str;
    142     length_ = str ? STRING_TYPE::traits_type::length(str) : 0;
    143   }
    144 
    145   value_type operator[](size_type i) const { return ptr_[i]; }
    146 
    147   void remove_prefix(size_type n) {
    148     ptr_ += n;
    149     length_ -= n;
    150   }
    151 
    152   void remove_suffix(size_type n) {
    153     length_ -= n;
    154   }
    155 
    156   int compare(const BasicStringPiece<STRING_TYPE>& x) const {
    157     int r = wordmemcmp(
    158         ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
    159     if (r == 0) {
    160       if (length_ < x.length_) r = -1;
    161       else if (length_ > x.length_) r = +1;
    162     }
    163     return r;
    164   }
    165 
    166   STRING_TYPE as_string() const {
    167     // std::string doesn't like to take a NULL pointer even with a 0 size.
    168     return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
    169   }
    170 
    171   const_iterator begin() const { return ptr_; }
    172   const_iterator end() const { return ptr_ + length_; }
    173   const_reverse_iterator rbegin() const {
    174     return const_reverse_iterator(ptr_ + length_);
    175   }
    176   const_reverse_iterator rend() const {
    177     return const_reverse_iterator(ptr_);
    178   }
    179 
    180   size_type max_size() const { return length_; }
    181   size_type capacity() const { return length_; }
    182 
    183   static int wordmemcmp(const value_type* p,
    184                         const value_type* p2,
    185                         size_type N) {
    186     return STRING_TYPE::traits_type::compare(p, p2, N);
    187   }
    188 
    189   // Sets the value of the given string target type to be the current string.
    190   // This saves a temporary over doing |a = b.as_string()|
    191   void CopyToString(STRING_TYPE* target) const {
    192     internal::CopyToString(*this, target);
    193   }
    194 
    195   void AppendToString(STRING_TYPE* target) const {
    196     internal::AppendToString(*this, target);
    197   }
    198 
    199   size_type copy(value_type* buf, size_type n, size_type pos = 0) const {
    200     return internal::copy(*this, buf, n, pos);
    201   }
    202 
    203   // Does "this" start with "x"
    204   bool starts_with(const BasicStringPiece& x) const {
    205     return ((this->length_ >= x.length_) &&
    206             (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0));
    207   }
    208 
    209   // Does "this" end with "x"
    210   bool ends_with(const BasicStringPiece& x) const {
    211     return ((this->length_ >= x.length_) &&
    212             (wordmemcmp(this->ptr_ + (this->length_-x.length_),
    213                         x.ptr_, x.length_) == 0));
    214   }
    215 
    216   // find: Search for a character or substring at a given offset.
    217   size_type find(const BasicStringPiece<STRING_TYPE>& s,
    218                  size_type pos = 0) const {
    219     return internal::find(*this, s, pos);
    220   }
    221   size_type find(value_type c, size_type pos = 0) const {
    222     return internal::find(*this, c, pos);
    223   }
    224 
    225   // rfind: Reverse find.
    226   size_type rfind(const BasicStringPiece& s,
    227                   size_type pos = BasicStringPiece::npos) const {
    228     return internal::rfind(*this, s, pos);
    229   }
    230   size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const {
    231     return internal::rfind(*this, c, pos);
    232   }
    233 
    234   // find_first_of: Find the first occurence of one of a set of characters.
    235   size_type find_first_of(const BasicStringPiece& s,
    236                           size_type pos = 0) const {
    237     return internal::find_first_of(*this, s, pos);
    238   }
    239   size_type find_first_of(value_type c, size_type pos = 0) const {
    240     return find(c, pos);
    241   }
    242 
    243   // find_first_not_of: Find the first occurence not of a set of characters.
    244   size_type find_first_not_of(const BasicStringPiece& s,
    245                               size_type pos = 0) const {
    246     return internal::find_first_not_of(*this, s, pos);
    247   }
    248   size_type find_first_not_of(value_type c, size_type pos = 0) const {
    249     return internal::find_first_not_of(*this, c, pos);
    250   }
    251 
    252   // find_last_of: Find the last occurence of one of a set of characters.
    253   size_type find_last_of(const BasicStringPiece& s,
    254                          size_type pos = BasicStringPiece::npos) const {
    255     return internal::find_last_of(*this, s, pos);
    256   }
    257   size_type find_last_of(value_type c,
    258                          size_type pos = BasicStringPiece::npos) const {
    259     return rfind(c, pos);
    260   }
    261 
    262   // find_last_not_of: Find the last occurence not of a set of characters.
    263   size_type find_last_not_of(const BasicStringPiece& s,
    264                              size_type pos = BasicStringPiece::npos) const {
    265     return internal::find_last_not_of(*this, s, pos);
    266   }
    267   size_type find_last_not_of(value_type c,
    268                              size_type pos = BasicStringPiece::npos) const {
    269     return internal::find_last_not_of(*this, c, pos);
    270   }
    271 
    272   // substr.
    273   BasicStringPiece substr(size_type pos,
    274                           size_type n = BasicStringPiece::npos) const {
    275     return internal::substr(*this, pos, n);
    276   }
    277 
    278  protected:
    279   const value_type* ptr_;
    280   size_type     length_;
    281 };
    282 
    283 template <typename STRING_TYPE>
    284 const typename BasicStringPiece<STRING_TYPE>::size_type
    285 BasicStringPiece<STRING_TYPE>::npos =
    286     typename BasicStringPiece<STRING_TYPE>::size_type(-1);
    287 
    288 // MSVC doesn't like complex extern templates and DLLs.
    289 #if !defined(COMPILER_MSVC)
    290 extern template class BASE_EXPORT BasicStringPiece<std::string>;
    291 #endif
    292 
    293 // StingPiece operators --------------------------------------------------------
    294 
    295 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
    296 
    297 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
    298   return !(x == y);
    299 }
    300 
    301 inline bool operator<(const StringPiece& x, const StringPiece& y) {
    302   const int r = StringPiece::wordmemcmp(
    303       x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
    304   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
    305 }
    306 
    307 inline bool operator>(const StringPiece& x, const StringPiece& y) {
    308   return y < x;
    309 }
    310 
    311 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
    312   return !(x > y);
    313 }
    314 
    315 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
    316   return !(x < y);
    317 }
    318 
    319 std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
    320 
    321 }  // namespace base
    322 
    323 #endif  // BASE_STRINGS_STRING_PIECE_H_
    324