Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_BASE_STRINGPIECE_H_
     18 #define ART_RUNTIME_BASE_STRINGPIECE_H_
     19 
     20 #include <string.h>
     21 #include <string>
     22 
     23 namespace art {
     24 
     25 // A string-like object that points to a sized piece of memory.
     26 //
     27 // Functions or methods may use const StringPiece& parameters to accept either
     28 // a "const char*" or a "string" value that will be implicitly converted to
     29 // a StringPiece.  The implicit conversion means that it is often appropriate
     30 // to include this .h file in other files rather than forward-declaring
     31 // StringPiece as would be appropriate for most other Google classes.
     32 class StringPiece {
     33  public:
     34   // standard STL container boilerplate
     35   typedef char value_type;
     36   typedef const char* pointer;
     37   typedef const char& reference;
     38   typedef const char& const_reference;
     39   typedef size_t size_type;
     40   typedef ptrdiff_t difference_type;
     41   static constexpr size_type npos = size_type(-1);
     42   typedef const char* const_iterator;
     43   typedef const char* iterator;
     44   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     45   typedef std::reverse_iterator<iterator> reverse_iterator;
     46 
     47   // We provide non-explicit singleton constructors so users can pass
     48   // in a "const char*" or a "string" wherever a "StringPiece" is
     49   // expected.
     50   StringPiece() : ptr_(nullptr), length_(0) { }
     51   StringPiece(const char* str)  // NOLINT implicit constructor desired
     52     : ptr_(str), length_((str == nullptr) ? 0 : strlen(str)) { }
     53   StringPiece(const std::string& str)  // NOLINT implicit constructor desired
     54     : ptr_(str.data()), length_(str.size()) { }
     55   StringPiece(const char* offset, size_t len) : ptr_(offset), length_(len) { }
     56 
     57   // data() may return a pointer to a buffer with embedded NULs, and the
     58   // returned buffer may or may not be null terminated.  Therefore it is
     59   // typically a mistake to pass data() to a routine that expects a NUL
     60   // terminated string.
     61   const char* data() const { return ptr_; }
     62   size_type size() const { return length_; }
     63   size_type length() const { return length_; }
     64   bool empty() const { return length_ == 0; }
     65 
     66   void clear() {
     67     ptr_ = nullptr;
     68     length_ = 0;
     69   }
     70   void set(const char* data_in, size_type len) {
     71     ptr_ = data_in;
     72     length_ = len;
     73   }
     74   void set(const char* str) {
     75     ptr_ = str;
     76     if (str != nullptr) {
     77       length_ = strlen(str);
     78     } else {
     79       length_ = 0;
     80     }
     81   }
     82   void set(const void* data_in, size_type len) {
     83     ptr_ = reinterpret_cast<const char*>(data_in);
     84     length_ = len;
     85   }
     86 
     87 #if defined(NDEBUG)
     88   char operator[](size_type i) const {
     89     return ptr_[i];
     90   }
     91 #else
     92   char operator[](size_type i) const;
     93 #endif
     94 
     95   void remove_prefix(size_type n) {
     96     ptr_ += n;
     97     length_ -= n;
     98   }
     99 
    100   void remove_suffix(size_type n) {
    101     length_ -= n;
    102   }
    103 
    104   int compare(const StringPiece& x) const;
    105 
    106   std::string as_string() const {
    107     return std::string(data(), size());
    108   }
    109   // We also define ToString() here, since many other string-like
    110   // interfaces name the routine that converts to a C++ string
    111   // "ToString", and it's confusing to have the method that does that
    112   // for a StringPiece be called "as_string()".  We also leave the
    113   // "as_string()" method defined here for existing code.
    114   std::string ToString() const {
    115     return std::string(data(), size());
    116   }
    117 
    118   void CopyToString(std::string* target) const;
    119   void AppendToString(std::string* target) const;
    120 
    121   // Does "this" start with "x"
    122   bool starts_with(const StringPiece& x) const {
    123     return ((length_ >= x.length_) &&
    124             (memcmp(ptr_, x.ptr_, x.length_) == 0));
    125   }
    126 
    127   // Does "this" end with "x"
    128   bool ends_with(const StringPiece& x) const {
    129     return ((length_ >= x.length_) &&
    130             (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
    131   }
    132 
    133   iterator begin() const { return ptr_; }
    134   iterator end() const { return ptr_ + length_; }
    135   const_reverse_iterator rbegin() const {
    136     return const_reverse_iterator(ptr_ + length_);
    137   }
    138   const_reverse_iterator rend() const {
    139     return const_reverse_iterator(ptr_);
    140   }
    141 
    142   size_type copy(char* buf, size_type n, size_type pos = 0) const;
    143 
    144   size_type find(const StringPiece& s, size_type pos = 0) const;
    145   size_type find(char c, size_type pos = 0) const;
    146   size_type rfind(const StringPiece& s, size_type pos = npos) const;
    147   size_type rfind(char c, size_type pos = npos) const;
    148 
    149   StringPiece substr(size_type pos, size_type n = npos) const;
    150 
    151   int Compare(const StringPiece& rhs) const {
    152     const int r = memcmp(data(), rhs.data(), std::min(size(), rhs.size()));
    153     if (r != 0) {
    154       return r;
    155     }
    156     if (size() < rhs.size()) {
    157       return -1;
    158     } else if (size() > rhs.size()) {
    159       return 1;
    160     }
    161     return 0;
    162   }
    163 
    164  private:
    165   // Pointer to char data, not necessarily zero terminated.
    166   const char* ptr_;
    167   // Length of data.
    168   size_type length_;
    169 };
    170 
    171 // This large function is defined inline so that in a fairly common case where
    172 // one of the arguments is a literal, the compiler can elide a lot of the
    173 // following comparisons.
    174 inline bool operator==(const StringPiece& x, const StringPiece& y) {
    175   StringPiece::size_type len = x.size();
    176   if (len != y.size()) {
    177     return false;
    178   }
    179 
    180   const char* p1 = x.data();
    181   const char* p2 = y.data();
    182   if (p1 == p2) {
    183     return true;
    184   }
    185   if (len == 0) {
    186     return true;
    187   }
    188 
    189   // Test last byte in case strings share large common prefix
    190   if (p1[len-1] != p2[len-1]) return false;
    191   if (len == 1) return true;
    192 
    193   // At this point we can, but don't have to, ignore the last byte.  We use
    194   // this observation to fold the odd-length case into the even-length case.
    195   len &= ~1;
    196 
    197   return memcmp(p1, p2, len) == 0;
    198 }
    199 
    200 inline bool operator==(const StringPiece& x, const char* y) {
    201   if (y == nullptr) {
    202     return x.size() == 0;
    203   } else {
    204     return strncmp(x.data(), y, x.size()) == 0 && y[x.size()] == '\0';
    205   }
    206 }
    207 
    208 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
    209   return !(x == y);
    210 }
    211 
    212 inline bool operator!=(const StringPiece& x, const char* y) {
    213   return !(x == y);
    214 }
    215 
    216 inline bool operator<(const StringPiece& x, const StringPiece& y) {
    217   return x.Compare(y) < 0;
    218 }
    219 
    220 inline bool operator>(const StringPiece& x, const StringPiece& y) {
    221   return y < x;
    222 }
    223 
    224 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
    225   return !(x > y);
    226 }
    227 
    228 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
    229   return !(x < y);
    230 }
    231 
    232 extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
    233 
    234 }  // namespace art
    235 
    236 #endif  // ART_RUNTIME_BASE_STRINGPIECE_H_
    237