Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 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 
     18 #ifndef BASE_STRING_PIECE_H_
     19 #define BASE_STRING_PIECE_H_
     20 
     21 #include <algorithm>
     22 #include <iosfwd>
     23 #include <string>
     24 
     25 #include "base/basictypes.h"
     26 
     27 namespace base {
     28 
     29 class StringPiece {
     30  public:
     31   typedef size_t size_type;
     32 
     33  private:
     34   const char*   ptr_;
     35   size_type     length_;
     36 
     37  public:
     38   // We provide non-explicit singleton constructors so users can pass
     39   // in a "const char*" or a "string" wherever a "StringPiece" is
     40   // expected.
     41   StringPiece() : ptr_(NULL), length_(0) { }
     42   StringPiece(const char* str)
     43     : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }
     44   StringPiece(const std::string& str)
     45     : ptr_(str.data()), length_(str.size()) { }
     46   StringPiece(const char* offset, size_type len)
     47     : ptr_(offset), length_(len) { }
     48 
     49   // data() may return a pointer to a buffer with embedded NULs, and the
     50   // returned buffer may or may not be null terminated.  Therefore it is
     51   // typically a mistake to pass data() to a routine that expects a NUL
     52   // terminated string.
     53   const char* data() const { return ptr_; }
     54   size_type size() const { return length_; }
     55   size_type length() const { return length_; }
     56   bool empty() const { return length_ == 0; }
     57 
     58   void clear() {
     59     ptr_ = NULL;
     60     length_ = 0;
     61   }
     62   void set(const char* data, size_type len) {
     63     ptr_ = data;
     64     length_ = len;
     65   }
     66   void set(const char* str) {
     67     ptr_ = str;
     68     length_ = str ? strlen(str) : 0;
     69   }
     70   void set(const void* data, size_type len) {
     71     ptr_ = reinterpret_cast<const char*>(data);
     72     length_ = len;
     73   }
     74 
     75   char operator[](size_type i) const { return ptr_[i]; }
     76 
     77   void remove_prefix(size_type n) {
     78     ptr_ += n;
     79     length_ -= n;
     80   }
     81 
     82   void remove_suffix(size_type n) {
     83     length_ -= n;
     84   }
     85 
     86   int compare(const StringPiece& x) const {
     87     int r = wordmemcmp(ptr_, x.ptr_, std::min(length_, x.length_));
     88     if (r == 0) {
     89       if (length_ < x.length_) r = -1;
     90       else if (length_ > x.length_) r = +1;
     91     }
     92     return r;
     93   }
     94 
     95   std::string as_string() const {
     96     // std::string doesn't like to take a NULL pointer even with a 0 size.
     97     return std::string(!empty() ? data() : "", size());
     98   }
     99 
    100   void CopyToString(std::string* target) const;
    101   void AppendToString(std::string* target) const;
    102 
    103   // Does "this" start with "x"
    104   bool starts_with(const StringPiece& x) const {
    105     return ((length_ >= x.length_) &&
    106             (wordmemcmp(ptr_, x.ptr_, x.length_) == 0));
    107   }
    108 
    109   // Does "this" end with "x"
    110   bool ends_with(const StringPiece& x) const {
    111     return ((length_ >= x.length_) &&
    112             (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
    113   }
    114 
    115   // standard STL container boilerplate
    116   typedef char value_type;
    117   typedef const char* pointer;
    118   typedef const char& reference;
    119   typedef const char& const_reference;
    120   typedef ptrdiff_t difference_type;
    121   static const size_type npos;
    122   typedef const char* const_iterator;
    123   typedef const char* iterator;
    124   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    125   typedef std::reverse_iterator<iterator> reverse_iterator;
    126   iterator begin() const { return ptr_; }
    127   iterator end() const { return ptr_ + length_; }
    128   const_reverse_iterator rbegin() const {
    129     return const_reverse_iterator(ptr_ + length_);
    130   }
    131   const_reverse_iterator rend() const {
    132     return const_reverse_iterator(ptr_);
    133   }
    134 
    135   size_type max_size() const { return length_; }
    136   size_type capacity() const { return length_; }
    137 
    138   size_type copy(char* buf, size_type n, size_type pos = 0) const;
    139 
    140   size_type find(const StringPiece& s, size_type pos = 0) const;
    141   size_type find(char c, size_type pos = 0) const;
    142   size_type rfind(const StringPiece& s, size_type pos = npos) const;
    143   size_type rfind(char c, size_type pos = npos) const;
    144 
    145   size_type find_first_of(const StringPiece& s, size_type pos = 0) const;
    146   size_type find_first_of(char c, size_type pos = 0) const {
    147     return find(c, pos);
    148   }
    149   size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const;
    150   size_type find_first_not_of(char c, size_type pos = 0) const;
    151   size_type find_last_of(const StringPiece& s, size_type pos = npos) const;
    152   size_type find_last_of(char c, size_type pos = npos) const {
    153     return rfind(c, pos);
    154   }
    155   size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const;
    156   size_type find_last_not_of(char c, size_type pos = npos) const;
    157 
    158   StringPiece substr(size_type pos, size_type n = npos) const;
    159 
    160   static int wordmemcmp(const char* p, const char* p2, size_type N) {
    161     return memcmp(p, p2, N);
    162   }
    163 };
    164 
    165 bool operator==(const StringPiece& x, const StringPiece& y);
    166 
    167 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
    168   return !(x == y);
    169 }
    170 
    171 inline bool operator<(const StringPiece& x, const StringPiece& y) {
    172   const int r = StringPiece::wordmemcmp(x.data(), y.data(),
    173                                         std::min(x.size(), y.size()));
    174   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
    175 }
    176 
    177 inline bool operator>(const StringPiece& x, const StringPiece& y) {
    178   return y < x;
    179 }
    180 
    181 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
    182   return !(x > y);
    183 }
    184 
    185 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
    186   return !(x < y);
    187 }
    188 
    189 // allow StringPiece to be logged (needed for unit testing).
    190 extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
    191 
    192 }  // namespace base
    193 
    194 #endif  // BASE_STRING_PIECE_H_
    195