| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 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 | 4 |
| 23 #ifndef BASE_STRING_PIECE_H_ | 5 // TODO(brettw) move callers to using the new location |
| 24 #define BASE_STRING_PIECE_H_ | 6 #include "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/hash_tables.h" | |
| 34 #include "base/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). | |
| 65 StringPieceDetail() : ptr_(NULL), length_(0) {} | |
| 66 StringPieceDetail(const value_type* str) | |
| 67 : ptr_(str), | |
| 68 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} | |
| 69 StringPieceDetail(const STRING_TYPE& str) | |
| 70 : ptr_(str.data()), length_(str.size()) {} | |
| 71 StringPieceDetail(const value_type* offset, size_type len) | |
| 72 : ptr_(offset), length_(len) {} | |
| 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. | |
| 82 const value_type* data() const { return ptr_; } | |
| 83 size_type size() const { return length_; } | |
| 84 size_type length() const { return length_; } | |
| 85 bool empty() const { return length_ == 0; } | |
| 86 | |
| 87 void clear() { | |
| 88 ptr_ = NULL; | |
| 89 length_ = 0; | |
| 90 } | |
| 91 void set(const value_type* data, size_type len) { | |
| 92 ptr_ = data; | |
| 93 length_ = len; | |
| 94 } | |
| 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 | |
| 102 void remove_prefix(size_type n) { | |
| 103 ptr_ += n; | |
| 104 length_ -= n; | |
| 105 } | |
| 106 | |
| 107 void remove_suffix(size_type n) { | |
| 108 length_ -= n; | |
| 109 } | |
| 110 | |
| 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 | |
| 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 | |
| 126 const_iterator begin() const { return ptr_; } | |
| 127 const_iterator end() const { return ptr_ + length_; } | |
| 128 const_reverse_iterator rbegin() const { | |
| 129 return const_reverse_iterator(ptr_ + length_); | |
| 130 } | |
| 131 const_reverse_iterator rend() const { | |
| 132 return const_reverse_iterator(ptr_); | |
| 133 } | |
| 134 | |
| 135 size_type max_size() const { return length_; } | |
| 136 size_type capacity() const { return length_; } | |
| 137 | |
| 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 | |
| 226 BasicStringPiece() {} | |
| 227 BasicStringPiece(const value_type*str) | |
| 228 : internal::StringPieceDetail<STRING_TYPE>(str) {} | |
| 229 BasicStringPiece(const STRING_TYPE& str) | |
| 230 : internal::StringPieceDetail<STRING_TYPE>(str) {} | |
| 231 BasicStringPiece(const value_type* offset, size_type len) | |
| 232 : internal::StringPieceDetail<STRING_TYPE>(offset, len) {} | |
| 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: | |
| 243 BasicStringPiece() {} | |
| 244 BasicStringPiece(const char* str) | |
| 245 : internal::StringPieceDetail<std::string>(str) {} | |
| 246 BasicStringPiece(const std::string& str) | |
| 247 : internal::StringPieceDetail<std::string>(str) {} | |
| 248 BasicStringPiece(const char* offset, size_type len) | |
| 249 : internal::StringPieceDetail<std::string>(offset, len) {} | |
| 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 | |
| 258 void set(const void* data, size_type len) { | |
| 259 ptr_ = reinterpret_cast<const value_type*>(data); | |
| 260 length_ = len; | |
| 261 } | |
| 262 | |
| 263 void CopyToString(std::string* target) const { | |
| 264 internal::CopyToString(*this, target); | |
| 265 } | |
| 266 | |
| 267 void AppendToString(std::string* target) const { | |
| 268 internal::AppendToString(*this, target); | |
| 269 } | |
| 270 | |
| 271 // Does "this" start with "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" | |
| 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/hash_tables.h. We don't use the | |
| 413 // ones already defined for string and string16 directly because it would | |
| 414 // 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_STRING_PIECE_H_ | |
| OLD | NEW |