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). BasicStringPiece()181 BasicStringPiece() : ptr_(NULL), length_(0) {} BasicStringPiece(const value_type * str)182 BasicStringPiece(const value_type* str) 183 : ptr_(str), 184 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} BasicStringPiece(const STRING_TYPE & str)185 BasicStringPiece(const STRING_TYPE& str) 186 : ptr_(str.data()), length_(str.size()) {} BasicStringPiece(const value_type * offset,size_type len)187 BasicStringPiece(const value_type* offset, size_type len) 188 : ptr_(offset), length_(len) {} BasicStringPiece(const typename STRING_TYPE::const_iterator & begin,const typename STRING_TYPE::const_iterator & end)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. data()207 const value_type* data() const { return ptr_; } size()208 size_type size() const { return length_; } length()209 size_type length() const { return length_; } empty()210 bool empty() const { return length_ == 0; } 211 clear()212 void clear() { 213 ptr_ = NULL; 214 length_ = 0; 215 } set(const value_type * data,size_type len)216 void set(const value_type* data, size_type len) { 217 ptr_ = data; 218 length_ = len; 219 } set(const value_type * str)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]; } front()226 value_type front() const { return ptr_[0]; } back()227 value_type back() const { return ptr_[length_ - 1]; } 228 remove_prefix(size_type n)229 void remove_prefix(size_type n) { 230 ptr_ += n; 231 length_ -= n; 232 } 233 remove_suffix(size_type n)234 void remove_suffix(size_type n) { 235 length_ -= n; 236 } 237 compare(const BasicStringPiece<STRING_TYPE> & x)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 as_string()248 STRING_TYPE as_string() const { 249 // std::string doesn't like to take a NULL pointer even with a 0 size. 250 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); 251 } 252 begin()253 const_iterator begin() const { return ptr_; } end()254 const_iterator end() const { return ptr_ + length_; } rbegin()255 const_reverse_iterator rbegin() const { 256 return const_reverse_iterator(ptr_ + length_); 257 } rend()258 const_reverse_iterator rend() const { 259 return const_reverse_iterator(ptr_); 260 } 261 max_size()262 size_type max_size() const { return length_; } capacity()263 size_type capacity() const { return length_; } 264 wordmemcmp(const value_type * p,const value_type * p2,size_type N)265 static int wordmemcmp(const value_type* p, 266 const value_type* p2, 267 size_type N) { 268 return STRING_TYPE::traits_type::compare(p, p2, N); 269 } 270 271 // Sets the value of the given string target type to be the current string. 272 // This saves a temporary over doing |a = b.as_string()| CopyToString(STRING_TYPE * target)273 void CopyToString(STRING_TYPE* target) const { 274 internal::CopyToString(*this, target); 275 } 276 AppendToString(STRING_TYPE * target)277 void AppendToString(STRING_TYPE* target) const { 278 internal::AppendToString(*this, target); 279 } 280 281 size_type copy(value_type* buf, size_type n, size_type pos = 0) const { 282 return internal::copy(*this, buf, n, pos); 283 } 284 285 // Does "this" start with "x" starts_with(const BasicStringPiece & x)286 bool starts_with(const BasicStringPiece& x) const { 287 return ((this->length_ >= x.length_) && 288 (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0)); 289 } 290 291 // Does "this" end with "x" ends_with(const BasicStringPiece & x)292 bool ends_with(const BasicStringPiece& x) const { 293 return ((this->length_ >= x.length_) && 294 (wordmemcmp(this->ptr_ + (this->length_-x.length_), 295 x.ptr_, x.length_) == 0)); 296 } 297 298 // find: Search for a character or substring at a given offset. 299 size_type find(const BasicStringPiece<STRING_TYPE>& s, 300 size_type pos = 0) const { 301 return internal::find(*this, s, pos); 302 } 303 size_type find(value_type c, size_type pos = 0) const { 304 return internal::find(*this, c, pos); 305 } 306 307 // rfind: Reverse find. 308 size_type rfind(const BasicStringPiece& s, 309 size_type pos = BasicStringPiece::npos) const { 310 return internal::rfind(*this, s, pos); 311 } 312 size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const { 313 return internal::rfind(*this, c, pos); 314 } 315 316 // find_first_of: Find the first occurence of one of a set of characters. 317 size_type find_first_of(const BasicStringPiece& s, 318 size_type pos = 0) const { 319 return internal::find_first_of(*this, s, pos); 320 } 321 size_type find_first_of(value_type c, size_type pos = 0) const { 322 return find(c, pos); 323 } 324 325 // find_first_not_of: Find the first occurence not of a set of characters. 326 size_type find_first_not_of(const BasicStringPiece& s, 327 size_type pos = 0) const { 328 return internal::find_first_not_of(*this, s, pos); 329 } 330 size_type find_first_not_of(value_type c, size_type pos = 0) const { 331 return internal::find_first_not_of(*this, c, pos); 332 } 333 334 // find_last_of: Find the last occurence of one of a set of characters. 335 size_type find_last_of(const BasicStringPiece& s, 336 size_type pos = BasicStringPiece::npos) const { 337 return internal::find_last_of(*this, s, pos); 338 } 339 size_type find_last_of(value_type c, 340 size_type pos = BasicStringPiece::npos) const { 341 return rfind(c, pos); 342 } 343 344 // find_last_not_of: Find the last occurence not of a set of characters. 345 size_type find_last_not_of(const BasicStringPiece& s, 346 size_type pos = BasicStringPiece::npos) const { 347 return internal::find_last_not_of(*this, s, pos); 348 } 349 size_type find_last_not_of(value_type c, 350 size_type pos = BasicStringPiece::npos) const { 351 return internal::find_last_not_of(*this, c, pos); 352 } 353 354 // substr. 355 BasicStringPiece substr(size_type pos, 356 size_type n = BasicStringPiece::npos) const { 357 return internal::substr(*this, pos, n); 358 } 359 360 protected: 361 const value_type* ptr_; 362 size_type length_; 363 }; 364 365 template <typename STRING_TYPE> 366 const typename BasicStringPiece<STRING_TYPE>::size_type 367 BasicStringPiece<STRING_TYPE>::npos = 368 typename BasicStringPiece<STRING_TYPE>::size_type(-1); 369 370 // MSVC doesn't like complex extern templates and DLLs. 371 #if !defined(COMPILER_MSVC) 372 extern template class BASE_EXPORT BasicStringPiece<std::string>; 373 extern template class BASE_EXPORT BasicStringPiece<string16>; 374 #endif 375 376 // StingPiece operators -------------------------------------------------------- 377 378 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); 379 380 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 381 return !(x == y); 382 } 383 384 inline bool operator<(const StringPiece& x, const StringPiece& y) { 385 const int r = StringPiece::wordmemcmp( 386 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 387 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 388 } 389 390 inline bool operator>(const StringPiece& x, const StringPiece& y) { 391 return y < x; 392 } 393 394 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 395 return !(x > y); 396 } 397 398 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 399 return !(x < y); 400 } 401 402 // StringPiece16 operators ----------------------------------------------------- 403 404 inline bool operator==(const StringPiece16& x, const StringPiece16& y) { 405 if (x.size() != y.size()) 406 return false; 407 408 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; 409 } 410 411 inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { 412 return !(x == y); 413 } 414 415 inline bool operator<(const StringPiece16& x, const StringPiece16& y) { 416 const int r = StringPiece16::wordmemcmp( 417 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 418 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 419 } 420 421 inline bool operator>(const StringPiece16& x, const StringPiece16& y) { 422 return y < x; 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 return !(x < y); 431 } 432 433 BASE_EXPORT std::ostream& operator<<(std::ostream& o, 434 const StringPiece& piece); 435 436 // Hashing --------------------------------------------------------------------- 437 438 // We provide appropriate hash functions so StringPiece and StringPiece16 can 439 // be used as keys in hash sets and maps. 440 441 // This hash function is copied from base/strings/string16.h. We don't use the 442 // ones already defined for string and string16 directly because it would 443 // require the string constructors to be called, which we don't want. 444 #define HASH_STRING_PIECE(StringPieceType, string_piece) \ 445 std::size_t result = 0; \ 446 for (StringPieceType::const_iterator i = string_piece.begin(); \ 447 i != string_piece.end(); ++i) \ 448 result = (result * 131) + *i; \ 449 return result; 450 451 struct StringPieceHash { operatorStringPieceHash452 std::size_t operator()(const StringPiece& sp) const { 453 HASH_STRING_PIECE(StringPiece, sp); 454 } 455 }; 456 struct StringPiece16Hash { operatorStringPiece16Hash457 std::size_t operator()(const StringPiece16& sp16) const { 458 HASH_STRING_PIECE(StringPiece16, sp16); 459 } 460 }; 461 462 } // namespace base 463 464 #endif // BASE_STRINGS_STRING_PIECE_H_ 465