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 // Functions or methods may use const StringPiece& parameters to accept either 9 // a "const char*" or a "string" value that will be implicitly converted to 10 // a StringPiece. The implicit conversion means that it is often appropriate 11 // to include this .h file in other files rather than forward-declaring 12 // StringPiece as would be appropriate for most other Google classes. 13 // 14 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary 15 // conversions from "const char*" to "string" and back again. 16 // 17 // StringPiece16 is similar to StringPiece but for base::string16 instead of 18 // std::string. We do not define as large of a subset of the STL functions 19 // from basic_string as in StringPiece, but this can be changed if these 20 // functions (find, find_first_of, etc.) are found to be useful in this context. 21 // 22 23 #ifndef BASE_STRINGS_STRING_PIECE_H_ 24 #define BASE_STRINGS_STRING_PIECE_H_ 25 26 #include <stddef.h> 27 28 #include <iosfwd> 29 #include <string> 30 31 #include "base/base_export.h" 32 #include "base/basictypes.h" 33 #include "base/containers/hash_tables.h" 34 #include "base/strings/string16.h" 35 36 namespace base { 37 38 template <typename STRING_TYPE> class BasicStringPiece; 39 typedef BasicStringPiece<std::string> StringPiece; 40 typedef BasicStringPiece<string16> StringPiece16; 41 42 namespace internal { 43 44 // Defines the types, methods, operators, and data members common to both 45 // StringPiece and StringPiece16. Do not refer to this class directly, but 46 // rather to BasicStringPiece, StringPiece, or StringPiece16. 47 template <typename STRING_TYPE> class StringPieceDetail { 48 public: 49 // standard STL container boilerplate 50 typedef size_t size_type; 51 typedef typename STRING_TYPE::value_type value_type; 52 typedef const value_type* pointer; 53 typedef const value_type& reference; 54 typedef const value_type& const_reference; 55 typedef ptrdiff_t difference_type; 56 typedef const value_type* const_iterator; 57 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 58 59 static const size_type npos; 60 61 public: 62 // We provide non-explicit singleton constructors so users can pass 63 // in a "const char*" or a "string" wherever a "StringPiece" is 64 // expected (likewise for char16, string16, StringPiece16). StringPieceDetail()65 StringPieceDetail() : ptr_(NULL), length_(0) {} StringPieceDetail(const value_type * str)66 StringPieceDetail(const value_type* str) 67 : ptr_(str), 68 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} StringPieceDetail(const STRING_TYPE & str)69 StringPieceDetail(const STRING_TYPE& str) 70 : ptr_(str.data()), length_(str.size()) {} StringPieceDetail(const value_type * offset,size_type len)71 StringPieceDetail(const value_type* offset, size_type len) 72 : ptr_(offset), length_(len) {} StringPieceDetail(const typename STRING_TYPE::const_iterator & begin,const typename STRING_TYPE::const_iterator & end)73 StringPieceDetail(const typename STRING_TYPE::const_iterator& begin, 74 const typename STRING_TYPE::const_iterator& end) 75 : ptr_((end > begin) ? &(*begin) : NULL), 76 length_((end > begin) ? (size_type)(end - begin) : 0) {} 77 78 // data() may return a pointer to a buffer with embedded NULs, and the 79 // returned buffer may or may not be null terminated. Therefore it is 80 // typically a mistake to pass data() to a routine that expects a NUL 81 // terminated string. data()82 const value_type* data() const { return ptr_; } size()83 size_type size() const { return length_; } length()84 size_type length() const { return length_; } empty()85 bool empty() const { return length_ == 0; } 86 clear()87 void clear() { 88 ptr_ = NULL; 89 length_ = 0; 90 } set(const value_type * data,size_type len)91 void set(const value_type* data, size_type len) { 92 ptr_ = data; 93 length_ = len; 94 } set(const value_type * str)95 void set(const value_type* str) { 96 ptr_ = str; 97 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; 98 } 99 100 value_type operator[](size_type i) const { return ptr_[i]; } 101 remove_prefix(size_type n)102 void remove_prefix(size_type n) { 103 ptr_ += n; 104 length_ -= n; 105 } 106 remove_suffix(size_type n)107 void remove_suffix(size_type n) { 108 length_ -= n; 109 } 110 compare(const BasicStringPiece<STRING_TYPE> & x)111 int compare(const BasicStringPiece<STRING_TYPE>& x) const { 112 int r = wordmemcmp( 113 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); 114 if (r == 0) { 115 if (length_ < x.length_) r = -1; 116 else if (length_ > x.length_) r = +1; 117 } 118 return r; 119 } 120 as_string()121 STRING_TYPE as_string() const { 122 // std::string doesn't like to take a NULL pointer even with a 0 size. 123 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); 124 } 125 begin()126 const_iterator begin() const { return ptr_; } end()127 const_iterator end() const { return ptr_ + length_; } rbegin()128 const_reverse_iterator rbegin() const { 129 return const_reverse_iterator(ptr_ + length_); 130 } rend()131 const_reverse_iterator rend() const { 132 return const_reverse_iterator(ptr_); 133 } 134 max_size()135 size_type max_size() const { return length_; } capacity()136 size_type capacity() const { return length_; } 137 wordmemcmp(const value_type * p,const value_type * p2,size_type N)138 static int wordmemcmp(const value_type* p, 139 const value_type* p2, 140 size_type N) { 141 return STRING_TYPE::traits_type::compare(p, p2, N); 142 } 143 144 protected: 145 const value_type* ptr_; 146 size_type length_; 147 }; 148 149 template <typename STRING_TYPE> 150 const typename StringPieceDetail<STRING_TYPE>::size_type 151 StringPieceDetail<STRING_TYPE>::npos = 152 typename StringPieceDetail<STRING_TYPE>::size_type(-1); 153 154 // MSVC doesn't like complex extern templates and DLLs. 155 #if !defined(COMPILER_MSVC) 156 extern template class BASE_EXPORT StringPieceDetail<std::string>; 157 extern template class BASE_EXPORT StringPieceDetail<string16>; 158 #endif 159 160 BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); 161 BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); 162 BASE_EXPORT StringPieceDetail<std::string>::size_type copy( 163 const StringPiece& self, 164 char* buf, 165 StringPieceDetail<std::string>::size_type n, 166 StringPieceDetail<std::string>::size_type pos); 167 BASE_EXPORT StringPieceDetail<std::string>::size_type find( 168 const StringPiece& self, 169 const StringPiece& s, 170 StringPieceDetail<std::string>::size_type pos); 171 BASE_EXPORT StringPieceDetail<std::string>::size_type find( 172 const StringPiece& self, 173 char c, 174 StringPieceDetail<std::string>::size_type pos); 175 BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( 176 const StringPiece& self, 177 const StringPiece& s, 178 StringPieceDetail<std::string>::size_type pos); 179 BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( 180 const StringPiece& self, 181 char c, 182 StringPieceDetail<std::string>::size_type pos); 183 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_of( 184 const StringPiece& self, 185 const StringPiece& s, 186 StringPieceDetail<std::string>::size_type pos); 187 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( 188 const StringPiece& self, 189 const StringPiece& s, 190 StringPieceDetail<std::string>::size_type pos); 191 BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( 192 const StringPiece& self, 193 char c, 194 StringPieceDetail<std::string>::size_type pos); 195 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( 196 const StringPiece& self, 197 const StringPiece& s, 198 StringPieceDetail<std::string>::size_type pos); 199 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( 200 const StringPiece& self, 201 char c, 202 StringPieceDetail<std::string>::size_type pos); 203 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( 204 const StringPiece& self, 205 const StringPiece& s, 206 StringPieceDetail<std::string>::size_type pos); 207 BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( 208 const StringPiece& self, 209 char c, 210 StringPieceDetail<std::string>::size_type pos); 211 BASE_EXPORT StringPiece substr(const StringPiece& self, 212 StringPieceDetail<std::string>::size_type pos, 213 StringPieceDetail<std::string>::size_type n); 214 } // namespace internal 215 216 // Defines the template type that is instantiated as either StringPiece or 217 // StringPiece16. 218 template <typename STRING_TYPE> class BasicStringPiece : 219 public internal::StringPieceDetail<STRING_TYPE> { 220 public: 221 typedef typename internal::StringPieceDetail<STRING_TYPE>::value_type 222 value_type; 223 typedef typename internal::StringPieceDetail<STRING_TYPE>::size_type 224 size_type; 225 BasicStringPiece()226 BasicStringPiece() {} BasicStringPiece(const value_type * str)227 BasicStringPiece(const value_type*str) 228 : internal::StringPieceDetail<STRING_TYPE>(str) {} BasicStringPiece(const STRING_TYPE & str)229 BasicStringPiece(const STRING_TYPE& str) 230 : internal::StringPieceDetail<STRING_TYPE>(str) {} BasicStringPiece(const value_type * offset,size_type len)231 BasicStringPiece(const value_type* offset, size_type len) 232 : internal::StringPieceDetail<STRING_TYPE>(offset, len) {} BasicStringPiece(const typename STRING_TYPE::const_iterator & begin,const typename STRING_TYPE::const_iterator & end)233 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, 234 const typename STRING_TYPE::const_iterator& end) 235 : internal::StringPieceDetail<STRING_TYPE>(begin, end) {} 236 }; 237 238 // Specializes BasicStringPiece for std::string to add a few operations that 239 // are not needed for string16. 240 template <> class BasicStringPiece<std::string> : 241 public internal::StringPieceDetail<std::string> { 242 public: BasicStringPiece()243 BasicStringPiece() {} BasicStringPiece(const char * str)244 BasicStringPiece(const char* str) 245 : internal::StringPieceDetail<std::string>(str) {} BasicStringPiece(const std::string & str)246 BasicStringPiece(const std::string& str) 247 : internal::StringPieceDetail<std::string>(str) {} BasicStringPiece(const char * offset,size_type len)248 BasicStringPiece(const char* offset, size_type len) 249 : internal::StringPieceDetail<std::string>(offset, len) {} BasicStringPiece(const std::string::const_iterator & begin,const std::string::const_iterator & end)250 BasicStringPiece(const std::string::const_iterator& begin, 251 const std::string::const_iterator& end) 252 : internal::StringPieceDetail<std::string>(begin, end) {} 253 254 // Prevent the following overload of set() from hiding the definitions in the 255 // base class. 256 using internal::StringPieceDetail<std::string>::set; 257 set(const void * data,size_type len)258 void set(const void* data, size_type len) { 259 ptr_ = reinterpret_cast<const value_type*>(data); 260 length_ = len; 261 } 262 CopyToString(std::string * target)263 void CopyToString(std::string* target) const { 264 internal::CopyToString(*this, target); 265 } 266 AppendToString(std::string * target)267 void AppendToString(std::string* target) const { 268 internal::AppendToString(*this, target); 269 } 270 271 // Does "this" start with "x" starts_with(const BasicStringPiece & x)272 bool starts_with(const BasicStringPiece& x) const { 273 return ((length_ >= x.length_) && 274 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); 275 } 276 277 // Does "this" end with "x" ends_with(const BasicStringPiece & x)278 bool ends_with(const BasicStringPiece& x) const { 279 return ((length_ >= x.length_) && 280 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 281 } 282 283 size_type copy(char* buf, size_type n, size_type pos = 0) const { 284 return internal::copy(*this, buf, n, pos); 285 } 286 287 size_type find(const BasicStringPiece& s, size_type pos = 0) const { 288 return internal::find(*this, s, pos); 289 } 290 291 size_type find(char c, size_type pos = 0) const { 292 return internal::find(*this, c, pos); 293 } 294 295 size_type rfind(const BasicStringPiece& s, size_type pos = npos) const { 296 return internal::rfind(*this, s, pos); 297 } 298 299 size_type rfind(char c, size_type pos = npos) const { 300 return internal::rfind(*this, c, pos); 301 } 302 303 size_type find_first_of(const BasicStringPiece& s, size_type pos = 0) const { 304 return internal::find_first_of(*this, s, pos); 305 } 306 307 size_type find_first_of(char c, size_type pos = 0) const { 308 return find(c, pos); 309 } 310 311 size_type find_first_not_of(const BasicStringPiece& s, 312 size_type pos = 0) const { 313 return internal::find_first_not_of(*this, s, pos); 314 } 315 316 size_type find_first_not_of(char c, size_type pos = 0) const { 317 return internal::find_first_not_of(*this, c, pos); 318 } 319 320 size_type find_last_of(const BasicStringPiece& s, 321 size_type pos = npos) const { 322 return internal::find_last_of(*this, s, pos); 323 } 324 325 size_type find_last_of(char c, size_type pos = npos) const { 326 return rfind(c, pos); 327 } 328 329 size_type find_last_not_of(const BasicStringPiece& s, 330 size_type pos = npos) const { 331 return internal::find_last_not_of(*this, s, pos); 332 } 333 334 size_type find_last_not_of(char c, size_type pos = npos) const { 335 return internal::find_last_not_of(*this, c, pos); 336 } 337 338 BasicStringPiece substr(size_type pos, size_type n = npos) const { 339 return internal::substr(*this, pos, n); 340 } 341 }; 342 343 // MSVC doesn't like complex extern templates and DLLs. 344 #if !defined(COMPILER_MSVC) 345 // We can't explicitly declare the std::string instantiation here because it was 346 // already instantiated when specialized, above. Not only is it a no-op, but 347 // currently it also crashes Clang (see http://crbug.com/107412). 348 extern template class BASE_EXPORT BasicStringPiece<string16>; 349 #endif 350 351 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); 352 353 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 354 return !(x == y); 355 } 356 357 inline bool operator<(const StringPiece& x, const StringPiece& y) { 358 const int r = StringPiece::wordmemcmp( 359 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 360 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 361 } 362 363 inline bool operator>(const StringPiece& x, const StringPiece& y) { 364 return y < x; 365 } 366 367 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 368 return !(x > y); 369 } 370 371 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 372 return !(x < y); 373 } 374 375 inline bool operator==(const StringPiece16& x, const StringPiece16& y) { 376 if (x.size() != y.size()) 377 return false; 378 379 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; 380 } 381 382 inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { 383 return !(x == y); 384 } 385 386 inline bool operator<(const StringPiece16& x, const StringPiece16& y) { 387 const int r = StringPiece16::wordmemcmp( 388 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 389 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 390 } 391 392 inline bool operator>(const StringPiece16& x, const StringPiece16& y) { 393 return y < x; 394 } 395 396 inline bool operator<=(const StringPiece16& x, const StringPiece16& y) { 397 return !(x > y); 398 } 399 400 inline bool operator>=(const StringPiece16& x, const StringPiece16& y) { 401 return !(x < y); 402 } 403 404 BASE_EXPORT std::ostream& operator<<(std::ostream& o, 405 const StringPiece& piece); 406 407 } // namespace base 408 409 // We provide appropriate hash functions so StringPiece and StringPiece16 can 410 // be used as keys in hash sets and maps. 411 412 // This hash function is copied from base/containers/hash_tables.h. We don't 413 // use the ones already defined for string and string16 directly because it 414 // would require the string constructors to be called, which we don't want. 415 #define HASH_STRING_PIECE(StringPieceType, string_piece) \ 416 std::size_t result = 0; \ 417 for (StringPieceType::const_iterator i = string_piece.begin(); \ 418 i != string_piece.end(); ++i) \ 419 result = (result * 131) + *i; \ 420 return result; \ 421 422 namespace BASE_HASH_NAMESPACE { 423 #if defined(COMPILER_GCC) 424 425 template<> 426 struct hash<base::StringPiece> { 427 std::size_t operator()(const base::StringPiece& sp) const { 428 HASH_STRING_PIECE(base::StringPiece, sp); 429 } 430 }; 431 template<> 432 struct hash<base::StringPiece16> { 433 std::size_t operator()(const base::StringPiece16& sp16) const { 434 HASH_STRING_PIECE(base::StringPiece16, sp16); 435 } 436 }; 437 438 #elif defined(COMPILER_MSVC) 439 440 inline size_t hash_value(const base::StringPiece& sp) { 441 HASH_STRING_PIECE(base::StringPiece, sp); 442 } 443 inline size_t hash_value(const base::StringPiece16& sp16) { 444 HASH_STRING_PIECE(base::StringPiece16, sp16); 445 } 446 447 #endif // COMPILER 448 449 } // namespace BASE_HASH_NAMESPACE 450 451 #endif // BASE_STRINGS_STRING_PIECE_H_ 452