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 namespace detail { |
brettw
2011/12/01 20:29:24
Normally this would be "internal" or something, bu
erikwright (departed)
2011/12/06 15:52:06
A compelling reason for basic_string to be in std
| |
37 | |
38 template <typename STRING_TYPE> class BasicStringPiece { | |
37 public: | 39 public: |
38 // standard STL container boilerplate | 40 // standard STL container boilerplate |
39 typedef size_t size_type; | 41 typedef size_t size_type; |
40 typedef char value_type; | 42 typedef typename STRING_TYPE::value_type value_type; |
41 typedef const char* pointer; | 43 typedef const value_type* pointer; |
42 typedef const char& reference; | 44 typedef const value_type& reference; |
43 typedef const char& const_reference; | 45 typedef const value_type& const_reference; |
44 typedef ptrdiff_t difference_type; | 46 typedef ptrdiff_t difference_type; |
45 typedef const char* const_iterator; | 47 typedef const value_type* const_iterator; |
46 typedef const char* iterator; | 48 typedef const value_type* iterator; |
47 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 49 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
48 typedef std::reverse_iterator<iterator> reverse_iterator; | 50 typedef std::reverse_iterator<iterator> reverse_iterator; |
brettw
2011/12/01 20:29:24
I'd make this also const to match the non-reverse
erikwright (departed)
2011/12/06 15:52:06
In fact, why not just remove the non-const typedef
| |
49 | 51 |
50 static const size_type npos; | 52 static const size_type npos; |
51 | 53 |
52 public: | 54 public: |
53 // We provide non-explicit singleton constructors so users can pass | 55 // We provide non-explicit singleton constructors so users can pass |
54 // in a "const char*" or a "string" wherever a "StringPiece" is | 56 // in a "const char*" or a "string" wherever a "StringPiece" is |
55 // expected. | 57 // expected (likewise for char16, string16, StringPiece16). |
56 StringPiece() : ptr_(NULL), length_(0) { } | 58 BasicStringPiece() : ptr_(NULL), length_(0) { } |
57 StringPiece(const char* str) | 59 BasicStringPiece(const value_type* str) |
58 : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { } | 60 : ptr_(str), |
59 StringPiece(const std::string& str) | 61 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) { } |
62 BasicStringPiece(const STRING_TYPE& str) | |
60 : ptr_(str.data()), length_(str.size()) { } | 63 : ptr_(str.data()), length_(str.size()) { } |
61 StringPiece(const char* offset, size_type len) | 64 BasicStringPiece(const value_type* offset, size_type len) |
62 : ptr_(offset), length_(len) { } | 65 : ptr_(offset), length_(len) { } |
63 | 66 |
64 // data() may return a pointer to a buffer with embedded NULs, and the | 67 // 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 | 68 // 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 | 69 // typically a mistake to pass data() to a routine that expects a NUL |
67 // terminated string. | 70 // terminated string. |
68 const char* data() const { return ptr_; } | 71 const value_type* data() const { return ptr_; } |
69 size_type size() const { return length_; } | 72 size_type size() const { return length_; } |
70 size_type length() const { return length_; } | 73 size_type length() const { return length_; } |
71 bool empty() const { return length_ == 0; } | 74 bool empty() const { return length_ == 0; } |
72 | 75 |
73 void clear() { | 76 void clear() { |
74 ptr_ = NULL; | 77 ptr_ = NULL; |
75 length_ = 0; | 78 length_ = 0; |
76 } | 79 } |
77 void set(const char* data, size_type len) { | 80 void set(const value_type* data, size_type len) { |
78 ptr_ = data; | 81 ptr_ = data; |
79 length_ = len; | 82 length_ = len; |
80 } | 83 } |
81 void set(const char* str) { | 84 void set(const value_type* str) { |
82 ptr_ = str; | 85 ptr_ = str; |
83 length_ = str ? strlen(str) : 0; | 86 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 } | 87 } |
89 | 88 |
90 char operator[](size_type i) const { return ptr_[i]; } | 89 value_type operator[](size_type i) const { return ptr_[i]; } |
91 | 90 |
92 void remove_prefix(size_type n) { | 91 void remove_prefix(size_type n) { |
93 ptr_ += n; | 92 ptr_ += n; |
94 length_ -= n; | 93 length_ -= n; |
95 } | 94 } |
96 | 95 |
97 void remove_suffix(size_type n) { | 96 void remove_suffix(size_type n) { |
98 length_ -= n; | 97 length_ -= n; |
99 } | 98 } |
100 | 99 |
100 STRING_TYPE as_string() const { | |
101 // std::string doesn't like to take a NULL pointer even with a 0 size. | |
102 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); | |
103 } | |
104 | |
105 iterator begin() const { return ptr_; } | |
brettw
2011/12/01 20:29:24
Can these return const_iterator instead? The retur
erikwright (departed)
2011/12/06 15:52:06
Sure. Given this, I guess the next step would be t
| |
106 iterator end() const { return ptr_ + length_; } | |
107 const_reverse_iterator rbegin() const { | |
108 return const_reverse_iterator(ptr_ + length_); | |
109 } | |
110 const_reverse_iterator rend() const { | |
111 return const_reverse_iterator(ptr_); | |
112 } | |
113 | |
114 size_type max_size() const { return length_; } | |
115 size_type capacity() const { return length_; } | |
116 | |
117 static int wordmemcmp(const value_type* p, | |
118 const value_type* p2, | |
119 size_type N) { | |
120 return STRING_TYPE::traits_type::compare(p, p2, N); | |
121 } | |
122 | |
123 protected: | |
124 const value_type* ptr_; | |
125 size_type length_; | |
126 }; | |
127 | |
128 template <typename STRING_TYPE> | |
129 const typename BasicStringPiece<STRING_TYPE>::size_type | |
130 BasicStringPiece<STRING_TYPE>::npos = | |
131 typename BasicStringPiece<STRING_TYPE>::size_type(-1); | |
132 | |
133 } // namespace detail | |
134 | |
135 class BASE_EXPORT StringPiece : public detail::BasicStringPiece<std::string> { | |
136 public: | |
137 StringPiece() {} | |
138 StringPiece(const char* str) : detail::BasicStringPiece<std::string>(str) {} | |
139 StringPiece(const std::string& str) | |
140 : detail::BasicStringPiece<std::string>(str) {} | |
141 StringPiece(const char* offset, size_type len) | |
142 : detail::BasicStringPiece<std::string>(offset, len) {} | |
143 | |
101 int compare(const StringPiece& x) const { | 144 int compare(const StringPiece& x) const { |
102 int r = wordmemcmp( | 145 int r = wordmemcmp( |
103 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); | 146 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); |
104 if (r == 0) { | 147 if (r == 0) { |
105 if (length_ < x.length_) r = -1; | 148 if (length_ < x.length_) r = -1; |
106 else if (length_ > x.length_) r = +1; | 149 else if (length_ > x.length_) r = +1; |
107 } | 150 } |
108 return r; | 151 return r; |
109 } | 152 } |
110 | 153 |
111 std::string as_string() const { | 154 void set(const void* data, size_type len) { |
112 // std::string doesn't like to take a NULL pointer even with a 0 size. | 155 ptr_ = reinterpret_cast<const value_type*>(data); |
113 return std::string(!empty() ? data() : "", size()); | 156 length_ = len; |
114 } | 157 } |
115 | 158 |
116 void CopyToString(std::string* target) const; | 159 void CopyToString(std::string* target) const; |
117 void AppendToString(std::string* target) const; | 160 void AppendToString(std::string* target) const; |
118 | 161 |
119 // Does "this" start with "x" | 162 // Does "this" start with "x" |
120 bool starts_with(const StringPiece& x) const { | 163 bool starts_with(const StringPiece& x) const { |
121 return ((length_ >= x.length_) && | 164 return ((length_ >= x.length_) && |
122 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); | 165 (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); |
123 } | 166 } |
124 | 167 |
125 // Does "this" end with "x" | 168 // Does "this" end with "x" |
126 bool ends_with(const StringPiece& x) const { | 169 bool ends_with(const StringPiece& x) const { |
127 return ((length_ >= x.length_) && | 170 return ((length_ >= x.length_) && |
128 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); | 171 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); |
129 } | 172 } |
130 | 173 |
131 iterator begin() const { return ptr_; } | |
132 iterator end() const { return ptr_ + length_; } | |
133 const_reverse_iterator rbegin() const { | |
134 return const_reverse_iterator(ptr_ + length_); | |
135 } | |
136 const_reverse_iterator rend() const { | |
137 return const_reverse_iterator(ptr_); | |
138 } | |
139 | |
140 size_type max_size() const { return length_; } | |
141 size_type capacity() const { return length_; } | |
142 | |
143 size_type copy(char* buf, size_type n, size_type pos = 0) const; | 174 size_type copy(char* buf, size_type n, size_type pos = 0) const; |
144 | 175 |
145 size_type find(const StringPiece& s, size_type pos = 0) const; | 176 size_type find(const StringPiece& s, size_type pos = 0) const; |
146 size_type find(char c, size_type pos = 0) const; | 177 size_type find(char c, size_type pos = 0) const; |
147 size_type rfind(const StringPiece& s, size_type pos = npos) const; | 178 size_type rfind(const StringPiece& s, size_type pos = npos) const; |
148 size_type rfind(char c, size_type pos = npos) const; | 179 size_type rfind(char c, size_type pos = npos) const; |
149 | 180 |
150 size_type find_first_of(const StringPiece& s, size_type pos = 0) const; | 181 size_type find_first_of(const StringPiece& s, size_type pos = 0) const; |
151 size_type find_first_of(char c, size_type pos = 0) const { | 182 size_type find_first_of(char c, size_type pos = 0) const { |
152 return find(c, pos); | 183 return find(c, pos); |
153 } | 184 } |
154 size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const; | 185 size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const; |
155 size_type find_first_not_of(char c, size_type pos = 0) const; | 186 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; | 187 size_type find_last_of(const StringPiece& s, size_type pos = npos) const; |
157 size_type find_last_of(char c, size_type pos = npos) const { | 188 size_type find_last_of(char c, size_type pos = npos) const { |
158 return rfind(c, pos); | 189 return rfind(c, pos); |
159 } | 190 } |
160 size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const; | 191 size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const; |
161 size_type find_last_not_of(char c, size_type pos = npos) const; | 192 size_type find_last_not_of(char c, size_type pos = npos) const; |
162 | 193 |
163 StringPiece substr(size_type pos, size_type n = npos) const; | 194 StringPiece 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 }; | 195 }; |
173 | 196 |
174 class BASE_EXPORT StringPiece16 { | 197 typedef detail::BasicStringPiece<string16> StringPiece16; |
175 public: | |
176 // standard STL container boilerplate | |
177 typedef size_t size_type; | |
178 typedef char16 value_type; | |
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 | |
188 public: | |
189 // We provide non-explicit singleton constructors so users can pass | |
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 | 198 |
252 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); | 199 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); |
253 | 200 |
254 inline bool operator!=(const StringPiece& x, const StringPiece& y) { | 201 inline bool operator!=(const StringPiece& x, const StringPiece& y) { |
255 return !(x == y); | 202 return !(x == y); |
256 } | 203 } |
257 | 204 |
258 inline bool operator<(const StringPiece& x, const StringPiece& y) { | 205 inline bool operator<(const StringPiece& x, const StringPiece& y) { |
259 const int r = StringPiece::wordmemcmp( | 206 const int r = StringPiece::wordmemcmp( |
260 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); | 207 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 } | 287 } |
341 inline size_t hash_value(const base::StringPiece16& sp16) { | 288 inline size_t hash_value(const base::StringPiece16& sp16) { |
342 HASH_STRING_PIECE(base::StringPiece16, sp16); | 289 HASH_STRING_PIECE(base::StringPiece16, sp16); |
343 } | 290 } |
344 | 291 |
345 #endif // COMPILER | 292 #endif // COMPILER |
346 | 293 |
347 } // namespace BASE_HASH_NAMESPACE | 294 } // namespace BASE_HASH_NAMESPACE |
348 | 295 |
349 #endif // BASE_STRING_PIECE_H_ | 296 #endif // BASE_STRING_PIECE_H_ |
OLD | NEW |