Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: base/string_piece.h

Issue 8933012: Revert "Extract common code from StringPiece and StringPiece16 into a templated base class.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/logging.h ('k') | base/string_piece.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 template <typename STRING_TYPE> class BasicStringPiece; 36 class BASE_EXPORT StringPiece {
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 {
44 public: 37 public:
45 // standard STL container boilerplate 38 // standard STL container boilerplate
46 typedef size_t size_type; 39 typedef size_t size_type;
47 typedef typename STRING_TYPE::value_type value_type; 40 typedef char value_type;
48 typedef const value_type* pointer; 41 typedef const char* pointer;
49 typedef const value_type& reference; 42 typedef const char& reference;
50 typedef const value_type& const_reference; 43 typedef const char& const_reference;
51 typedef ptrdiff_t difference_type; 44 typedef ptrdiff_t difference_type;
52 typedef const value_type* const_iterator; 45 typedef const char* const_iterator;
46 typedef const char* iterator;
53 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 47 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
48 typedef std::reverse_iterator<iterator> reverse_iterator;
54 49
55 static const size_type npos; 50 static const size_type npos;
56 51
57 public: 52 public:
58 // We provide non-explicit singleton constructors so users can pass 53 // We provide non-explicit singleton constructors so users can pass
59 // in a "const char*" or a "string" wherever a "StringPiece" is 54 // in a "const char*" or a "string" wherever a "StringPiece" is
60 // expected (likewise for char16, string16, StringPiece16). 55 // expected.
61 StringPieceDetail() : ptr_(NULL), length_(0) {} 56 StringPiece() : ptr_(NULL), length_(0) { }
62 StringPieceDetail(const value_type* str) 57 StringPiece(const char* str)
63 : ptr_(str), 58 : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }
64 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} 59 StringPiece(const std::string& str)
65 StringPieceDetail(const STRING_TYPE& str) 60 : ptr_(str.data()), length_(str.size()) { }
66 : ptr_(str.data()), 61 StringPiece(const char* offset, size_type len)
67 length_(str.size()) {} 62 : ptr_(offset), length_(len) { }
68 StringPieceDetail(const value_type* offset, size_type len)
69 : ptr_(offset),
70 length_(len) {}
71 63
72 // data() may return a pointer to a buffer with embedded NULs, and the 64 // data() may return a pointer to a buffer with embedded NULs, and the
73 // returned buffer may or may not be null terminated. Therefore it is 65 // returned buffer may or may not be null terminated. Therefore it is
74 // typically a mistake to pass data() to a routine that expects a NUL 66 // typically a mistake to pass data() to a routine that expects a NUL
75 // terminated string. 67 // terminated string.
76 const value_type* data() const { return ptr_; } 68 const char* data() const { return ptr_; }
77 size_type size() const { return length_; } 69 size_type size() const { return length_; }
78 size_type length() const { return length_; } 70 size_type length() const { return length_; }
79 bool empty() const { return length_ == 0; } 71 bool empty() const { return length_ == 0; }
80 72
81 void clear() { 73 void clear() {
82 ptr_ = NULL; 74 ptr_ = NULL;
83 length_ = 0; 75 length_ = 0;
84 } 76 }
85 void set(const value_type* data, size_type len) { 77 void set(const char* data, size_type len) {
86 ptr_ = data; 78 ptr_ = data;
87 length_ = len; 79 length_ = len;
88 } 80 }
89 void set(const value_type* str) { 81 void set(const char* str) {
90 ptr_ = str; 82 ptr_ = str;
91 length_ = str ? STRING_TYPE::traits_type::length(str) : 0; 83 length_ = str ? strlen(str) : 0;
84 }
85 void set(const void* data, size_type len) {
86 ptr_ = reinterpret_cast<const char*>(data);
87 length_ = len;
92 } 88 }
93 89
94 value_type operator[](size_type i) const { return ptr_[i]; } 90 char operator[](size_type i) const { return ptr_[i]; }
95 91
96 void remove_prefix(size_type n) { 92 void remove_prefix(size_type n) {
97 ptr_ += n; 93 ptr_ += n;
98 length_ -= n; 94 length_ -= n;
99 } 95 }
100 96
101 void remove_suffix(size_type n) { 97 void remove_suffix(size_type n) {
102 length_ -= n; 98 length_ -= n;
103 } 99 }
104 100
105 int compare(const BasicStringPiece<STRING_TYPE>& x) const { 101 int compare(const StringPiece& x) const {
106 int r = wordmemcmp( 102 int r = wordmemcmp(
107 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); 103 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
108 if (r == 0) { 104 if (r == 0) {
109 if (length_ < x.length_) r = -1; 105 if (length_ < x.length_) r = -1;
110 else if (length_ > x.length_) r = +1; 106 else if (length_ > x.length_) r = +1;
111 } 107 }
112 return r; 108 return r;
113 } 109 }
114 110
115 STRING_TYPE as_string() const { 111 std::string as_string() const {
116 // std::string doesn't like to take a NULL pointer even with a 0 size. 112 // std::string doesn't like to take a NULL pointer even with a 0 size.
117 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); 113 return std::string(!empty() ? data() : "", size());
118 } 114 }
119 115
120 const_iterator begin() const { return ptr_; } 116 void CopyToString(std::string* target) const;
121 const_iterator end() const { return ptr_ + length_; } 117 void AppendToString(std::string* target) const;
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_; }
122 const_reverse_iterator rbegin() const { 133 const_reverse_iterator rbegin() const {
123 return const_reverse_iterator(ptr_ + length_); 134 return const_reverse_iterator(ptr_ + length_);
124 } 135 }
125 const_reverse_iterator rend() const { 136 const_reverse_iterator rend() const {
126 return const_reverse_iterator(ptr_); 137 return const_reverse_iterator(ptr_);
127 } 138 }
128 139
129 size_type max_size() const { return length_; } 140 size_type max_size() const { return length_; }
130 size_type capacity() const { return length_; } 141 size_type capacity() const { return length_; }
131 142
132 static int wordmemcmp(const value_type* p, 143 size_type copy(char* buf, size_type n, size_type pos = 0) const;
133 const value_type* p2, 144
134 size_type N) { 145 size_type find(const StringPiece& s, size_type pos = 0) const;
135 return STRING_TYPE::traits_type::compare(p, p2, N); 146 size_type find(char c, size_type pos = 0) const;
147 size_type rfind(const StringPiece& s, size_type pos = npos) const;
148 size_type rfind(char c, size_type pos = npos) const;
149
150 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 {
152 return find(c, pos);
153 }
154 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;
156 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 {
158 return rfind(c, pos);
159 }
160 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;
162
163 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);
136 } 167 }
137 168
138 protected: 169 private:
139 const value_type* ptr_; 170 const char* ptr_;
140 size_type length_; 171 size_type length_;
141 }; 172 };
142 173
143 template <typename STRING_TYPE> 174 class BASE_EXPORT StringPiece16 {
144 const typename StringPieceDetail<STRING_TYPE>::size_type 175 public:
145 StringPieceDetail<STRING_TYPE>::npos = 176 // standard STL container boilerplate
146 typename StringPieceDetail<STRING_TYPE>::size_type(-1); 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;
147 187
148 // MSVC doesn't like complex extern templates and DLLs. 188 public:
149 #if !defined(COMPILER_MSVC) 189 // We provide non-explicit singleton constructors so users can pass
150 extern template class BASE_EXPORT StringPieceDetail<std::string>; 190 // in a "const char16*" or a "string16" wherever a "StringPiece16" is
151 extern template class BASE_EXPORT StringPieceDetail<string16>; 191 // expected.
152 #endif 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) { }
153 200
154 } // namespace internal 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; }
155 209
156 // Defines the template type that is instantiated as either StringPiece or 210 void clear() {
157 // StringPiece16. 211 ptr_ = NULL;
158 template <typename STRING_TYPE> class BasicStringPiece : 212 length_ = 0;
159 public internal::StringPieceDetail<STRING_TYPE> { 213 }
160 public: 214 void set(const char16* data, size_type len) {
161 typedef typename internal::StringPieceDetail<STRING_TYPE>::value_type 215 ptr_ = data;
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; 216 length_ = len;
195 } 217 }
196 218 void set(const char16* str) {
197 void CopyToString(std::string* target) const; 219 ptr_ = str;
198 void AppendToString(std::string* target) const; 220 length_ = str ? string16::traits_type::length(str) : 0;
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 } 221 }
205 222
206 // Does "this" end with "x" 223 char16 operator[](size_type i) const { return ptr_[i]; }
207 bool ends_with(const BasicStringPiece& x) const { 224
208 return ((length_ >= x.length_) && 225 string16 as_string16() const {
209 (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 226 // StringPiece claims that this is bad when data() is NULL, but unittesting
227 // seems to say otherwise.
228 return string16(data(), size());
210 } 229 }
211 230
212 size_type copy(char* buf, size_type n, size_type pos = 0) const; 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 }
213 239
214 size_type find(const BasicStringPiece& s, size_type pos = 0) const; 240 size_type max_size() const { return length_; }
215 size_type find(char c, size_type pos = 0) const; 241 size_type capacity() const { return length_; }
216 size_type rfind(const BasicStringPiece& s, size_type pos = npos) const;
217 size_type rfind(char c, size_type pos = npos) const;
218 242
219 size_type find_first_of(const BasicStringPiece& s, size_type pos = 0) const; 243 static int wordmemcmp(const char16* p, const char16* p2, size_type N) {
220 size_type find_first_of(char c, size_type pos = 0) const { 244 return string16::traits_type::compare(p, p2, N);
221 return find(c, pos);
222 } 245 }
223 size_type find_first_not_of(const BasicStringPiece& s,
224 size_type pos = 0) const;
225 size_type find_first_not_of(char c, size_type pos = 0) const;
226 size_type find_last_of(const BasicStringPiece& s, size_type pos = npos) const;
227 size_type find_last_of(char c, size_type pos = npos) const {
228 return rfind(c, pos);
229 }
230 size_type find_last_not_of(const BasicStringPiece& s,
231 size_type pos = npos) const;
232 size_type find_last_not_of(char c, size_type pos = npos) const;
233 246
234 BasicStringPiece substr(size_type pos, size_type n = npos) const; 247 private:
248 const char16* ptr_;
249 size_type length_;
235 }; 250 };
236 251
237 // MSVC doesn't like complex extern templates and DLLs.
238 #if !defined(COMPILER_MSVC)
239 extern template class BasicStringPiece<std::string>;
240 extern template class BASE_EXPORT BasicStringPiece<string16>;
241 #endif
242
243 typedef BasicStringPiece<std::string> StringPiece;
244 typedef BasicStringPiece<string16> StringPiece16;
245
246 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); 252 BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
247 253
248 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 254 inline bool operator!=(const StringPiece& x, const StringPiece& y) {
249 return !(x == y); 255 return !(x == y);
250 } 256 }
251 257
252 inline bool operator<(const StringPiece& x, const StringPiece& y) { 258 inline bool operator<(const StringPiece& x, const StringPiece& y) {
253 const int r = StringPiece::wordmemcmp( 259 const int r = StringPiece::wordmemcmp(
254 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); 260 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
255 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 261 return ((r < 0) || ((r == 0) && (x.size() < y.size())));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 } 340 }
335 inline size_t hash_value(const base::StringPiece16& sp16) { 341 inline size_t hash_value(const base::StringPiece16& sp16) {
336 HASH_STRING_PIECE(base::StringPiece16, sp16); 342 HASH_STRING_PIECE(base::StringPiece16, sp16);
337 } 343 }
338 344
339 #endif // COMPILER 345 #endif // COMPILER
340 346
341 } // namespace BASE_HASH_NAMESPACE 347 } // namespace BASE_HASH_NAMESPACE
342 348
343 #endif // BASE_STRING_PIECE_H_ 349 #endif // BASE_STRING_PIECE_H_
OLDNEW
« no previous file with comments | « base/logging.h ('k') | base/string_piece.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698