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_LIBARTBASE_BASE_STRINGPIECE_H_ 18 #define ART_LIBARTBASE_BASE_STRINGPIECE_H_ 19 20 #include <string.h> 21 #include <string> 22 23 #include <android-base/logging.h> 24 25 namespace art { 26 27 // A string-like object that points to a sized piece of memory. 28 // 29 // Functions or methods may use const StringPiece& parameters to accept either 30 // a "const char*" or a "string" value that will be implicitly converted to 31 // a StringPiece. The implicit conversion means that it is often appropriate 32 // to include this .h file in other files rather than forward-declaring 33 // StringPiece as would be appropriate for most other Google classes. 34 class StringPiece { 35 public: 36 // standard STL container boilerplate 37 typedef char value_type; 38 typedef const char* pointer; 39 typedef const char& reference; 40 typedef const char& const_reference; 41 typedef size_t size_type; 42 typedef ptrdiff_t difference_type; 43 static constexpr size_type npos = size_type(-1); 44 typedef const char* const_iterator; 45 typedef const char* iterator; 46 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 47 typedef std::reverse_iterator<iterator> reverse_iterator; 48 49 // We provide non-explicit singleton constructors so users can pass 50 // in a "const char*" or a "string" wherever a "StringPiece" is 51 // expected. StringPiece()52 StringPiece() : ptr_(nullptr), length_(0) { } StringPiece(const char * str)53 StringPiece(const char* str) // NOLINT implicit constructor desired 54 : ptr_(str), length_((str == nullptr) ? 0 : strlen(str)) { } StringPiece(const std::string & str)55 StringPiece(const std::string& str) // NOLINT implicit constructor desired 56 : ptr_(str.data()), length_(str.size()) { } StringPiece(const char * offset,size_t len)57 StringPiece(const char* offset, size_t len) : ptr_(offset), length_(len) { } 58 59 // data() may return a pointer to a buffer with embedded NULs, and the 60 // returned buffer may or may not be null terminated. Therefore it is 61 // typically a mistake to pass data() to a routine that expects a NUL 62 // terminated string. data()63 const char* data() const { return ptr_; } size()64 size_type size() const { return length_; } length()65 size_type length() const { return length_; } empty()66 bool empty() const { return length_ == 0; } 67 clear()68 void clear() { 69 ptr_ = nullptr; 70 length_ = 0; 71 } set(const char * data_in,size_type len)72 void set(const char* data_in, size_type len) { 73 ptr_ = data_in; 74 length_ = len; 75 } set(const char * str)76 void set(const char* str) { 77 ptr_ = str; 78 if (str != nullptr) { 79 length_ = strlen(str); 80 } else { 81 length_ = 0; 82 } 83 } set(const void * data_in,size_type len)84 void set(const void* data_in, size_type len) { 85 ptr_ = reinterpret_cast<const char*>(data_in); 86 length_ = len; 87 } 88 89 char operator[](size_type i) const { 90 DCHECK_LT(i, length_); 91 return ptr_[i]; 92 } 93 remove_prefix(size_type n)94 void remove_prefix(size_type n) { 95 ptr_ += n; 96 length_ -= n; 97 } 98 remove_suffix(size_type n)99 void remove_suffix(size_type n) { 100 length_ -= n; 101 } 102 compare(const StringPiece & x)103 int compare(const StringPiece& x) const { 104 int r = memcmp(ptr_, x.ptr_, std::min(length_, x.length_)); 105 if (r == 0) { 106 if (length_ < x.length_) r = -1; 107 else if (length_ > x.length_) r = +1; 108 } 109 return r; 110 } 111 as_string()112 std::string as_string() const { 113 return std::string(data(), size()); 114 } 115 // We also define ToString() here, since many other string-like 116 // interfaces name the routine that converts to a C++ string 117 // "ToString", and it's confusing to have the method that does that 118 // for a StringPiece be called "as_string()". We also leave the 119 // "as_string()" method defined here for existing code. ToString()120 std::string ToString() const { 121 return std::string(data(), size()); 122 } 123 CopyToString(std::string * target)124 void CopyToString(std::string* target) const { 125 target->assign(ptr_, length_); 126 } 127 128 void AppendToString(std::string* target) const; 129 130 // Does "this" start with "x" starts_with(const StringPiece & x)131 bool starts_with(const StringPiece& x) const { 132 return ((length_ >= x.length_) && 133 (memcmp(ptr_, x.ptr_, x.length_) == 0)); 134 } 135 136 // Does "this" end with "x" ends_with(const StringPiece & x)137 bool ends_with(const StringPiece& x) const { 138 return ((length_ >= x.length_) && 139 (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 140 } 141 begin()142 iterator begin() const { return ptr_; } end()143 iterator end() const { return ptr_ + length_; } rbegin()144 const_reverse_iterator rbegin() const { 145 return const_reverse_iterator(ptr_ + length_); 146 } rend()147 const_reverse_iterator rend() const { 148 return const_reverse_iterator(ptr_); 149 } 150 151 size_type copy(char* buf, size_type n, size_type pos = 0) const { 152 size_type ret = std::min(length_ - pos, n); 153 memcpy(buf, ptr_ + pos, ret); 154 return ret; 155 } 156 157 size_type find(const StringPiece& s, size_type pos = 0) const { 158 if (length_ == 0 || pos > static_cast<size_type>(length_)) { 159 return npos; 160 } 161 const char* result = std::search(ptr_ + pos, ptr_ + length_, s.ptr_, s.ptr_ + s.length_); 162 const size_type xpos = result - ptr_; 163 return xpos + s.length_ <= length_ ? xpos : npos; 164 } 165 166 size_type find(char c, size_type pos = 0) const { 167 if (length_ == 0 || pos >= length_) { 168 return npos; 169 } 170 const char* result = std::find(ptr_ + pos, ptr_ + length_, c); 171 return result != ptr_ + length_ ? result - ptr_ : npos; 172 } 173 174 size_type rfind(const StringPiece& s, size_type pos = npos) const { 175 if (length_ < s.length_) return npos; 176 const size_t ulen = length_; 177 if (s.length_ == 0) return std::min(ulen, pos); 178 179 const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_; 180 const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); 181 return result != last ? result - ptr_ : npos; 182 } 183 184 size_type rfind(char c, size_type pos = npos) const { 185 if (length_ == 0) return npos; 186 for (int i = std::min(pos, static_cast<size_type>(length_ - 1)); 187 i >= 0; --i) { 188 if (ptr_[i] == c) { 189 return i; 190 } 191 } 192 return npos; 193 } 194 195 StringPiece substr(size_type pos, size_type n = npos) const { 196 if (pos > static_cast<size_type>(length_)) pos = length_; 197 if (n > length_ - pos) n = length_ - pos; 198 return StringPiece(ptr_ + pos, n); 199 } 200 Compare(const StringPiece & rhs)201 int Compare(const StringPiece& rhs) const { 202 const int r = memcmp(data(), rhs.data(), std::min(size(), rhs.size())); 203 if (r != 0) { 204 return r; 205 } 206 if (size() < rhs.size()) { 207 return -1; 208 } else if (size() > rhs.size()) { 209 return 1; 210 } 211 return 0; 212 } 213 214 private: 215 // Pointer to char data, not necessarily zero terminated. 216 const char* ptr_; 217 // Length of data. 218 size_type length_; 219 }; 220 221 // This large function is defined inline so that in a fairly common case where 222 // one of the arguments is a literal, the compiler can elide a lot of the 223 // following comparisons. 224 inline bool operator==(const StringPiece& x, const StringPiece& y) { 225 StringPiece::size_type len = x.size(); 226 if (len != y.size()) { 227 return false; 228 } 229 230 const char* p1 = x.data(); 231 const char* p2 = y.data(); 232 if (p1 == p2) { 233 return true; 234 } 235 if (len == 0) { 236 return true; 237 } 238 239 // Test last byte in case strings share large common prefix 240 if (p1[len-1] != p2[len-1]) return false; 241 if (len == 1) return true; 242 243 // At this point we can, but don't have to, ignore the last byte. We use 244 // this observation to fold the odd-length case into the even-length case. 245 len &= ~1; 246 247 return memcmp(p1, p2, len) == 0; 248 } 249 250 inline bool operator==(const StringPiece& x, const char* y) { 251 if (y == nullptr) { 252 return x.size() == 0; 253 } else { 254 return strncmp(x.data(), y, x.size()) == 0 && y[x.size()] == '\0'; 255 } 256 } 257 258 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 259 return !(x == y); 260 } 261 262 inline bool operator!=(const StringPiece& x, const char* y) { 263 return !(x == y); 264 } 265 266 inline bool operator<(const StringPiece& x, const StringPiece& y) { 267 return x.Compare(y) < 0; 268 } 269 270 inline bool operator>(const StringPiece& x, const StringPiece& y) { 271 return y < x; 272 } 273 274 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 275 return !(x > y); 276 } 277 278 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 279 return !(x < y); 280 } 281 282 inline std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { 283 o.write(piece.data(), piece.size()); 284 return o; 285 } 286 287 } // namespace art 288 289 #endif // ART_LIBARTBASE_BASE_STRINGPIECE_H_ 290