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 // StringPiece16 is similar to StringPiece but for base::string16 instead of
23 // std::string. We do not define as large of a subset of the STL functions
24 // from basic_string as in StringPiece, but this can be changed if these
25 // functions (find, find_first_of, etc.) are found to be useful in this context.
28 #ifndef BASE_STRINGS_STRING_PIECE_H_
29 #define BASE_STRINGS_STRING_PIECE_H_
36 #include "base/base_export.h"
37 #include "base/basictypes.h"
38 #include "base/containers/hash_tables.h"
39 #include "base/strings/string16.h"
43 template <typename STRING_TYPE
> class BasicStringPiece
;
44 typedef BasicStringPiece
<std::string
> StringPiece
;
45 typedef BasicStringPiece
<string16
> StringPiece16
;
47 // internal --------------------------------------------------------------------
49 // Many of the StringPiece functions use different implementations for the
50 // 8-bit and 16-bit versions, and we don't want lots of template expansions in
51 // this (very common) header that will slow down compilation.
53 // So here we define overloaded functions called by the StringPiece template.
54 // For those that share an implementation, the two versions will expand to a
55 // template internal to the .cc file.
58 BASE_EXPORT
void CopyToString(const StringPiece
& self
, std::string
* target
);
59 BASE_EXPORT
void CopyToString(const StringPiece16
& self
, string16
* target
);
61 BASE_EXPORT
void AppendToString(const StringPiece
& self
, std::string
* target
);
62 BASE_EXPORT
void AppendToString(const StringPiece16
& self
, string16
* target
);
64 BASE_EXPORT
size_t copy(const StringPiece
& self
,
68 BASE_EXPORT
size_t copy(const StringPiece16
& self
,
73 BASE_EXPORT
size_t find(const StringPiece
& self
,
76 BASE_EXPORT
size_t find(const StringPiece16
& self
,
77 const StringPiece16
& s
,
79 BASE_EXPORT
size_t find(const StringPiece
& self
,
82 BASE_EXPORT
size_t find(const StringPiece16
& self
,
86 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
89 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
90 const StringPiece16
& s
,
92 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
95 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
99 BASE_EXPORT
size_t find_first_of(const StringPiece
& self
,
100 const StringPiece
& s
,
102 BASE_EXPORT
size_t find_first_of(const StringPiece16
& self
,
103 const StringPiece16
& s
,
106 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
107 const StringPiece
& s
,
109 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
110 const StringPiece16
& s
,
112 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
115 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
119 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
120 const StringPiece
& s
,
122 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
123 const StringPiece16
& s
,
125 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
128 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
132 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
133 const StringPiece
& s
,
135 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
136 const StringPiece16
& s
,
138 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
141 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
145 BASE_EXPORT StringPiece
substr(const StringPiece
& self
,
148 BASE_EXPORT StringPiece16
substr(const StringPiece16
& self
,
152 } // namespace internal
154 // BasicStringPiece ------------------------------------------------------------
156 // Defines the types, methods, operators, and data members common to both
157 // StringPiece and StringPiece16. Do not refer to this class directly, but
158 // rather to BasicStringPiece, StringPiece, or StringPiece16.
160 // This is templatized by string class type rather than character type, so
161 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
162 template <typename STRING_TYPE
> class BasicStringPiece
{
164 // Standard STL container boilerplate.
165 typedef size_t size_type
;
166 typedef typename
STRING_TYPE::value_type value_type
;
167 typedef const value_type
* pointer
;
168 typedef const value_type
& reference
;
169 typedef const value_type
& const_reference
;
170 typedef ptrdiff_t difference_type
;
171 typedef const value_type
* const_iterator
;
172 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
174 static const size_type npos
;
177 // We provide non-explicit singleton constructors so users can pass
178 // in a "const char*" or a "string" wherever a "StringPiece" is
179 // expected (likewise for char16, string16, StringPiece16).
180 BasicStringPiece() : ptr_(NULL
), length_(0) {}
181 BasicStringPiece(const value_type
* str
)
183 length_((str
== NULL
) ? 0 : STRING_TYPE::traits_type::length(str
)) {}
184 BasicStringPiece(const STRING_TYPE
& str
)
185 : ptr_(str
.data()), length_(str
.size()) {}
186 BasicStringPiece(const value_type
* offset
, size_type len
)
187 : ptr_(offset
), length_(len
) {}
188 BasicStringPiece(const typename
STRING_TYPE::const_iterator
& begin
,
189 const typename
STRING_TYPE::const_iterator
& end
)
190 : ptr_((end
> begin
) ? &(*begin
) : NULL
),
191 length_((end
> begin
) ? (size_type
)(end
- begin
) : 0) {}
193 // data() may return a pointer to a buffer with embedded NULs, and the
194 // returned buffer may or may not be null terminated. Therefore it is
195 // typically a mistake to pass data() to a routine that expects a NUL
196 // terminated string.
197 const value_type
* data() const { return ptr_
; }
198 size_type
size() const { return length_
; }
199 size_type
length() const { return length_
; }
200 bool empty() const { return length_
== 0; }
206 void set(const value_type
* data
, size_type len
) {
210 void set(const value_type
* str
) {
212 length_
= str
? STRING_TYPE::traits_type::length(str
) : 0;
215 value_type
operator[](size_type i
) const { return ptr_
[i
]; }
217 void remove_prefix(size_type n
) {
222 void remove_suffix(size_type n
) {
226 int compare(const BasicStringPiece
<STRING_TYPE
>& x
) const {
228 ptr_
, x
.ptr_
, (length_
< x
.length_
? length_
: x
.length_
));
230 if (length_
< x
.length_
) r
= -1;
231 else if (length_
> x
.length_
) r
= +1;
236 STRING_TYPE
as_string() const {
237 // std::string doesn't like to take a NULL pointer even with a 0 size.
238 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
241 const_iterator
begin() const { return ptr_
; }
242 const_iterator
end() const { return ptr_
+ length_
; }
243 const_reverse_iterator
rbegin() const {
244 return const_reverse_iterator(ptr_
+ length_
);
246 const_reverse_iterator
rend() const {
247 return const_reverse_iterator(ptr_
);
250 size_type
max_size() const { return length_
; }
251 size_type
capacity() const { return length_
; }
253 static int wordmemcmp(const value_type
* p
,
254 const value_type
* p2
,
256 return STRING_TYPE::traits_type::compare(p
, p2
, N
);
259 // Sets the value of the given string target type to be the current string.
260 // This saves a temporary over doing |a = b.as_string()|
261 void CopyToString(STRING_TYPE
* target
) const {
262 internal::CopyToString(*this, target
);
265 void AppendToString(STRING_TYPE
* target
) const {
266 internal::AppendToString(*this, target
);
269 size_type
copy(value_type
* buf
, size_type n
, size_type pos
= 0) const {
270 return internal::copy(*this, buf
, n
, pos
);
273 // Does "this" start with "x"
274 bool starts_with(const BasicStringPiece
& x
) const {
275 return ((this->length_
>= x
.length_
) &&
276 (wordmemcmp(this->ptr_
, x
.ptr_
, x
.length_
) == 0));
279 // Does "this" end with "x"
280 bool ends_with(const BasicStringPiece
& x
) const {
281 return ((this->length_
>= x
.length_
) &&
282 (wordmemcmp(this->ptr_
+ (this->length_
-x
.length_
),
283 x
.ptr_
, x
.length_
) == 0));
286 // find: Search for a character or substring at a given offset.
287 size_type
find(const BasicStringPiece
<STRING_TYPE
>& s
,
288 size_type pos
= 0) const {
289 return internal::find(*this, s
, pos
);
291 size_type
find(value_type c
, size_type pos
= 0) const {
292 return internal::find(*this, c
, pos
);
295 // rfind: Reverse find.
296 size_type
rfind(const BasicStringPiece
& s
,
297 size_type pos
= BasicStringPiece::npos
) const {
298 return internal::rfind(*this, s
, pos
);
300 size_type
rfind(value_type c
, size_type pos
= BasicStringPiece::npos
) const {
301 return internal::rfind(*this, c
, pos
);
304 // find_first_of: Find the first occurence of one of a set of characters.
305 size_type
find_first_of(const BasicStringPiece
& s
,
306 size_type pos
= 0) const {
307 return internal::find_first_of(*this, s
, pos
);
309 size_type
find_first_of(value_type c
, size_type pos
= 0) const {
313 // find_first_not_of: Find the first occurence not of a set of characters.
314 size_type
find_first_not_of(const BasicStringPiece
& s
,
315 size_type pos
= 0) const {
316 return internal::find_first_not_of(*this, s
, pos
);
318 size_type
find_first_not_of(value_type c
, size_type pos
= 0) const {
319 return internal::find_first_not_of(*this, c
, pos
);
322 // find_last_of: Find the last occurence of one of a set of characters.
323 size_type
find_last_of(const BasicStringPiece
& s
,
324 size_type pos
= BasicStringPiece::npos
) const {
325 return internal::find_last_of(*this, s
, pos
);
327 size_type
find_last_of(value_type c
,
328 size_type pos
= BasicStringPiece::npos
) const {
329 return rfind(c
, pos
);
332 // find_last_not_of: Find the last occurence not of a set of characters.
333 size_type
find_last_not_of(const BasicStringPiece
& s
,
334 size_type pos
= BasicStringPiece::npos
) const {
335 return internal::find_last_not_of(*this, s
, pos
);
337 size_type
find_last_not_of(value_type c
,
338 size_type pos
= BasicStringPiece::npos
) const {
339 return internal::find_last_not_of(*this, c
, pos
);
343 BasicStringPiece
substr(size_type pos
,
344 size_type n
= BasicStringPiece::npos
) const {
345 return internal::substr(*this, pos
, n
);
349 const value_type
* ptr_
;
353 template <typename STRING_TYPE
>
354 const typename BasicStringPiece
<STRING_TYPE
>::size_type
355 BasicStringPiece
<STRING_TYPE
>::npos
=
356 typename BasicStringPiece
<STRING_TYPE
>::size_type(-1);
358 // MSVC doesn't like complex extern templates and DLLs.
359 #if !defined(COMPILER_MSVC)
360 extern template class BASE_EXPORT BasicStringPiece
<std::string
>;
361 extern template class BASE_EXPORT BasicStringPiece
<string16
>;
364 // StingPiece operators --------------------------------------------------------
366 BASE_EXPORT
bool operator==(const StringPiece
& x
, const StringPiece
& y
);
368 inline bool operator!=(const StringPiece
& x
, const StringPiece
& y
) {
372 inline bool operator<(const StringPiece
& x
, const StringPiece
& y
) {
373 const int r
= StringPiece::wordmemcmp(
374 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
375 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
378 inline bool operator>(const StringPiece
& x
, const StringPiece
& y
) {
382 inline bool operator<=(const StringPiece
& x
, const StringPiece
& y
) {
386 inline bool operator>=(const StringPiece
& x
, const StringPiece
& y
) {
390 // StringPiece16 operators -----------------------------------------------------
392 inline bool operator==(const StringPiece16
& x
, const StringPiece16
& y
) {
393 if (x
.size() != y
.size())
396 return StringPiece16::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
399 inline bool operator!=(const StringPiece16
& x
, const StringPiece16
& y
) {
403 inline bool operator<(const StringPiece16
& x
, const StringPiece16
& y
) {
404 const int r
= StringPiece16::wordmemcmp(
405 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
406 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
409 inline bool operator>(const StringPiece16
& x
, const StringPiece16
& y
) {
413 inline bool operator<=(const StringPiece16
& x
, const StringPiece16
& y
) {
417 inline bool operator>=(const StringPiece16
& x
, const StringPiece16
& y
) {
421 BASE_EXPORT
std::ostream
& operator<<(std::ostream
& o
,
422 const StringPiece
& piece
);
426 // Hashing ---------------------------------------------------------------------
428 // We provide appropriate hash functions so StringPiece and StringPiece16 can
429 // be used as keys in hash sets and maps.
431 // This hash function is copied from base/containers/hash_tables.h. We don't
432 // use the ones already defined for string and string16 directly because it
433 // would require the string constructors to be called, which we don't want.
434 #define HASH_STRING_PIECE(StringPieceType, string_piece) \
435 std::size_t result = 0; \
436 for (StringPieceType::const_iterator i = string_piece.begin(); \
437 i != string_piece.end(); ++i) \
438 result = (result * 131) + *i; \
441 namespace BASE_HASH_NAMESPACE {
444 struct hash
<base::StringPiece
> {
445 std::size_t operator()(const base::StringPiece
& sp
) const {
446 HASH_STRING_PIECE(base::StringPiece
, sp
);
450 struct hash
<base::StringPiece16
> {
451 std::size_t operator()(const base::StringPiece16
& sp16
) const {
452 HASH_STRING_PIECE(base::StringPiece16
, sp16
);
456 } // namespace BASE_HASH_NAMESPACE
458 #endif // BASE_STRINGS_STRING_PIECE_H_