1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // Copied from strings/stringpiece.h with modifications 5 // 6 // A string-like object that points to a sized piece of memory. 7 // 8 // You can use StringPiece as a function or method parameter. A StringPiece 9 // parameter can receive a double-quoted string literal argument, a "const 10 // char*" argument, a string argument, or a StringPiece argument with no data 11 // copying. Systematic use of StringPiece for arguments reduces data 12 // copies and strlen() calls. 13 // 14 // Prefer passing StringPieces by value: 15 // void MyFunction(StringPiece arg); 16 // If circumstances require, you may also pass by const reference: 17 // void MyFunction(const StringPiece& arg); // not preferred 18 // Both of these have the same lifetime semantics. Passing by value 19 // generates slightly smaller code. For more discussion, Googlers can see 20 // the thread go/stringpiecebyvalue on c-users. 21 22 #ifndef BASE_STRINGS_STRING_PIECE_H_ 23 #define BASE_STRINGS_STRING_PIECE_H_ 24 25 #include <stddef.h> 26 27 #include <iosfwd> 28 #include <string> 29 30 #include "base/base_export.h" 31 #include "base/logging.h" 32 #include "base/strings/string16.h" 33 34 namespace base { 35 36 template <typename STRING_TYPE> class BasicStringPiece; 37 typedef BasicStringPiece<std::string> StringPiece; 38 typedef BasicStringPiece<string16> StringPiece16; 39 40 // internal -------------------------------------------------------------------- 41 42 // Many of the StringPiece functions use different implementations for the 43 // 8-bit and 16-bit versions, and we don't want lots of template expansions in 44 // this (very common) header that will slow down compilation. 45 // 46 // So here we define overloaded functions called by the StringPiece template. 47 // For those that share an implementation, the two versions will expand to a 48 // template internal to the .cc file. 49 namespace internal { 50 51 BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); 52 BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target); 53 54 BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); 55 BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target); 56 57 BASE_EXPORT size_t copy(const StringPiece& self, 58 char* buf, 59 size_t n, 60 size_t pos); 61 BASE_EXPORT size_t copy(const StringPiece16& self, 62 char16* buf, 63 size_t n, 64 size_t pos); 65 66 BASE_EXPORT size_t find(const StringPiece& self, 67 const StringPiece& s, 68 size_t pos); 69 BASE_EXPORT size_t find(const StringPiece16& self, 70 const StringPiece16& s, 71 size_t pos); 72 BASE_EXPORT size_t find(const StringPiece& self, 73 char c, 74 size_t pos); 75 BASE_EXPORT size_t find(const StringPiece16& self, 76 char16 c, 77 size_t pos); 78 79 BASE_EXPORT size_t rfind(const StringPiece& self, 80 const StringPiece& s, 81 size_t pos); 82 BASE_EXPORT size_t rfind(const StringPiece16& self, 83 const StringPiece16& s, 84 size_t pos); 85 BASE_EXPORT size_t rfind(const StringPiece& self, 86 char c, 87 size_t pos); 88 BASE_EXPORT size_t rfind(const StringPiece16& self, 89 char16 c, 90 size_t pos); 91 92 BASE_EXPORT size_t find_first_of(const StringPiece& self, 93 const StringPiece& s, 94 size_t pos); 95 BASE_EXPORT size_t find_first_of(const StringPiece16& self, 96 const StringPiece16& s, 97 size_t pos); 98 99 BASE_EXPORT size_t find_first_not_of(const StringPiece& self, 100 const StringPiece& s, 101 size_t pos); 102 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, 103 const StringPiece16& s, 104 size_t pos); 105 BASE_EXPORT size_t find_first_not_of(const StringPiece& self, 106 char c, 107 size_t pos); 108 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, 109 char16 c, 110 size_t pos); 111 112 BASE_EXPORT size_t find_last_of(const StringPiece& self, 113 const StringPiece& s, 114 size_t pos); 115 BASE_EXPORT size_t find_last_of(const StringPiece16& self, 116 const StringPiece16& s, 117 size_t pos); 118 BASE_EXPORT size_t find_last_of(const StringPiece& self, 119 char c, 120 size_t pos); 121 BASE_EXPORT size_t find_last_of(const StringPiece16& self, 122 char16 c, 123 size_t pos); 124 125 BASE_EXPORT size_t find_last_not_of(const StringPiece& self, 126 const StringPiece& s, 127 size_t pos); 128 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, 129 const StringPiece16& s, 130 size_t pos); 131 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, 132 char16 c, 133 size_t pos); 134 BASE_EXPORT size_t find_last_not_of(const StringPiece& self, 135 char c, 136 size_t pos); 137 138 BASE_EXPORT StringPiece substr(const StringPiece& self, 139 size_t pos, 140 size_t n); 141 BASE_EXPORT StringPiece16 substr(const StringPiece16& self, 142 size_t pos, 143 size_t n); 144 145 #if DCHECK_IS_ON() 146 // Asserts that begin <= end to catch some errors with iterator usage. 147 BASE_EXPORT void AssertIteratorsInOrder(std::string::const_iterator begin, 148 std::string::const_iterator end); 149 BASE_EXPORT void AssertIteratorsInOrder(string16::const_iterator begin, 150 string16::const_iterator end); 151 #endif 152 153 } // namespace internal 154 155 // BasicStringPiece ------------------------------------------------------------ 156 157 // Defines the types, methods, operators, and data members common to both 158 // StringPiece and StringPiece16. Do not refer to this class directly, but 159 // rather to BasicStringPiece, StringPiece, or StringPiece16. 160 // 161 // This is templatized by string class type rather than character type, so 162 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>. 163 template <typename STRING_TYPE> class BasicStringPiece { 164 public: 165 // Standard STL container boilerplate. 166 typedef size_t size_type; 167 typedef typename STRING_TYPE::value_type value_type; 168 typedef const value_type* pointer; 169 typedef const value_type& reference; 170 typedef const value_type& const_reference; 171 typedef ptrdiff_t difference_type; 172 typedef const value_type* const_iterator; 173 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 174 175 static const size_type npos; 176 177 public: 178 // We provide non-explicit singleton constructors so users can pass 179 // in a "const char*" or a "string" wherever a "StringPiece" is 180 // expected (likewise for char16, string16, StringPiece16). 181 BasicStringPiece() : ptr_(NULL), length_(0) {} 182 BasicStringPiece(const value_type* str) 183 : ptr_(str), 184 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} 185 BasicStringPiece(const STRING_TYPE& str) 186 : ptr_(str.data()), length_(str.size()) {} 187 BasicStringPiece(const value_type* offset, size_type len) 188 : ptr_(offset), length_(len) {} 189 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, 190 const typename STRING_TYPE::const_iterator& end) { 191 #if DCHECK_IS_ON() 192 // This assertion is done out-of-line to avoid bringing in logging.h and 193 // instantiating logging macros for every instantiation. 194 internal::AssertIteratorsInOrder(begin, end); 195 #endif 196 length_ = static_cast<size_t>(std::distance(begin, end)); 197 198 // The length test before assignment is to avoid dereferencing an iterator 199 // that may point to the end() of a string. 200 ptr_ = length_ > 0 ? &*begin : nullptr; 201 } 202 203 // data() may return a pointer to a buffer with embedded NULs, and the 204 // returned buffer may or may not be null terminated. Therefore it is 205 // typically a mistake to pass data() to a routine that expects a NUL 206 // terminated string. 207 const value_type* data() const { return ptr_; } 208 size_type size() const { return length_; } 209 size_type length() const { return length_; } 210 bool empty() const { return length_ == 0; } 211 212 void clear() { 213 ptr_ = NULL; 214 length_ = 0; 215 } 216 void set(const value_type* data, size_type len) { 217 ptr_ = data; 218 length_ = len; 219 } 220 void set(const value_type* str) { 221 ptr_ = str; 222 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; 223 } 224 225 value_type operator[](size_type i) const { return ptr_[i]; } 226 value_type front() const { return ptr_[0]; } 227 value_type back() const { return ptr_[length_ - 1]; } 228 229 void remove_prefix(size_type n) { 230 ptr_ += n; 231 length_ -= n; 232 } 233 234 void remove_suffix(size_type n) { 235 length_ -= n; 236 } 237 238 int compare(const BasicStringPiece<STRING_TYPE>& x) const { 239 int r = wordmemcmp( 240 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); 241 if (r == 0) { 242 if (length_ < x.length_) r = -1; 243 else if (length_ > x.length_) r = +1; 244 } 245 return r; 246 } 247 248 // This is the style of conversion preferred by std::string_view in C++17. 249 explicit operator STRING_TYPE() const { return as_string(); } 250 251 STRING_TYPE as_string() const { 252 // std::string doesn't like to take a NULL pointer even with a 0 size. 253 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); 254 } 255 256 const_iterator begin() const { return ptr_; } 257 const_iterator end() const { return ptr_ + length_; } 258 const_reverse_iterator rbegin() const { 259 return const_reverse_iterator(ptr_ + length_); 260 } 261 const_reverse_iterator rend() const { 262 return const_reverse_iterator(ptr_); 263 } 264 265 size_type max_size() const { return length_; } 266 size_type capacity() const { return length_; } 267 268 static int wordmemcmp(const value_type* p, 269 const value_type* p2, 270 size_type N) { 271 return STRING_TYPE::traits_type::compare(p, p2, N); 272 } 273 274 // Sets the value of the given string target type to be the current string. 275 // This saves a temporary over doing |a = b.as_string()| 276 void CopyToString(STRING_TYPE* target) const { 277 internal::CopyToString(*this, target); 278 } 279 280 void AppendToString(STRING_TYPE* target) const { 281 internal::AppendToString(*this, target); 282 } 283 284 size_type copy(value_type* buf, size_type n, size_type pos = 0) const { 285 return internal::copy(*this, buf, n, pos); 286 } 287 288 // Does "this" start with "x" 289 bool starts_with(const BasicStringPiece& x) const { 290 return ((this->length_ >= x.length_) && 291 (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0)); 292 } 293 294 // Does "this" end with "x" 295 bool ends_with(const BasicStringPiece& x) const { 296 return ((this->length_ >= x.length_) && 297 (wordmemcmp(this->ptr_ + (this->length_-x.length_), 298 x.ptr_, x.length_) == 0)); 299 } 300 301 // find: Search for a character or substring at a given offset. 302 size_type find(const BasicStringPiece<STRING_TYPE>& s, 303 size_type pos = 0) const { 304 return internal::find(*this, s, pos); 305 } 306 size_type find(value_type c, size_type pos = 0) const { 307 return internal::find(*this, c, pos); 308 } 309 310 // rfind: Reverse find. 311 size_type rfind(const BasicStringPiece& s, 312 size_type pos = BasicStringPiece::npos) const { 313 return internal::rfind(*this, s, pos); 314 } 315 size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const { 316 return internal::rfind(*this, c, pos); 317 } 318 319 // find_first_of: Find the first occurence of one of a set of characters. 320 size_type find_first_of(const BasicStringPiece& s, 321 size_type pos = 0) const { 322 return internal::find_first_of(*this, s, pos); 323 } 324 size_type find_first_of(value_type c, size_type pos = 0) const { 325 return find(c, pos); 326 } 327 328 // find_first_not_of: Find the first occurence not of a set of characters. 329 size_type find_first_not_of(const BasicStringPiece& s, 330 size_type pos = 0) const { 331 return internal::find_first_not_of(*this, s, pos); 332 } 333 size_type find_first_not_of(value_type c, size_type pos = 0) const { 334 return internal::find_first_not_of(*this, c, pos); 335 } 336 337 // find_last_of: Find the last occurence of one of a set of characters. 338 size_type find_last_of(const BasicStringPiece& s, 339 size_type pos = BasicStringPiece::npos) const { 340 return internal::find_last_of(*this, s, pos); 341 } 342 size_type find_last_of(value_type c, 343 size_type pos = BasicStringPiece::npos) const { 344 return rfind(c, pos); 345 } 346 347 // find_last_not_of: Find the last occurence not of a set of characters. 348 size_type find_last_not_of(const BasicStringPiece& s, 349 size_type pos = BasicStringPiece::npos) const { 350 return internal::find_last_not_of(*this, s, pos); 351 } 352 size_type find_last_not_of(value_type c, 353 size_type pos = BasicStringPiece::npos) const { 354 return internal::find_last_not_of(*this, c, pos); 355 } 356 357 // substr. 358 BasicStringPiece substr(size_type pos, 359 size_type n = BasicStringPiece::npos) const { 360 return internal::substr(*this, pos, n); 361 } 362 363 protected: 364 const value_type* ptr_; 365 size_type length_; 366 }; 367 368 template <typename STRING_TYPE> 369 const typename BasicStringPiece<STRING_TYPE>::size_type 370 BasicStringPiece<STRING_TYPE>::npos = 371 typename BasicStringPiece<STRING_TYPE>::size_type(-1); 372 373 // MSVC doesn't like complex extern templates and DLLs. 374 #if !defined(COMPILER_MSVC) 375 extern template class BASE_EXPORT BasicStringPiece<std::string>; 376 extern template class BASE_EXPORT BasicStringPiece<string16>; 377 #endif 378 379 // StingPiece operators -------------------------------------------------------- 380 381 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); 382 383 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 384 return !(x == y); 385 } 386 387 inline bool operator<(const StringPiece& x, const StringPiece& y) { 388 const int r = StringPiece::wordmemcmp( 389 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 390 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 391 } 392 393 inline bool operator>(const StringPiece& x, const StringPiece& y) { 394 return y < x; 395 } 396 397 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 398 return !(x > y); 399 } 400 401 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 402 return !(x < y); 403 } 404 405 // StringPiece16 operators ----------------------------------------------------- 406 407 inline bool operator==(const StringPiece16& x, const StringPiece16& y) { 408 if (x.size() != y.size()) 409 return false; 410 411 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; 412 } 413 414 inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { 415 return !(x == y); 416 } 417 418 inline bool operator<(const StringPiece16& x, const StringPiece16& y) { 419 const int r = StringPiece16::wordmemcmp( 420 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 421 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 422 } 423 424 inline bool operator>(const StringPiece16& x, const StringPiece16& y) { 425 return y < x; 426 } 427 428 inline bool operator<=(const StringPiece16& x, const StringPiece16& y) { 429 return !(x > y); 430 } 431 432 inline bool operator>=(const StringPiece16& x, const StringPiece16& y) { 433 return !(x < y); 434 } 435 436 BASE_EXPORT std::ostream& operator<<(std::ostream& o, 437 const StringPiece& piece); 438 439 // Hashing --------------------------------------------------------------------- 440 441 // We provide appropriate hash functions so StringPiece and StringPiece16 can 442 // be used as keys in hash sets and maps. 443 444 // This hash function is copied from base/strings/string16.h. We don't use the 445 // ones already defined for string and string16 directly because it would 446 // require the string constructors to be called, which we don't want. 447 #define HASH_STRING_PIECE(StringPieceType, string_piece) \ 448 std::size_t result = 0; \ 449 for (StringPieceType::const_iterator i = string_piece.begin(); \ 450 i != string_piece.end(); ++i) \ 451 result = (result * 131) + *i; \ 452 return result; 453 454 struct StringPieceHash { 455 std::size_t operator()(const StringPiece& sp) const { 456 HASH_STRING_PIECE(StringPiece, sp); 457 } 458 }; 459 struct StringPiece16Hash { 460 std::size_t operator()(const StringPiece16& sp16) const { 461 HASH_STRING_PIECE(StringPiece16, sp16); 462 } 463 }; 464 465 } // namespace base 466 467 #endif // BASE_STRINGS_STRING_PIECE_H_ 468