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