blob: 38e2277e98c874c9db56d5b9cc454f24c972249f [file] [log] [blame]
[email protected]7d7b0ac2013-03-28 20:07:401// 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"
[email protected]14c1c232013-06-11 17:52:4433#include "base/containers/hash_tables.h"
[email protected]c851cfd2013-06-10 20:11:1434#include "base/strings/string16.h"
[email protected]7d7b0ac2013-03-28 20:07:4035
36namespace base {
37
38template <typename STRING_TYPE> class BasicStringPiece;
39typedef BasicStringPiece<std::string> StringPiece;
40typedef BasicStringPiece<string16> StringPiece16;
41
[email protected]0ecab7892014-03-11 21:15:4042// internal --------------------------------------------------------------------
43
44// Many of the StringPiece functions use different implementations for the
45// 8-bit and 16-bit versions, and we don't want lots of template expansions in
46// this (very common) header that will slow down compilation.
47//
48// So here we define overloaded functions called by the StringPiece template.
49// For those that share an implementation, the two versions will expand to a
50// template internal to the .cc file.
[email protected]7d7b0ac2013-03-28 20:07:4051namespace internal {
52
[email protected]0ecab7892014-03-11 21:15:4053BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target);
54BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target);
55
56BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target);
57BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target);
58
59BASE_EXPORT size_t copy(const StringPiece& self,
60 char* buf,
61 size_t n,
62 size_t pos);
63BASE_EXPORT size_t copy(const StringPiece16& self,
64 char16* buf,
65 size_t n,
66 size_t pos);
67
68BASE_EXPORT size_t find(const StringPiece& self,
69 const StringPiece& s,
70 size_t pos);
71BASE_EXPORT size_t find(const StringPiece16& self,
72 const StringPiece16& s,
73 size_t pos);
74BASE_EXPORT size_t find(const StringPiece& self,
75 char c,
76 size_t pos);
77BASE_EXPORT size_t find(const StringPiece16& self,
78 char16 c,
79 size_t pos);
80
81BASE_EXPORT size_t rfind(const StringPiece& self,
82 const StringPiece& s,
83 size_t pos);
84BASE_EXPORT size_t rfind(const StringPiece16& self,
85 const StringPiece16& s,
86 size_t pos);
87BASE_EXPORT size_t rfind(const StringPiece& self,
88 char c,
89 size_t pos);
90BASE_EXPORT size_t rfind(const StringPiece16& self,
91 char16 c,
92 size_t pos);
93
94BASE_EXPORT size_t find_first_of(const StringPiece& self,
95 const StringPiece& s,
96 size_t pos);
97BASE_EXPORT size_t find_first_of(const StringPiece16& self,
98 const StringPiece16& s,
99 size_t pos);
100
101BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
102 const StringPiece& s,
103 size_t pos);
104BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
105 const StringPiece16& s,
106 size_t pos);
107BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
108 char c,
109 size_t pos);
110BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
111 char16 c,
112 size_t pos);
113
114BASE_EXPORT size_t find_last_of(const StringPiece& self,
115 const StringPiece& s,
116 size_t pos);
117BASE_EXPORT size_t find_last_of(const StringPiece16& self,
118 const StringPiece16& s,
119 size_t pos);
120BASE_EXPORT size_t find_last_of(const StringPiece& self,
121 char c,
122 size_t pos);
123BASE_EXPORT size_t find_last_of(const StringPiece16& self,
124 char16 c,
125 size_t pos);
126
127BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
128 const StringPiece& s,
129 size_t pos);
130BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
131 const StringPiece16& s,
132 size_t pos);
133BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
134 char16 c,
135 size_t pos);
136BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
137 char c,
138 size_t pos);
139
140BASE_EXPORT StringPiece substr(const StringPiece& self,
141 size_t pos,
142 size_t n);
143BASE_EXPORT StringPiece16 substr(const StringPiece16& self,
144 size_t pos,
145 size_t n);
146
147} // namespace internal
148
149// BasicStringPiece ------------------------------------------------------------
150
[email protected]7d7b0ac2013-03-28 20:07:40151// Defines the types, methods, operators, and data members common to both
152// StringPiece and StringPiece16. Do not refer to this class directly, but
153// rather to BasicStringPiece, StringPiece, or StringPiece16.
[email protected]0ecab7892014-03-11 21:15:40154//
155// This is templatized by string class type rather than character type, so
156// BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
157template <typename STRING_TYPE> class BasicStringPiece {
[email protected]7d7b0ac2013-03-28 20:07:40158 public:
[email protected]0ecab7892014-03-11 21:15:40159 // Standard STL container boilerplate.
[email protected]7d7b0ac2013-03-28 20:07:40160 typedef size_t size_type;
161 typedef typename STRING_TYPE::value_type value_type;
162 typedef const value_type* pointer;
163 typedef const value_type& reference;
164 typedef const value_type& const_reference;
165 typedef ptrdiff_t difference_type;
166 typedef const value_type* const_iterator;
167 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
168
169 static const size_type npos;
170
171 public:
172 // We provide non-explicit singleton constructors so users can pass
173 // in a "const char*" or a "string" wherever a "StringPiece" is
174 // expected (likewise for char16, string16, StringPiece16).
[email protected]0ecab7892014-03-11 21:15:40175 BasicStringPiece() : ptr_(NULL), length_(0) {}
176 BasicStringPiece(const value_type* str)
[email protected]7d7b0ac2013-03-28 20:07:40177 : ptr_(str),
178 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
[email protected]0ecab7892014-03-11 21:15:40179 BasicStringPiece(const STRING_TYPE& str)
[email protected]7d7b0ac2013-03-28 20:07:40180 : ptr_(str.data()), length_(str.size()) {}
[email protected]0ecab7892014-03-11 21:15:40181 BasicStringPiece(const value_type* offset, size_type len)
[email protected]7d7b0ac2013-03-28 20:07:40182 : ptr_(offset), length_(len) {}
[email protected]0ecab7892014-03-11 21:15:40183 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin,
[email protected]7d7b0ac2013-03-28 20:07:40184 const typename STRING_TYPE::const_iterator& end)
185 : ptr_((end > begin) ? &(*begin) : NULL),
186 length_((end > begin) ? (size_type)(end - begin) : 0) {}
187
188 // data() may return a pointer to a buffer with embedded NULs, and the
189 // returned buffer may or may not be null terminated. Therefore it is
190 // typically a mistake to pass data() to a routine that expects a NUL
191 // terminated string.
192 const value_type* data() const { return ptr_; }
193 size_type size() const { return length_; }
194 size_type length() const { return length_; }
195 bool empty() const { return length_ == 0; }
196
197 void clear() {
198 ptr_ = NULL;
199 length_ = 0;
200 }
201 void set(const value_type* data, size_type len) {
202 ptr_ = data;
203 length_ = len;
204 }
205 void set(const value_type* str) {
206 ptr_ = str;
207 length_ = str ? STRING_TYPE::traits_type::length(str) : 0;
208 }
209
210 value_type operator[](size_type i) const { return ptr_[i]; }
211
212 void remove_prefix(size_type n) {
213 ptr_ += n;
214 length_ -= n;
215 }
216
217 void remove_suffix(size_type n) {
218 length_ -= n;
219 }
220
221 int compare(const BasicStringPiece<STRING_TYPE>& x) const {
222 int r = wordmemcmp(
223 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
224 if (r == 0) {
225 if (length_ < x.length_) r = -1;
226 else if (length_ > x.length_) r = +1;
227 }
228 return r;
229 }
230
231 STRING_TYPE as_string() const {
232 // std::string doesn't like to take a NULL pointer even with a 0 size.
233 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
234 }
235
236 const_iterator begin() const { return ptr_; }
237 const_iterator end() const { return ptr_ + length_; }
238 const_reverse_iterator rbegin() const {
239 return const_reverse_iterator(ptr_ + length_);
240 }
241 const_reverse_iterator rend() const {
242 return const_reverse_iterator(ptr_);
243 }
244
245 size_type max_size() const { return length_; }
246 size_type capacity() const { return length_; }
247
248 static int wordmemcmp(const value_type* p,
249 const value_type* p2,
250 size_type N) {
251 return STRING_TYPE::traits_type::compare(p, p2, N);
252 }
253
[email protected]0ecab7892014-03-11 21:15:40254 // Sets the value of the given string target type to be the current string.
255 // This saves a temporary over doing |a = b.as_string()|
256 void CopyToString(STRING_TYPE* target) const {
257 internal::CopyToString(*this, target);
258 }
259
260 void AppendToString(STRING_TYPE* target) const {
261 internal::AppendToString(*this, target);
262 }
263
264 size_type copy(value_type* buf, size_type n, size_type pos = 0) const {
265 return internal::copy(*this, buf, n, pos);
266 }
267
268 // Does "this" start with "x"
269 bool starts_with(const BasicStringPiece& x) const {
270 return ((this->length_ >= x.length_) &&
271 (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0));
272 }
273
274 // Does "this" end with "x"
275 bool ends_with(const BasicStringPiece& x) const {
276 return ((this->length_ >= x.length_) &&
277 (wordmemcmp(this->ptr_ + (this->length_-x.length_),
278 x.ptr_, x.length_) == 0));
279 }
280
281 // find: Search for a character or substring at a given offset.
282 size_type find(const BasicStringPiece<STRING_TYPE>& s,
283 size_type pos = 0) const {
284 return internal::find(*this, s, pos);
285 }
286 size_type find(value_type c, size_type pos = 0) const {
287 return internal::find(*this, c, pos);
288 }
289
290 // rfind: Reverse find.
291 size_type rfind(const BasicStringPiece& s,
292 size_type pos = BasicStringPiece::npos) const {
293 return internal::rfind(*this, s, pos);
294 }
295 size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const {
296 return internal::rfind(*this, c, pos);
297 }
298
299 // find_first_of: Find the first occurence of one of a set of characters.
300 size_type find_first_of(const BasicStringPiece& s,
301 size_type pos = 0) const {
302 return internal::find_first_of(*this, s, pos);
303 }
304 size_type find_first_of(value_type c, size_type pos = 0) const {
305 return find(c, pos);
306 }
307
308 // find_first_not_of: Find the first occurence not of a set of characters.
309 size_type find_first_not_of(const BasicStringPiece& s,
310 size_type pos = 0) const {
311 return internal::find_first_not_of(*this, s, pos);
312 }
313 size_type find_first_not_of(value_type c, size_type pos = 0) const {
314 return internal::find_first_not_of(*this, c, pos);
315 }
316
317 // find_last_of: Find the last occurence of one of a set of characters.
318 size_type find_last_of(const BasicStringPiece& s,
319 size_type pos = BasicStringPiece::npos) const {
320 return internal::find_last_of(*this, s, pos);
321 }
322 size_type find_last_of(value_type c,
323 size_type pos = BasicStringPiece::npos) const {
324 return rfind(c, pos);
325 }
326
327 // find_last_not_of: Find the last occurence not of a set of characters.
328 size_type find_last_not_of(const BasicStringPiece& s,
329 size_type pos = BasicStringPiece::npos) const {
330 return internal::find_last_not_of(*this, s, pos);
331 }
332 size_type find_last_not_of(value_type c,
333 size_type pos = BasicStringPiece::npos) const {
334 return internal::find_last_not_of(*this, c, pos);
335 }
336
337 // substr.
338 BasicStringPiece substr(size_type pos,
339 size_type n = BasicStringPiece::npos) const {
340 return internal::substr(*this, pos, n);
341 }
342
[email protected]7d7b0ac2013-03-28 20:07:40343 protected:
344 const value_type* ptr_;
345 size_type length_;
346};
347
348template <typename STRING_TYPE>
[email protected]0ecab7892014-03-11 21:15:40349const typename BasicStringPiece<STRING_TYPE>::size_type
350BasicStringPiece<STRING_TYPE>::npos =
351 typename BasicStringPiece<STRING_TYPE>::size_type(-1);
[email protected]7d7b0ac2013-03-28 20:07:40352
353// MSVC doesn't like complex extern templates and DLLs.
354#if !defined(COMPILER_MSVC)
[email protected]0ecab7892014-03-11 21:15:40355extern template class BASE_EXPORT BasicStringPiece<std::string>;
[email protected]50bc27c2014-03-07 01:45:03356extern template class BASE_EXPORT BasicStringPiece<string16>;
357#endif
[email protected]51cb94c2014-03-06 17:54:33358
[email protected]0ecab7892014-03-11 21:15:40359// StingPiece operators --------------------------------------------------------
360
[email protected]7d7b0ac2013-03-28 20:07:40361BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
362
363inline bool operator!=(const StringPiece& x, const StringPiece& y) {
364 return !(x == y);
365}
366
367inline bool operator<(const StringPiece& x, const StringPiece& y) {
368 const int r = StringPiece::wordmemcmp(
369 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
370 return ((r < 0) || ((r == 0) && (x.size() < y.size())));
371}
372
373inline bool operator>(const StringPiece& x, const StringPiece& y) {
374 return y < x;
375}
376
377inline bool operator<=(const StringPiece& x, const StringPiece& y) {
378 return !(x > y);
379}
380
381inline bool operator>=(const StringPiece& x, const StringPiece& y) {
382 return !(x < y);
383}
384
[email protected]0ecab7892014-03-11 21:15:40385// StringPiece16 operators -----------------------------------------------------
386
[email protected]7d7b0ac2013-03-28 20:07:40387inline bool operator==(const StringPiece16& x, const StringPiece16& y) {
388 if (x.size() != y.size())
389 return false;
390
391 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0;
392}
393
394inline bool operator!=(const StringPiece16& x, const StringPiece16& y) {
395 return !(x == y);
396}
397
398inline bool operator<(const StringPiece16& x, const StringPiece16& y) {
399 const int r = StringPiece16::wordmemcmp(
400 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
401 return ((r < 0) || ((r == 0) && (x.size() < y.size())));
402}
403
404inline bool operator>(const StringPiece16& x, const StringPiece16& y) {
405 return y < x;
406}
407
408inline bool operator<=(const StringPiece16& x, const StringPiece16& y) {
409 return !(x > y);
410}
411
412inline bool operator>=(const StringPiece16& x, const StringPiece16& y) {
413 return !(x < y);
414}
415
416BASE_EXPORT std::ostream& operator<<(std::ostream& o,
417 const StringPiece& piece);
418
419} // namespace base
420
[email protected]0ecab7892014-03-11 21:15:40421// Hashing ---------------------------------------------------------------------
422
[email protected]7d7b0ac2013-03-28 20:07:40423// We provide appropriate hash functions so StringPiece and StringPiece16 can
424// be used as keys in hash sets and maps.
425
[email protected]14c1c232013-06-11 17:52:44426// This hash function is copied from base/containers/hash_tables.h. We don't
427// use the ones already defined for string and string16 directly because it
428// would require the string constructors to be called, which we don't want.
[email protected]7d7b0ac2013-03-28 20:07:40429#define HASH_STRING_PIECE(StringPieceType, string_piece) \
430 std::size_t result = 0; \
431 for (StringPieceType::const_iterator i = string_piece.begin(); \
432 i != string_piece.end(); ++i) \
433 result = (result * 131) + *i; \
434 return result; \
435
436namespace BASE_HASH_NAMESPACE {
437#if defined(COMPILER_GCC)
438
439template<>
440struct hash<base::StringPiece> {
441 std::size_t operator()(const base::StringPiece& sp) const {
442 HASH_STRING_PIECE(base::StringPiece, sp);
443 }
444};
445template<>
446struct hash<base::StringPiece16> {
447 std::size_t operator()(const base::StringPiece16& sp16) const {
448 HASH_STRING_PIECE(base::StringPiece16, sp16);
449 }
450};
451
452#elif defined(COMPILER_MSVC)
453
454inline size_t hash_value(const base::StringPiece& sp) {
455 HASH_STRING_PIECE(base::StringPiece, sp);
456}
457inline size_t hash_value(const base::StringPiece16& sp16) {
458 HASH_STRING_PIECE(base::StringPiece16, sp16);
459}
460
461#endif // COMPILER
462
463} // namespace BASE_HASH_NAMESPACE
464
465#endif // BASE_STRINGS_STRING_PIECE_H_