1 // 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
6 // A string-like object that points to a sized piece of memory.
8 // You can use StringPiece as a function or method parameter. A StringPiece
9 // parameter can receive a double-quoted string literal argument, a "const
10 // char*" argument, a string argument, or a StringPiece argument with no data
11 // copying. Systematic use of StringPiece for arguments reduces data
12 // copies and strlen() calls.
14 // Prefer passing StringPieces by value:
15 // void MyFunction(StringPiece arg);
16 // If circumstances require, you may also pass by const reference:
17 // void MyFunction(const StringPiece& arg); // not preferred
18 // Both of these have the same lifetime semantics. Passing by value
19 // generates slightly smaller code. For more discussion, Googlers can see
20 // the thread go/stringpiecebyvalue on c-users.
22 #ifndef BASE_STRINGS_STRING_PIECE_H_
23 #define BASE_STRINGS_STRING_PIECE_H_
30 #include "base/base_export.h"
31 #include "base/basictypes.h"
32 #include "base/containers/hash_tables.h"
33 #include "base/strings/string16.h"
37 template <typename STRING_TYPE
> class BasicStringPiece
;
38 typedef BasicStringPiece
<std::string
> StringPiece
;
39 typedef BasicStringPiece
<string16
> StringPiece16
;
41 // internal --------------------------------------------------------------------
43 // Many of the StringPiece functions use different implementations for the
44 // 8-bit and 16-bit versions, and we don't want lots of template expansions in
45 // this (very common) header that will slow down compilation.
47 // So here we define overloaded functions called by the StringPiece template.
48 // For those that share an implementation, the two versions will expand to a
49 // template internal to the .cc file.
52 BASE_EXPORT
void CopyToString(const StringPiece
& self
, std::string
* target
);
53 BASE_EXPORT
void CopyToString(const StringPiece16
& self
, string16
* target
);
55 BASE_EXPORT
void AppendToString(const StringPiece
& self
, std::string
* target
);
56 BASE_EXPORT
void AppendToString(const StringPiece16
& self
, string16
* target
);
58 BASE_EXPORT
size_t copy(const StringPiece
& self
,
62 BASE_EXPORT
size_t copy(const StringPiece16
& self
,
67 BASE_EXPORT
size_t find(const StringPiece
& self
,
70 BASE_EXPORT
size_t find(const StringPiece16
& self
,
71 const StringPiece16
& s
,
73 BASE_EXPORT
size_t find(const StringPiece
& self
,
76 BASE_EXPORT
size_t find(const StringPiece16
& self
,
80 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
83 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
84 const StringPiece16
& s
,
86 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
89 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
93 BASE_EXPORT
size_t find_first_of(const StringPiece
& self
,
96 BASE_EXPORT
size_t find_first_of(const StringPiece16
& self
,
97 const StringPiece16
& s
,
100 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
101 const StringPiece
& s
,
103 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
104 const StringPiece16
& s
,
106 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
109 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
113 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
114 const StringPiece
& s
,
116 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
117 const StringPiece16
& s
,
119 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
122 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
126 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
127 const StringPiece
& s
,
129 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
130 const StringPiece16
& s
,
132 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
135 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
139 BASE_EXPORT StringPiece
substr(const StringPiece
& self
,
142 BASE_EXPORT StringPiece16
substr(const StringPiece16
& self
,
146 } // namespace internal
148 // BasicStringPiece ------------------------------------------------------------
150 // Defines the types, methods, operators, and data members common to both
151 // StringPiece and StringPiece16. Do not refer to this class directly, but
152 // rather to BasicStringPiece, StringPiece, or StringPiece16.
154 // This is templatized by string class type rather than character type, so
155 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
156 template <typename STRING_TYPE
> class BasicStringPiece
{
158 // Standard STL container boilerplate.
159 typedef size_t size_type
;
160 typedef typename
STRING_TYPE::value_type value_type
;
161 typedef const value_type
* pointer
;
162 typedef const value_type
& reference
;
163 typedef const value_type
& const_reference
;
164 typedef ptrdiff_t difference_type
;
165 typedef const value_type
* const_iterator
;
166 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
168 static const size_type npos
;
171 // We provide non-explicit singleton constructors so users can pass
172 // in a "const char*" or a "string" wherever a "StringPiece" is
173 // expected (likewise for char16, string16, StringPiece16).
174 BasicStringPiece() : ptr_(NULL
), length_(0) {}
175 BasicStringPiece(const value_type
* str
)
177 length_((str
== NULL
) ? 0 : STRING_TYPE::traits_type::length(str
)) {}
178 BasicStringPiece(const STRING_TYPE
& str
)
179 : ptr_(str
.data()), length_(str
.size()) {}
180 BasicStringPiece(const value_type
* offset
, size_type len
)
181 : ptr_(offset
), length_(len
) {}
182 BasicStringPiece(const typename
STRING_TYPE::const_iterator
& begin
,
183 const typename
STRING_TYPE::const_iterator
& end
)
184 : ptr_((end
> begin
) ? &(*begin
) : NULL
),
185 length_((end
> begin
) ? (size_type
)(end
- begin
) : 0) {}
187 // data() may return a pointer to a buffer with embedded NULs, and the
188 // returned buffer may or may not be null terminated. Therefore it is
189 // typically a mistake to pass data() to a routine that expects a NUL
190 // terminated string.
191 const value_type
* data() const { return ptr_
; }
192 size_type
size() const { return length_
; }
193 size_type
length() const { return length_
; }
194 bool empty() const { return length_
== 0; }
200 void set(const value_type
* data
, size_type len
) {
204 void set(const value_type
* str
) {
206 length_
= str
? STRING_TYPE::traits_type::length(str
) : 0;
209 value_type
operator[](size_type i
) const { return ptr_
[i
]; }
211 void remove_prefix(size_type n
) {
216 void remove_suffix(size_type n
) {
220 int compare(const BasicStringPiece
<STRING_TYPE
>& x
) const {
222 ptr_
, x
.ptr_
, (length_
< x
.length_
? length_
: x
.length_
));
224 if (length_
< x
.length_
) r
= -1;
225 else if (length_
> x
.length_
) r
= +1;
230 STRING_TYPE
as_string() const {
231 // std::string doesn't like to take a NULL pointer even with a 0 size.
232 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
235 const_iterator
begin() const { return ptr_
; }
236 const_iterator
end() const { return ptr_
+ length_
; }
237 const_reverse_iterator
rbegin() const {
238 return const_reverse_iterator(ptr_
+ length_
);
240 const_reverse_iterator
rend() const {
241 return const_reverse_iterator(ptr_
);
244 size_type
max_size() const { return length_
; }
245 size_type
capacity() const { return length_
; }
247 static int wordmemcmp(const value_type
* p
,
248 const value_type
* p2
,
250 return STRING_TYPE::traits_type::compare(p
, p2
, N
);
253 // Sets the value of the given string target type to be the current string.
254 // This saves a temporary over doing |a = b.as_string()|
255 void CopyToString(STRING_TYPE
* target
) const {
256 internal::CopyToString(*this, target
);
259 void AppendToString(STRING_TYPE
* target
) const {
260 internal::AppendToString(*this, target
);
263 size_type
copy(value_type
* buf
, size_type n
, size_type pos
= 0) const {
264 return internal::copy(*this, buf
, n
, pos
);
267 // Does "this" start with "x"
268 bool starts_with(const BasicStringPiece
& x
) const {
269 return ((this->length_
>= x
.length_
) &&
270 (wordmemcmp(this->ptr_
, x
.ptr_
, x
.length_
) == 0));
273 // Does "this" end with "x"
274 bool ends_with(const BasicStringPiece
& x
) const {
275 return ((this->length_
>= x
.length_
) &&
276 (wordmemcmp(this->ptr_
+ (this->length_
-x
.length_
),
277 x
.ptr_
, x
.length_
) == 0));
280 // find: Search for a character or substring at a given offset.
281 size_type
find(const BasicStringPiece
<STRING_TYPE
>& s
,
282 size_type pos
= 0) const {
283 return internal::find(*this, s
, pos
);
285 size_type
find(value_type c
, size_type pos
= 0) const {
286 return internal::find(*this, c
, pos
);
289 // rfind: Reverse find.
290 size_type
rfind(const BasicStringPiece
& s
,
291 size_type pos
= BasicStringPiece::npos
) const {
292 return internal::rfind(*this, s
, pos
);
294 size_type
rfind(value_type c
, size_type pos
= BasicStringPiece::npos
) const {
295 return internal::rfind(*this, c
, pos
);
298 // find_first_of: Find the first occurence of one of a set of characters.
299 size_type
find_first_of(const BasicStringPiece
& s
,
300 size_type pos
= 0) const {
301 return internal::find_first_of(*this, s
, pos
);
303 size_type
find_first_of(value_type c
, size_type pos
= 0) const {
307 // find_first_not_of: Find the first occurence not of a set of characters.
308 size_type
find_first_not_of(const BasicStringPiece
& s
,
309 size_type pos
= 0) const {
310 return internal::find_first_not_of(*this, s
, pos
);
312 size_type
find_first_not_of(value_type c
, size_type pos
= 0) const {
313 return internal::find_first_not_of(*this, c
, pos
);
316 // find_last_of: Find the last occurence of one of a set of characters.
317 size_type
find_last_of(const BasicStringPiece
& s
,
318 size_type pos
= BasicStringPiece::npos
) const {
319 return internal::find_last_of(*this, s
, pos
);
321 size_type
find_last_of(value_type c
,
322 size_type pos
= BasicStringPiece::npos
) const {
323 return rfind(c
, pos
);
326 // find_last_not_of: Find the last occurence not of a set of characters.
327 size_type
find_last_not_of(const BasicStringPiece
& s
,
328 size_type pos
= BasicStringPiece::npos
) const {
329 return internal::find_last_not_of(*this, s
, pos
);
331 size_type
find_last_not_of(value_type c
,
332 size_type pos
= BasicStringPiece::npos
) const {
333 return internal::find_last_not_of(*this, c
, pos
);
337 BasicStringPiece
substr(size_type pos
,
338 size_type n
= BasicStringPiece::npos
) const {
339 return internal::substr(*this, pos
, n
);
343 const value_type
* ptr_
;
347 template <typename STRING_TYPE
>
348 const typename BasicStringPiece
<STRING_TYPE
>::size_type
349 BasicStringPiece
<STRING_TYPE
>::npos
=
350 typename BasicStringPiece
<STRING_TYPE
>::size_type(-1);
352 // MSVC doesn't like complex extern templates and DLLs.
353 #if !defined(COMPILER_MSVC)
354 extern template class BASE_EXPORT BasicStringPiece
<std::string
>;
355 extern template class BASE_EXPORT BasicStringPiece
<string16
>;
358 // StingPiece operators --------------------------------------------------------
360 BASE_EXPORT
bool operator==(const StringPiece
& x
, const StringPiece
& y
);
362 inline bool operator!=(const StringPiece
& x
, const StringPiece
& y
) {
366 inline bool operator<(const StringPiece
& x
, const StringPiece
& y
) {
367 const int r
= StringPiece::wordmemcmp(
368 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
369 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
372 inline bool operator>(const StringPiece
& x
, const StringPiece
& y
) {
376 inline bool operator<=(const StringPiece
& x
, const StringPiece
& y
) {
380 inline bool operator>=(const StringPiece
& x
, const StringPiece
& y
) {
384 // StringPiece16 operators -----------------------------------------------------
386 inline bool operator==(const StringPiece16
& x
, const StringPiece16
& y
) {
387 if (x
.size() != y
.size())
390 return StringPiece16::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
393 inline bool operator!=(const StringPiece16
& x
, const StringPiece16
& y
) {
397 inline bool operator<(const StringPiece16
& x
, const StringPiece16
& y
) {
398 const int r
= StringPiece16::wordmemcmp(
399 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
400 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
403 inline bool operator>(const StringPiece16
& x
, const StringPiece16
& y
) {
407 inline bool operator<=(const StringPiece16
& x
, const StringPiece16
& y
) {
411 inline bool operator>=(const StringPiece16
& x
, const StringPiece16
& y
) {
415 BASE_EXPORT
std::ostream
& operator<<(std::ostream
& o
,
416 const StringPiece
& piece
);
420 // Hashing ---------------------------------------------------------------------
422 // We provide appropriate hash functions so StringPiece and StringPiece16 can
423 // be used as keys in hash sets and maps.
425 // This hash function is copied from base/containers/hash_tables.h. We don't
426 // use the ones already defined for string and string16 directly because it
427 // would require the string constructors to be called, which we don't want.
428 #define HASH_STRING_PIECE(StringPieceType, string_piece) \
429 std::size_t result = 0; \
430 for (StringPieceType::const_iterator i = string_piece.begin(); \
431 i != string_piece.end(); ++i) \
432 result = (result * 131) + *i; \
435 namespace BASE_HASH_NAMESPACE {
438 struct hash
<base::StringPiece
> {
439 std::size_t operator()(const base::StringPiece
& sp
) const {
440 HASH_STRING_PIECE(base::StringPiece
, sp
);
444 struct hash
<base::StringPiece16
> {
445 std::size_t operator()(const base::StringPiece16
& sp16
) const {
446 HASH_STRING_PIECE(base::StringPiece16
, sp16
);
450 } // namespace BASE_HASH_NAMESPACE
452 #endif // BASE_STRINGS_STRING_PIECE_H_