Home | History | Annotate | Download | only in re2
      1 // Copyright 2001-2010 The RE2 Authors.  All Rights Reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // A string-like object that points to a sized piece of memory.
      6 //
      7 // Functions or methods may use const StringPiece& parameters to accept either
      8 // a "const char*" or a "string" value that will be implicitly converted to
      9 // a StringPiece.  The implicit conversion means that it is often appropriate
     10 // to include this .h file in other files rather than forward-declaring
     11 // StringPiece as would be appropriate for most other Google classes.
     12 //
     13 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary
     14 // conversions from "const char*" to "string" and back again.
     15 //
     16 //
     17 // Arghh!  I wish C++ literals were "string".
     18 
     19 #ifndef STRINGS_STRINGPIECE_H__
     20 #define STRINGS_STRINGPIECE_H__
     21 
     22 #include <string.h>
     23 #include <cstddef>
     24 #include <iosfwd>
     25 #include <string>
     26 
     27 namespace re2 {
     28 
     29 class StringPiece {
     30  private:
     31   const char*   ptr_;
     32   int           length_;
     33 
     34  public:
     35   // We provide non-explicit singleton constructors so users can pass
     36   // in a "const char*" or a "string" wherever a "StringPiece" is
     37   // expected.
     38   StringPiece() : ptr_(NULL), length_(0) { }
     39   StringPiece(const char* str)
     40     : ptr_(str), length_((str == NULL) ? 0 : static_cast<int>(strlen(str))) { }
     41   StringPiece(const std::string& str)
     42     : ptr_(str.data()), length_(static_cast<int>(str.size())) { }
     43   StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { }
     44 
     45   // data() may return a pointer to a buffer with embedded NULs, and the
     46   // returned buffer may or may not be null terminated.  Therefore it is
     47   // typically a mistake to pass data() to a routine that expects a NUL
     48   // terminated string.
     49   const char* data() const { return ptr_; }
     50   int size() const { return length_; }
     51   int length() const { return length_; }
     52   bool empty() const { return length_ == 0; }
     53 
     54   void clear() { ptr_ = NULL; length_ = 0; }
     55   void set(const char* data, int len) { ptr_ = data; length_ = len; }
     56   void set(const char* str) {
     57     ptr_ = str;
     58     if (str != NULL)
     59       length_ = static_cast<int>(strlen(str));
     60     else
     61       length_ = 0;
     62   }
     63   void set(const void* data, int len) {
     64     ptr_ = reinterpret_cast<const char*>(data);
     65     length_ = len;
     66   }
     67 
     68   char operator[](int i) const { return ptr_[i]; }
     69 
     70   void remove_prefix(int n) {
     71     ptr_ += n;
     72     length_ -= n;
     73   }
     74 
     75   void remove_suffix(int n) {
     76     length_ -= n;
     77   }
     78 
     79   int compare(const StringPiece& x) const {
     80     int r = memcmp(ptr_, x.ptr_, std::min(length_, x.length_));
     81     if (r == 0) {
     82       if (length_ < x.length_) r = -1;
     83       else if (length_ > x.length_) r = +1;
     84     }
     85     return r;
     86   }
     87 
     88   std::string as_string() const {
     89     return std::string(data(), size());
     90   }
     91   // We also define ToString() here, since many other string-like
     92   // interfaces name the routine that converts to a C++ string
     93   // "ToString", and it's confusing to have the method that does that
     94   // for a StringPiece be called "as_string()".  We also leave the
     95   // "as_string()" method defined here for existing code.
     96   std::string ToString() const {
     97     return std::string(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             (memcmp(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             (memcmp(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 size_t size_type;
    121   typedef ptrdiff_t difference_type;
    122   static const size_type npos;
    123   typedef const char* const_iterator;
    124   typedef const char* iterator;
    125   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    126   typedef std::reverse_iterator<iterator> reverse_iterator;
    127   iterator begin() const { return ptr_; }
    128   iterator end() const { return ptr_ + length_; }
    129   const_reverse_iterator rbegin() const {
    130     return const_reverse_iterator(ptr_ + length_);
    131   }
    132   const_reverse_iterator rend() const {
    133     return const_reverse_iterator(ptr_);
    134   }
    135   // STLS says return size_type, but Google says return int
    136   int max_size() const { return length_; }
    137   int capacity() const { return length_; }
    138 
    139   int copy(char* buf, size_type n, size_type pos = 0) const;
    140 
    141   int find(const StringPiece& s, size_type pos = 0) const;
    142   int find(char c, size_type pos = 0) const;
    143   int rfind(const StringPiece& s, size_type pos = npos) const;
    144   int rfind(char c, size_type pos = npos) const;
    145 
    146   StringPiece substr(size_type pos, size_type n = npos) const;
    147 
    148   static bool _equal(const StringPiece&, const StringPiece&);
    149 };
    150 
    151 inline bool operator==(const StringPiece& x, const StringPiece& y) {
    152   return StringPiece::_equal(x, y);
    153 }
    154 
    155 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
    156   return !(x == y);
    157 }
    158 
    159 inline bool operator<(const StringPiece& x, const StringPiece& y) {
    160   const int r = memcmp(x.data(), y.data(),
    161                        std::min(x.size(), y.size()));
    162   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
    163 }
    164 
    165 inline bool operator>(const StringPiece& x, const StringPiece& y) {
    166   return y < x;
    167 }
    168 
    169 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
    170   return !(x > y);
    171 }
    172 
    173 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
    174   return !(x < y);
    175 }
    176 
    177 }  // namespace re2
    178 
    179 // allow StringPiece to be logged
    180 extern std::ostream& operator<<(std::ostream& o, const re2::StringPiece& piece);
    181 
    182 #endif  // STRINGS_STRINGPIECE_H__
    183