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