Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 4 // Copied from strings/stringpiece.h with modifications |
| 5 // | 5 // |
| 6 // A string-like object that points to a sized piece of memory. | 6 // A string-like object that points to a sized piece of memory. |
| 7 // | 7 // |
| 8 // Functions or methods may use const StringPiece& parameters to accept either | 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 | 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 | 10 // a StringPiece. The implicit conversion means that it is often appropriate |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 | 26 |
| 27 #include <string> | 27 #include <string> |
| 28 | 28 |
| 29 #include "base/base_export.h" | 29 #include "base/base_export.h" |
| 30 #include "base/basictypes.h" | 30 #include "base/basictypes.h" |
| 31 #include "base/hash_tables.h" | 31 #include "base/hash_tables.h" |
| 32 #include "base/string16.h" | 32 #include "base/string16.h" |
| 33 | 33 |
| 34 namespace base { | 34 namespace base { |
| 35 | 35 |
| 36 class BASE_EXPORT StringPiece { | 36 template <typename STRING_TYPE> class BasicStringPiece; |
| 37 | |
| 38 namespace internal { | |
| 39 | |
| 40 // Defines the types, methods, operators, and data members common to both | |
| 41 // StringPiece and StringPiece16. Do not refer to this class directly, but | |
| 42 // rather to BasicStringPiece, StringPiece, or StringPiece16. | |
| 43 template <typename STRING_TYPE> class StringPieceDetail { | |
| 37 public: | 44 public: |
| 38 // standard STL container boilerplate | 45 // standard STL container boilerplate |
| 39 typedef size_t size_type; | 46 typedef size_t size_type; |
| 40 typedef char value_type; | 47 typedef typename STRING_TYPE::value_type value_type; |
| 41 typedef const char* pointer; | 48 typedef const value_type* pointer; |
| 42 typedef const char& reference; | 49 typedef const value_type& reference; |
| 43 typedef const char& const_reference; | 50 typedef const value_type& const_reference; |
| 44 typedef ptrdiff_t difference_type; | 51 typedef ptrdiff_t difference_type; |
| 45 typedef const char* const_iterator; | 52 typedef const value_type* const_iterator; |
| 46 typedef const char* iterator; | |
| 47 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 53 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
| 48 typedef std::reverse_iterator<iterator> reverse_iterator; | |
| 49 | 54 |
| 50 static const size_type npos; | 55 static const size_type npos; |
| 51 | 56 |
| 52 public: | 57 public: |
| 53 // We provide non-explicit singleton constructors so users can pass | 58 // We provide non-explicit singleton constructors so users can pass |
| 54 // in a "const char*" or a "string" wherever a "StringPiece" is | 59 // in a "const char*" or a "string" wherever a "StringPiece" is |
| 55 // expected. | 60 // expected (likewise for char16, string16, StringPiece16). |
| 56 StringPiece() : ptr_(NULL), length_(0) { } | 61 StringPieceDetail() : ptr_(NULL), length_(0) {} |
| 57 StringPiece(const char* str) | 62 StringPieceDetail(const value_type* str) |
| 58 : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { } | 63 : ptr_(str), |
| 59 StringPiece(const std::string& str) | 64 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} |
| 60 : ptr_(str.data()), length_(str.size()) { } | 65 StringPieceDetail(const STRING_TYPE& str) |
| 61 StringPiece(const char* offset, size_type len) | 66 : ptr_(str.data()), |
| 62 : ptr_(offset), length_(len) { } | 67 length_(str.size()) {} |
| 68 StringPieceDetail(const value_type* offset, size_type len) | |
| 69 : ptr_(offset), | |
| 70 length_(len) {} | |
| 63 | 71 |
| 64 // data() may return a pointer to a buffer with embedded NULs, and the | 72 // data() may return a pointer to a buffer with embedded NULs, and the |
| 65 // returned buffer may or may not be null terminated. Therefore it is | 73 // returned buffer may or may not be null terminated. Therefore it is |
| 66 // typically a mistake to pass data() to a routine that expects a NUL | 74 // typically a mistake to pass data() to a routine that expects a NUL |
| 67 // terminated string. | 75 // terminated string. |
| 68 const char* data() const { return ptr_; } | 76 const value_type* data() const { return ptr_; } |
| 69 size_type size() const { return length_; } | 77 size_type size() const { return length_; } |
| 70 size_type length() const { return length_; } | 78 size_type length() const { return length_; } |
| 71 bool empty() const { return length_ == 0; } | 79 bool empty() const { return length_ == 0; } |
| 72 | 80 |
| 73 void clear() { | 81 void clear() { |
| 74 ptr_ = NULL; | 82 ptr_ = NULL; |
| 75 length_ = 0; | 83 length_ = 0; |
| 76 } | 84 } |
| 77 void set(const char* data, size_type len) { | 85 void set(const value_type* data, size_type len) { |
| 78 ptr_ = data; | 86 ptr_ = data; |
| 79 length_ = len; | 87 length_ = len; |
| 80 } | 88 } |
| 81 void set(const char* str) { | 89 void set(const value_type* str) { |
| 82 ptr_ = str; | 90 ptr_ = str; |
| 83 length_ = str ? strlen(str) : 0; | 91 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; |
| 84 } | |
| 85 void set(const void* data, size_type len) { | |
| 86 ptr_ = reinterpret_cast<const char*>(data); | |
| 87 length_ = len; | |
| 88 } | 92 } |
| 89 | 93 |
| 90 char operator[](size_type i) const { return ptr_[i]; } | 94 value_type operator[](size_type i) const { return ptr_[i]; } |
| 91 | 95 |
| 92 void remove_prefix(size_type n) { | 96 void remove_prefix(size_type n) { |
| 93 ptr_ += n; | 97 ptr_ += n; |
| 94 length_ -= n; | 98 length_ -= n; |
| 95 } | 99 } |
| 96 | 100 |
| 97 void remove_suffix(size_type n) { | 101 void remove_suffix(size_type n) { |
| 98 length_ -= n; | 102 length_ -= n; |
| 99 } | 103 } |
| 100 | 104 |
| 101 int compare(const StringPiece& x) const { | 105 int compare(const BasicStringPiece<STRING_TYPE>& x) const { |
| 102 int r = wordmemcmp( | 106 int r = wordmemcmp( |
| 103 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); | 107 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); |
| 104 if (r == 0) { | 108 if (r == 0) { |
| 105 if (length_ < x.length_) r = -1; | 109 if (length_ < x.length_) r = -1; |
| 106 else if (length_ > x.length_) r = +1; | 110 else if (length_ > x.length_) r = +1; |
| 107 } | 111 } |
| 108 return r; | 112 return r; |
| 109 } | 113 } |
| 110 | 114 |
| 111 std::string as_string() const { | 115 STRING_TYPE as_string() const { |
| 112 // std::string doesn't like to take a NULL pointer even with a 0 size. | 116 // std::string doesn't like to take a NULL pointer even with a 0 size. |
| 113 return std::string(!empty() ? data() : "", size()); | 117 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); |
| 114 } | 118 } |
| 115 | 119 |
| 116 void CopyToString(std::string* target) const; | 120 const_iterator begin() const { return ptr_; } |
| 117 void AppendToString(std::string* target) const; | 121 const_iterator end() const { return ptr_ + length_; } |
| 118 | |
| 119 // Does "this" start with "x" | |
| 120 bool starts_with(const StringPiece& x) const { | |
| 121 return ((length_ >= x.length_) && | |
| 122 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); | |
| 123 } | |
| 124 | |
| 125 // Does "this" end with "x" | |
| 126 bool ends_with(const StringPiece& x) const { | |
| 127 return ((length_ >= x.length_) && | |
| 128 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); | |
| 129 } | |
| 130 | |
| 131 iterator begin() const { return ptr_; } | |
| 132 iterator end() const { return ptr_ + length_; } | |
| 133 const_reverse_iterator rbegin() const { | 122 const_reverse_iterator rbegin() const { |
| 134 return const_reverse_iterator(ptr_ + length_); | 123 return const_reverse_iterator(ptr_ + length_); |
| 135 } | 124 } |
| 136 const_reverse_iterator rend() const { | 125 const_reverse_iterator rend() const { |
| 137 return const_reverse_iterator(ptr_); | 126 return const_reverse_iterator(ptr_); |
| 138 } | 127 } |
| 139 | 128 |
| 140 size_type max_size() const { return length_; } | 129 size_type max_size() const { return length_; } |
| 141 size_type capacity() const { return length_; } | 130 size_type capacity() const { return length_; } |
| 142 | 131 |
| 132 static int wordmemcmp(const value_type* p, | |
| 133 const value_type* p2, | |
| 134 size_type N) { | |
| 135 return STRING_TYPE::traits_type::compare(p, p2, N); | |
| 136 } | |
| 137 | |
| 138 protected: | |
| 139 const value_type* ptr_; | |
| 140 size_type length_; | |
| 141 }; | |
| 142 | |
| 143 template <typename STRING_TYPE> | |
| 144 const typename StringPieceDetail<STRING_TYPE>::size_type | |
| 145 StringPieceDetail<STRING_TYPE>::npos = | |
| 146 typename StringPieceDetail<STRING_TYPE>::size_type(-1); | |
| 147 | |
| 148 // MSVC doesn't like complex extern templates and DLLs. | |
| 149 #if !defined(COMPILER_MSVC) | |
| 150 extern template class BASE_EXPORT StringPieceDetail<std::string>; | |
| 151 extern template class BASE_EXPORT StringPieceDetail<string16>; | |
| 152 #endif | |
| 153 | |
| 154 } // namespace internal | |
| 155 | |
| 156 // Defines the template type that is instantiated as either StringPiece or | |
| 157 // StringPiece16. | |
| 158 template <typename STRING_TYPE> class BasicStringPiece : | |
| 159 public internal::StringPieceDetail<STRING_TYPE> { | |
| 160 public: | |
| 161 typedef typename internal::StringPieceDetail<STRING_TYPE>::value_type | |
| 162 value_type; | |
| 163 typedef typename internal::StringPieceDetail<STRING_TYPE>::size_type | |
| 164 size_type; | |
| 165 | |
| 166 BasicStringPiece() {} | |
| 167 BasicStringPiece(const value_type*str) | |
| 168 : internal::StringPieceDetail<STRING_TYPE>(str) {} | |
| 169 BasicStringPiece(const STRING_TYPE& str) | |
| 170 : internal::StringPieceDetail<STRING_TYPE>(str) {} | |
| 171 BasicStringPiece(const value_type* offset, size_type len) | |
| 172 : internal::StringPieceDetail<STRING_TYPE>(offset, len) {} | |
| 173 }; | |
| 174 | |
| 175 // Specializes BasicStringPiece for std::string to add a few operations that | |
| 176 // are not needed for string16. | |
| 177 template <> class BASE_EXPORT BasicStringPiece<std::string> : | |
| 178 public internal::StringPieceDetail<std::string> { | |
| 179 public: | |
| 180 BasicStringPiece() {} | |
| 181 BasicStringPiece(const char* str) | |
| 182 : internal::StringPieceDetail<std::string>(str) {} | |
| 183 BasicStringPiece(const std::string& str) | |
| 184 : internal::StringPieceDetail<std::string>(str) {} | |
| 185 BasicStringPiece(const char* offset, size_type len) | |
| 186 : internal::StringPieceDetail<std::string>(offset, len) {} | |
| 187 | |
| 188 // Prevent the following overload of set() from hiding the definitions in the | |
| 189 // base class. | |
| 190 using internal::StringPieceDetail<std::string>::set; | |
| 191 | |
| 192 void set(const void* data, size_type len) { | |
| 193 ptr_ = reinterpret_cast<const value_type*>(data); | |
| 194 length_ = len; | |
| 195 } | |
| 196 | |
| 197 void CopyToString(std::string* target) const; | |
| 198 void AppendToString(std::string* target) const; | |
| 199 | |
| 200 // Does "this" start with "x" | |
| 201 bool starts_with(const BasicStringPiece& x) const { | |
| 202 return ((length_ >= x.length_) && | |
| 203 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); | |
| 204 } | |
| 205 | |
| 206 // Does "this" end with "x" | |
| 207 bool ends_with(const BasicStringPiece& x) const { | |
| 208 return ((length_ >= x.length_) && | |
| 209 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); | |
| 210 } | |
| 211 | |
| 143 size_type copy(char* buf, size_type n, size_type pos = 0) const; | 212 size_type copy(char* buf, size_type n, size_type pos = 0) const; |
| 144 | 213 |
| 145 size_type find(const StringPiece& s, size_type pos = 0) const; | 214 size_type find(const BasicStringPiece& s, size_type pos = 0) const; |
| 146 size_type find(char c, size_type pos = 0) const; | 215 size_type find(char c, size_type pos = 0) const; |
| 147 size_type rfind(const StringPiece& s, size_type pos = npos) const; | 216 size_type rfind(const BasicStringPiece& s, size_type pos = npos) const; |
| 148 size_type rfind(char c, size_type pos = npos) const; | 217 size_type rfind(char c, size_type pos = npos) const; |
| 149 | 218 |
| 150 size_type find_first_of(const StringPiece& s, size_type pos = 0) const; | 219 size_type find_first_of(const BasicStringPiece& s, size_type pos = 0) const; |
| 151 size_type find_first_of(char c, size_type pos = 0) const { | 220 size_type find_first_of(char c, size_type pos = 0) const { |
| 152 return find(c, pos); | 221 return find(c, pos); |
| 153 } | 222 } |
| 154 size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const; | 223 size_type find_first_not_of(const BasicStringPiece& s, |
| 224 size_type pos = 0) const; | |
| 155 size_type find_first_not_of(char c, size_type pos = 0) const; | 225 size_type find_first_not_of(char c, size_type pos = 0) const; |
| 156 size_type find_last_of(const StringPiece& s, size_type pos = npos) const; | 226 size_type find_last_of(const BasicStringPiece& s, size_type pos = npos) const; |
| 157 size_type find_last_of(char c, size_type pos = npos) const { | 227 size_type find_last_of(char c, size_type pos = npos) const { |
| 158 return rfind(c, pos); | 228 return rfind(c, pos); |
| 159 } | 229 } |
| 160 size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const; | 230 size_type find_last_not_of(const BasicStringPiece& s, |
| 231 size_type pos = npos) const; | |
| 161 size_type find_last_not_of(char c, size_type pos = npos) const; | 232 size_type find_last_not_of(char c, size_type pos = npos) const; |
| 162 | 233 |
| 163 StringPiece substr(size_type pos, size_type n = npos) const; | 234 BasicStringPiece substr(size_type pos, size_type n = npos) const; |
| 164 | |
| 165 static int wordmemcmp(const char* p, const char* p2, size_type N) { | |
| 166 return memcmp(p, p2, N); | |
| 167 } | |
| 168 | |
| 169 private: | |
| 170 const char* ptr_; | |
| 171 size_type length_; | |
| 172 }; | 235 }; |
| 173 | 236 |
| 174 class BASE_EXPORT StringPiece16 { | 237 // MSVC doesn't like complex extern templates and DLLs. |
| 175 public: | 238 #if !defined(COMPILER_MSVC) |
| 176 // standard STL container boilerplate | 239 extern template class BasicStringPiece<std::string>; |
|
Nico
2011/12/19 21:58:26
hans@ points out that declaring specialized templa
erikwright (departed)
2011/12/20 15:26:41
Hmm. OK. The other concern would be the method def
| |
| 177 typedef size_t size_type; | 240 extern template class BASE_EXPORT BasicStringPiece<string16>; |
| 178 typedef char16 value_type; | 241 #endif |
| 179 typedef const char16* pointer; | |
| 180 typedef const char16& reference; | |
| 181 typedef const char16& const_reference; | |
| 182 typedef ptrdiff_t difference_type; | |
| 183 typedef const char16* const_iterator; | |
| 184 typedef const char16* iterator; | |
| 185 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | |
| 186 typedef std::reverse_iterator<iterator> reverse_iterator; | |
| 187 | 242 |
| 188 public: | 243 typedef BasicStringPiece<std::string> StringPiece; |
| 189 // We provide non-explicit singleton constructors so users can pass | 244 typedef BasicStringPiece<string16> StringPiece16; |
| 190 // in a "const char16*" or a "string16" wherever a "StringPiece16" is | |
| 191 // expected. | |
| 192 StringPiece16() : ptr_(NULL), length_(0) { } | |
| 193 StringPiece16(const char16* str) | |
| 194 : ptr_(str), | |
| 195 length_((str == NULL) ? 0 : string16::traits_type::length(str)) { } | |
| 196 StringPiece16(const string16& str) | |
| 197 : ptr_(str.data()), length_(str.size()) { } | |
| 198 StringPiece16(const char16* offset, size_type len) | |
| 199 : ptr_(offset), length_(len) { } | |
| 200 | |
| 201 // data() may return a pointer to a buffer with embedded NULs, and the | |
| 202 // returned buffer may or may not be null terminated. Therefore it is | |
| 203 // typically a mistake to pass data() to a routine that expects a NUL | |
| 204 // terminated string. | |
| 205 const char16* data() const { return ptr_; } | |
| 206 size_type size() const { return length_; } | |
| 207 size_type length() const { return length_; } | |
| 208 bool empty() const { return length_ == 0; } | |
| 209 | |
| 210 void clear() { | |
| 211 ptr_ = NULL; | |
| 212 length_ = 0; | |
| 213 } | |
| 214 void set(const char16* data, size_type len) { | |
| 215 ptr_ = data; | |
| 216 length_ = len; | |
| 217 } | |
| 218 void set(const char16* str) { | |
| 219 ptr_ = str; | |
| 220 length_ = str ? string16::traits_type::length(str) : 0; | |
| 221 } | |
| 222 | |
| 223 char16 operator[](size_type i) const { return ptr_[i]; } | |
| 224 | |
| 225 string16 as_string16() const { | |
| 226 // StringPiece claims that this is bad when data() is NULL, but unittesting | |
| 227 // seems to say otherwise. | |
| 228 return string16(data(), size()); | |
| 229 } | |
| 230 | |
| 231 iterator begin() const { return ptr_; } | |
| 232 iterator end() const { return ptr_ + length_; } | |
| 233 const_reverse_iterator rbegin() const { | |
| 234 return const_reverse_iterator(ptr_ + length_); | |
| 235 } | |
| 236 const_reverse_iterator rend() const { | |
| 237 return const_reverse_iterator(ptr_); | |
| 238 } | |
| 239 | |
| 240 size_type max_size() const { return length_; } | |
| 241 size_type capacity() const { return length_; } | |
| 242 | |
| 243 static int wordmemcmp(const char16* p, const char16* p2, size_type N) { | |
| 244 return string16::traits_type::compare(p, p2, N); | |
| 245 } | |
| 246 | |
| 247 private: | |
| 248 const char16* ptr_; | |
| 249 size_type length_; | |
| 250 }; | |
| 251 | 245 |
| 252 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); | 246 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); |
| 253 | 247 |
| 254 inline bool operator!=(const StringPiece& x, const StringPiece& y) { | 248 inline bool operator!=(const StringPiece& x, const StringPiece& y) { |
| 255 return !(x == y); | 249 return !(x == y); |
| 256 } | 250 } |
| 257 | 251 |
| 258 inline bool operator<(const StringPiece& x, const StringPiece& y) { | 252 inline bool operator<(const StringPiece& x, const StringPiece& y) { |
| 259 const int r = StringPiece::wordmemcmp( | 253 const int r = StringPiece::wordmemcmp( |
| 260 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); | 254 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 } | 334 } |
| 341 inline size_t hash_value(const base::StringPiece16& sp16) { | 335 inline size_t hash_value(const base::StringPiece16& sp16) { |
| 342 HASH_STRING_PIECE(base::StringPiece16, sp16); | 336 HASH_STRING_PIECE(base::StringPiece16, sp16); |
| 343 } | 337 } |
| 344 | 338 |
| 345 #endif // COMPILER | 339 #endif // COMPILER |
| 346 | 340 |
| 347 } // namespace BASE_HASH_NAMESPACE | 341 } // namespace BASE_HASH_NAMESPACE |
| 348 | 342 |
| 349 #endif // BASE_STRING_PIECE_H_ | 343 #endif // BASE_STRING_PIECE_H_ |
| OLD | NEW |