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 // A string-like object that points to a sized piece of memory.
     18 //
     19 // Functions or methods may use const StringPiece& parameters to accept either
     20 // a "const char*" or a "string" value that will be implicitly converted to
     21 // a StringPiece.  The implicit conversion means that it is often appropriate
     22 // to include this .h file in other files rather than forward-declaring
     23 // StringPiece as would be appropriate for most other Google classes.
     24 //
     25 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary
     26 // conversions from "const char*" to "string" and back again.
     27 
     28 #ifndef ART_RUNTIME_BASE_STRINGPIECE_H_
     29 #define ART_RUNTIME_BASE_STRINGPIECE_H_
     30 
     31 #include <string.h>
     32 #include <algorithm>
     33 #include <cstddef>
     34 #include <iosfwd>
     35 #include <string>
     36 
     37 namespace art {
     38 
     39 class StringPiece {
     40  private:
     41   const char*   ptr_;
     42   int           length_;
     43 
     44  public:
     45   // We provide non-explicit singleton constructors so users can pass
     46   // in a "const char*" or a "string" wherever a "StringPiece" is
     47   // expected.
     48   StringPiece() : ptr_(NULL), length_(0) { }
     49   StringPiece(const char* str)  // NOLINT
     50     : ptr_(str), length_((str == NULL) ? 0 : static_cast<int>(strlen(str))) { }
     51   StringPiece(const std::string& str)  // NOLINT
     52     : ptr_(str.data()), length_(static_cast<int>(str.size())) { }
     53   StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { }
     54 
     55   // data() may return a pointer to a buffer with embedded NULs, and the
     56   // returned buffer may or may not be null terminated.  Therefore it is
     57   // typically a mistake to pass data() to a routine that expects a NUL
     58   // terminated string.
     59   const char* data() const { return ptr_; }
     60   int size() const { return length_; }
     61   int length() const { return length_; }
     62   bool empty() const { return length_ == 0; }
     63 
     64   void clear() {
     65     ptr_ = NULL;
     66     length_ = 0;
     67   }
     68   void set(const char* data, int len) {
     69     ptr_ = data;
     70     length_ = len;
     71   }
     72   void set(const char* str) {
     73     ptr_ = str;
     74     if (str != NULL)
     75       length_ = static_cast<int>(strlen(str));
     76     else
     77       length_ = 0;
     78   }
     79   void set(const void* data, int len) {
     80     ptr_ = reinterpret_cast<const char*>(data);
     81     length_ = len;
     82   }
     83 
     84   char operator[](int i) const { return ptr_[i]; }
     85 
     86   void remove_prefix(int n) {
     87     ptr_ += n;
     88     length_ -= n;
     89   }
     90 
     91   void remove_suffix(int n) {
     92     length_ -= n;
     93   }
     94 
     95   int compare(const StringPiece& x) const;
     96 
     97   std::string as_string() const {
     98     return std::string(data(), size());
     99   }
    100   // We also define ToString() here, since many other string-like
    101   // interfaces name the routine that converts to a C++ string
    102   // "ToString", and it's confusing to have the method that does that
    103   // for a StringPiece be called "as_string()".  We also leave the
    104   // "as_string()" method defined here for existing code.
    105   std::string ToString() const {
    106     return std::string(data(), size());
    107   }
    108 
    109   void CopyToString(std::string* target) const;
    110   void AppendToString(std::string* target) const;
    111 
    112   // Does "this" start with "x"
    113   bool starts_with(const StringPiece& x) const {
    114     return ((length_ >= x.length_) &&
    115             (memcmp(ptr_, x.ptr_, x.length_) == 0));
    116   }
    117 
    118   // Does "this" end with "x"
    119   bool ends_with(const StringPiece& x) const {
    120     return ((length_ >= x.length_) &&
    121             (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
    122   }
    123 
    124   // standard STL container boilerplate
    125   typedef char value_type;
    126   typedef const char* pointer;
    127   typedef const char& reference;
    128   typedef const char& const_reference;
    129   typedef size_t size_type;
    130   typedef ptrdiff_t difference_type;
    131   static const size_type npos;
    132   typedef const char* const_iterator;
    133   typedef const char* iterator;
    134   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    135   typedef std::reverse_iterator<iterator> reverse_iterator;
    136   iterator begin() const { return ptr_; }
    137   iterator end() const { return ptr_ + length_; }
    138   const_reverse_iterator rbegin() const {
    139     return const_reverse_iterator(ptr_ + length_);
    140   }
    141   const_reverse_iterator rend() const {
    142     return const_reverse_iterator(ptr_);
    143   }
    144   // STLS says return size_type, but Google says return int
    145   int max_size() const { return length_; }
    146   int capacity() const { return length_; }
    147 
    148   int copy(char* buf, size_type n, size_type pos = 0) const;
    149 
    150   size_type find(const StringPiece& s, size_type pos = 0) const;
    151   size_type find(char c, size_type pos = 0) const;
    152   size_type rfind(const StringPiece& s, size_type pos = npos) const;
    153   size_type rfind(char c, size_type pos = npos) const;
    154 
    155   StringPiece substr(size_type pos, size_type n = npos) const;
    156 };
    157 
    158 // This large function is defined inline so that in a fairly common case where
    159 // one of the arguments is a literal, the compiler can elide a lot of the
    160 // following comparisons.
    161 inline bool operator==(const StringPiece& x, const StringPiece& y) {
    162   int len = x.size();
    163   if (len != y.size()) {
    164     return false;
    165   }
    166 
    167   const char* p1 = x.data();
    168   const char* p2 = y.data();
    169   if (p1 == p2) {
    170     return true;
    171   }
    172   if (len <= 0) {
    173     return true;
    174   }
    175 
    176   // Test last byte in case strings share large common prefix
    177   if (p1[len-1] != p2[len-1]) return false;
    178   if (len == 1) return true;
    179 
    180   // At this point we can, but don't have to, ignore the last byte.  We use
    181   // this observation to fold the odd-length case into the even-length case.
    182   len &= ~1;
    183 
    184   return memcmp(p1, p2, len) == 0;
    185 }
    186 
    187 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
    188   return !(x == y);
    189 }
    190 
    191 inline bool operator<(const StringPiece& x, const StringPiece& y) {
    192   const int r = memcmp(x.data(), y.data(),
    193                        std::min(x.size(), y.size()));
    194   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
    195 }
    196 
    197 inline bool operator>(const StringPiece& x, const StringPiece& y) {
    198   return y < x;
    199 }
    200 
    201 inline bool operator<=(const StringPiece& x, const StringPiece& y) {
    202   return !(x > y);
    203 }
    204 
    205 inline bool operator>=(const StringPiece& x, const StringPiece& y) {
    206   return !(x < y);
    207 }
    208 
    209 extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
    210 
    211 }  // namespace art
    212 
    213 #endif  // ART_RUNTIME_BASE_STRINGPIECE_H_
    214