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 #include <type_traits> 30 31 #include "base/base_export.h" 32 #include "base/logging.h" 33 #include "base/strings/char_traits.h" 34 #include "base/strings/string16.h" 35 #include "base/strings/string_piece_forward.h" 36 37 namespace base { 38 39 // internal -------------------------------------------------------------------- 40 41 // Many of the StringPiece functions use different implementations for the 42 // 8-bit and 16-bit versions, and we don't want lots of template expansions in 43 // this (very common) header that will slow down compilation. 44 // 45 // So here we define overloaded functions called by the StringPiece template. 46 // For those that share an implementation, the two versions will expand to a 47 // template internal to the .cc file. 48 namespace internal { 49 50 BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); 51 BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target); 52 53 BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); 54 BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target); 55 56 BASE_EXPORT size_t copy(const StringPiece& self, 57 char* buf, 58 size_t n, 59 size_t pos); 60 BASE_EXPORT size_t copy(const StringPiece16& self, 61 char16* buf, 62 size_t n, 63 size_t pos); 64 65 BASE_EXPORT size_t find(const StringPiece& self, 66 const StringPiece& s, 67 size_t pos); 68 BASE_EXPORT size_t find(const StringPiece16& self, 69 const StringPiece16& s, 70 size_t pos); 71 BASE_EXPORT size_t find(const StringPiece& self, 72 char c, 73 size_t pos); 74 BASE_EXPORT size_t find(const StringPiece16& self, 75 char16 c, 76 size_t pos); 77 78 BASE_EXPORT size_t rfind(const StringPiece& self, 79 const StringPiece& s, 80 size_t pos); 81 BASE_EXPORT size_t rfind(const StringPiece16& self, 82 const StringPiece16& s, 83 size_t pos); 84 BASE_EXPORT size_t rfind(const StringPiece& self, 85 char c, 86 size_t pos); 87 BASE_EXPORT size_t rfind(const StringPiece16& self, 88 char16 c, 89 size_t pos); 90 91 BASE_EXPORT size_t find_first_of(const StringPiece& self, 92 const StringPiece& s, 93 size_t pos); 94 BASE_EXPORT size_t find_first_of(const StringPiece16& self, 95 const StringPiece16& s, 96 size_t pos); 97 98 BASE_EXPORT size_t find_first_not_of(const StringPiece& self, 99 const StringPiece& s, 100 size_t pos); 101 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, 102 const StringPiece16& s, 103 size_t pos); 104 BASE_EXPORT size_t find_first_not_of(const StringPiece& self, 105 char c, 106 size_t pos); 107 BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, 108 char16 c, 109 size_t pos); 110 111 BASE_EXPORT size_t find_last_of(const StringPiece& self, 112 const StringPiece& s, 113 size_t pos); 114 BASE_EXPORT size_t find_last_of(const StringPiece16& self, 115 const StringPiece16& s, 116 size_t pos); 117 BASE_EXPORT size_t find_last_of(const StringPiece& self, 118 char c, 119 size_t pos); 120 BASE_EXPORT size_t find_last_of(const StringPiece16& self, 121 char16 c, 122 size_t pos); 123 124 BASE_EXPORT size_t find_last_not_of(const StringPiece& self, 125 const StringPiece& s, 126 size_t pos); 127 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, 128 const StringPiece16& s, 129 size_t pos); 130 BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, 131 char16 c, 132 size_t pos); 133 BASE_EXPORT size_t find_last_not_of(const StringPiece& self, 134 char c, 135 size_t pos); 136 137 BASE_EXPORT StringPiece substr(const StringPiece& self, 138 size_t pos, 139 size_t n); 140 BASE_EXPORT StringPiece16 substr(const StringPiece16& self, 141 size_t pos, 142 size_t n); 143 144 #if DCHECK_IS_ON() 145 // Asserts that begin <= end to catch some errors with iterator usage. 146 BASE_EXPORT void AssertIteratorsInOrder(std::string::const_iterator begin, 147 std::string::const_iterator end); 148 BASE_EXPORT void AssertIteratorsInOrder(string16::const_iterator begin, 149 string16::const_iterator end); 150 #endif 151 152 } // namespace internal 153 154 // BasicStringPiece ------------------------------------------------------------ 155 156 // Defines the types, methods, operators, and data members common to both 157 // StringPiece and StringPiece16. Do not refer to this class directly, but 158 // rather to BasicStringPiece, StringPiece, or StringPiece16. 159 // 160 // This is templatized by string class type rather than character type, so 161 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>. 162 template <typename STRING_TYPE> class BasicStringPiece { 163 public: 164 // Standard STL container boilerplate. 165 typedef size_t size_type; 166 typedef typename STRING_TYPE::value_type value_type; 167 typedef const value_type* pointer; 168 typedef const value_type& reference; 169 typedef const value_type& const_reference; 170 typedef ptrdiff_t difference_type; 171 typedef const value_type* const_iterator; 172 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 173 174 static const size_type npos; 175 176 public: 177 // We provide non-explicit singleton constructors so users can pass 178 // in a "const char*" or a "string" wherever a "StringPiece" is 179 // expected (likewise for char16, string16, StringPiece16). BasicStringPiece()180 constexpr BasicStringPiece() : ptr_(NULL), length_(0) {} 181 // TODO(dcheng): Construction from nullptr is not allowed for 182 // std::basic_string_view, so remove the special handling for it. 183 // Note: This doesn't just use STRING_TYPE::traits_type::length(), since that 184 // isn't constexpr until C++17. BasicStringPiece(const value_type * str)185 constexpr BasicStringPiece(const value_type* str) 186 : ptr_(str), length_(!str ? 0 : CharTraits<value_type>::length(str)) {} BasicStringPiece(const STRING_TYPE & str)187 BasicStringPiece(const STRING_TYPE& str) 188 : ptr_(str.data()), length_(str.size()) {} BasicStringPiece(const value_type * offset,size_type len)189 constexpr BasicStringPiece(const value_type* offset, size_type len) 190 : ptr_(offset), length_(len) {} BasicStringPiece(const typename STRING_TYPE::const_iterator & begin,const typename STRING_TYPE::const_iterator & end)191 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, 192 const typename STRING_TYPE::const_iterator& end) { 193 #if DCHECK_IS_ON() 194 // This assertion is done out-of-line to avoid bringing in logging.h and 195 // instantiating logging macros for every instantiation. 196 internal::AssertIteratorsInOrder(begin, end); 197 #endif 198 length_ = static_cast<size_t>(std::distance(begin, end)); 199 200 // The length test before assignment is to avoid dereferencing an iterator 201 // that may point to the end() of a string. 202 ptr_ = length_ > 0 ? &*begin : nullptr; 203 } 204 205 // data() may return a pointer to a buffer with embedded NULs, and the 206 // returned buffer may or may not be null terminated. Therefore it is 207 // typically a mistake to pass data() to a routine that expects a NUL 208 // terminated string. data()209 constexpr const value_type* data() const { return ptr_; } size()210 constexpr size_type size() const noexcept { return length_; } length()211 constexpr size_type length() const noexcept { return length_; } empty()212 bool empty() const { return length_ == 0; } 213 clear()214 void clear() { 215 ptr_ = NULL; 216 length_ = 0; 217 } set(const value_type * data,size_type len)218 void set(const value_type* data, size_type len) { 219 ptr_ = data; 220 length_ = len; 221 } set(const value_type * str)222 void set(const value_type* str) { 223 ptr_ = str; 224 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; 225 } 226 227 constexpr value_type operator[](size_type i) const { 228 CHECK(i < length_); 229 return ptr_[i]; 230 } 231 front()232 value_type front() const { 233 CHECK_NE(0UL, length_); 234 return ptr_[0]; 235 } 236 back()237 value_type back() const { 238 CHECK_NE(0UL, length_); 239 return ptr_[length_ - 1]; 240 } 241 remove_prefix(size_type n)242 constexpr void remove_prefix(size_type n) { 243 CHECK(n <= length_); 244 ptr_ += n; 245 length_ -= n; 246 } 247 remove_suffix(size_type n)248 constexpr void remove_suffix(size_type n) { 249 CHECK(n <= length_); 250 length_ -= n; 251 } 252 compare(BasicStringPiece x)253 constexpr int compare(BasicStringPiece x) const noexcept { 254 int r = CharTraits<value_type>::compare( 255 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); 256 if (r == 0) { 257 if (length_ < x.length_) r = -1; 258 else if (length_ > x.length_) r = +1; 259 } 260 return r; 261 } 262 263 // This is the style of conversion preferred by std::string_view in C++17. STRING_TYPE()264 explicit operator STRING_TYPE() const { return as_string(); } 265 as_string()266 STRING_TYPE as_string() const { 267 // std::string doesn't like to take a NULL pointer even with a 0 size. 268 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); 269 } 270 begin()271 const_iterator begin() const { return ptr_; } end()272 const_iterator end() const { return ptr_ + length_; } rbegin()273 const_reverse_iterator rbegin() const { 274 return const_reverse_iterator(ptr_ + length_); 275 } rend()276 const_reverse_iterator rend() const { 277 return const_reverse_iterator(ptr_); 278 } 279 max_size()280 size_type max_size() const { return length_; } capacity()281 size_type capacity() const { return length_; } 282 283 // Sets the value of the given string target type to be the current string. 284 // This saves a temporary over doing |a = b.as_string()| CopyToString(STRING_TYPE * target)285 void CopyToString(STRING_TYPE* target) const { 286 internal::CopyToString(*this, target); 287 } 288 AppendToString(STRING_TYPE * target)289 void AppendToString(STRING_TYPE* target) const { 290 internal::AppendToString(*this, target); 291 } 292 293 size_type copy(value_type* buf, size_type n, size_type pos = 0) const { 294 return internal::copy(*this, buf, n, pos); 295 } 296 297 // Does "this" start with "x" starts_with(BasicStringPiece x)298 constexpr bool starts_with(BasicStringPiece x) const noexcept { 299 return ( 300 (this->length_ >= x.length_) && 301 (CharTraits<value_type>::compare(this->ptr_, x.ptr_, x.length_) == 0)); 302 } 303 304 // Does "this" end with "x" ends_with(BasicStringPiece x)305 constexpr bool ends_with(BasicStringPiece x) const noexcept { 306 return ((this->length_ >= x.length_) && 307 (CharTraits<value_type>::compare( 308 this->ptr_ + (this->length_ - x.length_), x.ptr_, x.length_) == 309 0)); 310 } 311 312 // find: Search for a character or substring at a given offset. 313 size_type find(const BasicStringPiece<STRING_TYPE>& s, 314 size_type pos = 0) const { 315 return internal::find(*this, s, pos); 316 } 317 size_type find(value_type c, size_type pos = 0) const { 318 return internal::find(*this, c, pos); 319 } 320 321 // rfind: Reverse find. 322 size_type rfind(const BasicStringPiece& s, 323 size_type pos = BasicStringPiece::npos) const { 324 return internal::rfind(*this, s, pos); 325 } 326 size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const { 327 return internal::rfind(*this, c, pos); 328 } 329 330 // find_first_of: Find the first occurence of one of a set of characters. 331 size_type find_first_of(const BasicStringPiece& s, 332 size_type pos = 0) const { 333 return internal::find_first_of(*this, s, pos); 334 } 335 size_type find_first_of(value_type c, size_type pos = 0) const { 336 return find(c, pos); 337 } 338 339 // find_first_not_of: Find the first occurence not of a set of characters. 340 size_type find_first_not_of(const BasicStringPiece& s, 341 size_type pos = 0) const { 342 return internal::find_first_not_of(*this, s, pos); 343 } 344 size_type find_first_not_of(value_type c, size_type pos = 0) const { 345 return internal::find_first_not_of(*this, c, pos); 346 } 347 348 // find_last_of: Find the last occurence of one of a set of characters. 349 size_type find_last_of(const BasicStringPiece& s, 350 size_type pos = BasicStringPiece::npos) const { 351 return internal::find_last_of(*this, s, pos); 352 } 353 size_type find_last_of(value_type c, 354 size_type pos = BasicStringPiece::npos) const { 355 return rfind(c, pos); 356 } 357 358 // find_last_not_of: Find the last occurence not of a set of characters. 359 size_type find_last_not_of(const BasicStringPiece& s, 360 size_type pos = BasicStringPiece::npos) const { 361 return internal::find_last_not_of(*this, s, pos); 362 } 363 size_type find_last_not_of(value_type c, 364 size_type pos = BasicStringPiece::npos) const { 365 return internal::find_last_not_of(*this, c, pos); 366 } 367 368 // substr. 369 BasicStringPiece substr(size_type pos, 370 size_type n = BasicStringPiece::npos) const { 371 return internal::substr(*this, pos, n); 372 } 373 374 protected: 375 const value_type* ptr_; 376 size_type length_; 377 }; 378 379 template <typename STRING_TYPE> 380 const typename BasicStringPiece<STRING_TYPE>::size_type 381 BasicStringPiece<STRING_TYPE>::npos = 382 typename BasicStringPiece<STRING_TYPE>::size_type(-1); 383 384 // MSVC doesn't like complex extern templates and DLLs. 385 #if !defined(COMPILER_MSVC) 386 extern template class BASE_EXPORT BasicStringPiece<std::string>; 387 extern template class BASE_EXPORT BasicStringPiece<string16>; 388 #endif 389 390 // Comparison operators -------------------------------------------------------- 391 // operator == 392 template <typename StringT> 393 constexpr bool operator==(BasicStringPiece<StringT> lhs, 394 BasicStringPiece<StringT> rhs) noexcept { 395 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; 396 } 397 398 // Here and below we make use of std::common_type_t to emulate an identity type 399 // transformation. This creates a non-deduced context, so that we can compare 400 // StringPieces with types that implicitly convert to StringPieces. See 401 // https://wg21.link/n3766 for details. 402 // Furthermore, we require dummy template parameters for these overloads to work 403 // around a name mangling issue on Windows. 404 template <typename StringT, int = 1> 405 constexpr bool operator==( 406 BasicStringPiece<StringT> lhs, 407 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 408 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; 409 } 410 411 template <typename StringT, int = 2> 412 constexpr bool operator==(std::common_type_t<BasicStringPiece<StringT>> lhs, 413 BasicStringPiece<StringT> rhs) noexcept { 414 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; 415 } 416 417 // operator != 418 template <typename StringT> 419 constexpr bool operator!=(BasicStringPiece<StringT> lhs, 420 BasicStringPiece<StringT> rhs) noexcept { 421 return !(lhs == rhs); 422 } 423 424 template <typename StringT, int = 1> 425 constexpr bool operator!=( 426 BasicStringPiece<StringT> lhs, 427 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 428 return !(lhs == rhs); 429 } 430 431 template <typename StringT, int = 2> 432 constexpr bool operator!=(std::common_type_t<BasicStringPiece<StringT>> lhs, 433 BasicStringPiece<StringT> rhs) noexcept { 434 return !(lhs == rhs); 435 } 436 437 // operator < 438 template <typename StringT> 439 constexpr bool operator<(BasicStringPiece<StringT> lhs, 440 BasicStringPiece<StringT> rhs) noexcept { 441 return lhs.compare(rhs) < 0; 442 } 443 444 template <typename StringT, int = 1> 445 constexpr bool operator<( 446 BasicStringPiece<StringT> lhs, 447 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 448 return lhs.compare(rhs) < 0; 449 } 450 451 template <typename StringT, int = 2> 452 constexpr bool operator<(std::common_type_t<BasicStringPiece<StringT>> lhs, 453 BasicStringPiece<StringT> rhs) noexcept { 454 return lhs.compare(rhs) < 0; 455 } 456 457 // operator > 458 template <typename StringT> 459 constexpr bool operator>(BasicStringPiece<StringT> lhs, 460 BasicStringPiece<StringT> rhs) noexcept { 461 return rhs < lhs; 462 } 463 464 template <typename StringT, int = 1> 465 constexpr bool operator>( 466 BasicStringPiece<StringT> lhs, 467 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 468 return rhs < lhs; 469 } 470 471 template <typename StringT, int = 2> 472 constexpr bool operator>(std::common_type_t<BasicStringPiece<StringT>> lhs, 473 BasicStringPiece<StringT> rhs) noexcept { 474 return rhs < lhs; 475 } 476 477 // operator <= 478 template <typename StringT> 479 constexpr bool operator<=(BasicStringPiece<StringT> lhs, 480 BasicStringPiece<StringT> rhs) noexcept { 481 return !(rhs < lhs); 482 } 483 484 template <typename StringT, int = 1> 485 constexpr bool operator<=( 486 BasicStringPiece<StringT> lhs, 487 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 488 return !(rhs < lhs); 489 } 490 491 template <typename StringT, int = 2> 492 constexpr bool operator<=(std::common_type_t<BasicStringPiece<StringT>> lhs, 493 BasicStringPiece<StringT> rhs) noexcept { 494 return !(rhs < lhs); 495 } 496 497 // operator >= 498 template <typename StringT> 499 constexpr bool operator>=(BasicStringPiece<StringT> lhs, 500 BasicStringPiece<StringT> rhs) noexcept { 501 return !(lhs < rhs); 502 } 503 504 template <typename StringT, int = 1> 505 constexpr bool operator>=( 506 BasicStringPiece<StringT> lhs, 507 std::common_type_t<BasicStringPiece<StringT>> rhs) noexcept { 508 return !(lhs < rhs); 509 } 510 511 template <typename StringT, int = 2> 512 constexpr bool operator>=(std::common_type_t<BasicStringPiece<StringT>> lhs, 513 BasicStringPiece<StringT> rhs) noexcept { 514 return !(lhs < rhs); 515 } 516 517 BASE_EXPORT std::ostream& operator<<(std::ostream& o, 518 const StringPiece& piece); 519 520 BASE_EXPORT std::ostream& operator<<(std::ostream& o, 521 const StringPiece16& piece); 522 523 // Hashing --------------------------------------------------------------------- 524 525 // We provide appropriate hash functions so StringPiece and StringPiece16 can 526 // be used as keys in hash sets and maps. 527 528 // This hash function is copied from base/strings/string16.h. We don't use the 529 // ones already defined for string and string16 directly because it would 530 // require the string constructors to be called, which we don't want. 531 532 template <typename StringPieceType> 533 struct StringPieceHashImpl { operatorStringPieceHashImpl534 std::size_t operator()(StringPieceType sp) const { 535 std::size_t result = 0; 536 for (auto c : sp) 537 result = (result * 131) + c; 538 return result; 539 } 540 }; 541 542 using StringPieceHash = StringPieceHashImpl<StringPiece>; 543 using StringPiece16Hash = StringPieceHashImpl<StringPiece16>; 544 using WStringPieceHash = StringPieceHashImpl<WStringPiece>; 545 546 } // namespace base 547 548 #endif // BASE_STRINGS_STRING_PIECE_H_ 549