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. StringPiece()50 StringPiece() : ptr_(nullptr), length_(0) { } StringPiece(const char * str)51 StringPiece(const char* str) // NOLINT implicit constructor desired 52 : ptr_(str), length_((str == nullptr) ? 0 : strlen(str)) { } StringPiece(const std::string & str)53 StringPiece(const std::string& str) // NOLINT implicit constructor desired 54 : ptr_(str.data()), length_(str.size()) { } StringPiece(const char * offset,size_t len)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. data()61 const char* data() const { return ptr_; } size()62 size_type size() const { return length_; } length()63 size_type length() const { return length_; } empty()64 bool empty() const { return length_ == 0; } 65 clear()66 void clear() { 67 ptr_ = nullptr; 68 length_ = 0; 69 } set(const char * data_in,size_type len)70 void set(const char* data_in, size_type len) { 71 ptr_ = data_in; 72 length_ = len; 73 } set(const char * str)74 void set(const char* str) { 75 ptr_ = str; 76 if (str != nullptr) { 77 length_ = strlen(str); 78 } else { 79 length_ = 0; 80 } 81 } set(const void * data_in,size_type len)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 remove_prefix(size_type n)95 void remove_prefix(size_type n) { 96 ptr_ += n; 97 length_ -= n; 98 } 99 remove_suffix(size_type n)100 void remove_suffix(size_type n) { 101 length_ -= n; 102 } 103 104 int compare(const StringPiece& x) const; 105 as_string()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. ToString()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" starts_with(const StringPiece & 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" ends_with(const StringPiece & 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 begin()133 iterator begin() const { return ptr_; } end()134 iterator end() const { return ptr_ + length_; } rbegin()135 const_reverse_iterator rbegin() const { 136 return const_reverse_iterator(ptr_ + length_); 137 } rend()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 Compare(const StringPiece & rhs)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