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 // 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.
14 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary
15 // conversions from "const char*" to "string" and back again.
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.
23 #ifndef BASE_STRINGS_STRING_PIECE_H_
24 #define BASE_STRINGS_STRING_PIECE_H_
31 #include "base/base_export.h"
32 #include "base/basictypes.h"
33 #include "base/containers/hash_tables.h"
34 #include "base/strings/string16.h"
38 template <typename STRING_TYPE
> class BasicStringPiece
;
39 typedef BasicStringPiece
<std::string
> StringPiece
;
40 typedef BasicStringPiece
<string16
> StringPiece16
;
42 // internal --------------------------------------------------------------------
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.
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.
53 BASE_EXPORT
void CopyToString(const StringPiece
& self
, std::string
* target
);
54 BASE_EXPORT
void CopyToString(const StringPiece16
& self
, string16
* target
);
56 BASE_EXPORT
void AppendToString(const StringPiece
& self
, std::string
* target
);
57 BASE_EXPORT
void AppendToString(const StringPiece16
& self
, string16
* target
);
59 BASE_EXPORT
size_t copy(const StringPiece
& self
,
63 BASE_EXPORT
size_t copy(const StringPiece16
& self
,
68 BASE_EXPORT
size_t find(const StringPiece
& self
,
71 BASE_EXPORT
size_t find(const StringPiece16
& self
,
72 const StringPiece16
& s
,
74 BASE_EXPORT
size_t find(const StringPiece
& self
,
77 BASE_EXPORT
size_t find(const StringPiece16
& self
,
81 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
84 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
85 const StringPiece16
& s
,
87 BASE_EXPORT
size_t rfind(const StringPiece
& self
,
90 BASE_EXPORT
size_t rfind(const StringPiece16
& self
,
94 BASE_EXPORT
size_t find_first_of(const StringPiece
& self
,
97 BASE_EXPORT
size_t find_first_of(const StringPiece16
& self
,
98 const StringPiece16
& s
,
101 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
102 const StringPiece
& s
,
104 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
105 const StringPiece16
& s
,
107 BASE_EXPORT
size_t find_first_not_of(const StringPiece
& self
,
110 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
114 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
115 const StringPiece
& s
,
117 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
118 const StringPiece16
& s
,
120 BASE_EXPORT
size_t find_last_of(const StringPiece
& self
,
123 BASE_EXPORT
size_t find_last_of(const StringPiece16
& self
,
127 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
128 const StringPiece
& s
,
130 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
131 const StringPiece16
& s
,
133 BASE_EXPORT
size_t find_last_not_of(const StringPiece16
& self
,
136 BASE_EXPORT
size_t find_last_not_of(const StringPiece
& self
,
140 BASE_EXPORT StringPiece
substr(const StringPiece
& self
,
143 BASE_EXPORT StringPiece16
substr(const StringPiece16
& self
,
147 } // namespace internal
149 // BasicStringPiece ------------------------------------------------------------
151 // 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.
155 // This is templatized by string class type rather than character type, so
156 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
157 template <typename STRING_TYPE
> class BasicStringPiece
{
159 // Standard STL container boilerplate.
160 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
;
169 static const size_type npos
;
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).
175 BasicStringPiece() : ptr_(NULL
), length_(0) {}
176 BasicStringPiece(const value_type
* str
)
178 length_((str
== NULL
) ? 0 : STRING_TYPE::traits_type::length(str
)) {}
179 BasicStringPiece(const STRING_TYPE
& str
)
180 : ptr_(str
.data()), length_(str
.size()) {}
181 BasicStringPiece(const value_type
* offset
, size_type len
)
182 : ptr_(offset
), length_(len
) {}
183 BasicStringPiece(const typename
STRING_TYPE::const_iterator
& begin
,
184 const typename
STRING_TYPE::const_iterator
& end
)
185 : ptr_((end
> begin
) ? &(*begin
) : NULL
),
186 length_((end
> begin
) ? (size_type
)(end
- begin
) : 0) {}
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; }
201 void set(const value_type
* data
, size_type len
) {
205 void set(const value_type
* str
) {
207 length_
= str
? STRING_TYPE::traits_type::length(str
) : 0;
210 value_type
operator[](size_type i
) const { return ptr_
[i
]; }
212 void remove_prefix(size_type n
) {
217 void remove_suffix(size_type n
) {
221 int compare(const BasicStringPiece
<STRING_TYPE
>& x
) const {
223 ptr_
, x
.ptr_
, (length_
< x
.length_
? length_
: x
.length_
));
225 if (length_
< x
.length_
) r
= -1;
226 else if (length_
> x
.length_
) r
= +1;
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());
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_
);
241 const_reverse_iterator
rend() const {
242 return const_reverse_iterator(ptr_
);
245 size_type
max_size() const { return length_
; }
246 size_type
capacity() const { return length_
; }
248 static int wordmemcmp(const value_type
* p
,
249 const value_type
* p2
,
251 return STRING_TYPE::traits_type::compare(p
, p2
, N
);
254 // 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
);
260 void AppendToString(STRING_TYPE
* target
) const {
261 internal::AppendToString(*this, target
);
264 size_type
copy(value_type
* buf
, size_type n
, size_type pos
= 0) const {
265 return internal::copy(*this, buf
, n
, pos
);
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));
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));
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
);
286 size_type
find(value_type c
, size_type pos
= 0) const {
287 return internal::find(*this, c
, pos
);
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
);
295 size_type
rfind(value_type c
, size_type pos
= BasicStringPiece::npos
) const {
296 return internal::rfind(*this, c
, pos
);
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
);
304 size_type
find_first_of(value_type c
, size_type pos
= 0) const {
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
);
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
);
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
);
322 size_type
find_last_of(value_type c
,
323 size_type pos
= BasicStringPiece::npos
) const {
324 return rfind(c
, pos
);
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
);
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
);
338 BasicStringPiece
substr(size_type pos
,
339 size_type n
= BasicStringPiece::npos
) const {
340 return internal::substr(*this, pos
, n
);
344 const value_type
* ptr_
;
348 template <typename STRING_TYPE
>
349 const typename BasicStringPiece
<STRING_TYPE
>::size_type
350 BasicStringPiece
<STRING_TYPE
>::npos
=
351 typename BasicStringPiece
<STRING_TYPE
>::size_type(-1);
353 // MSVC doesn't like complex extern templates and DLLs.
354 #if !defined(COMPILER_MSVC)
355 extern template class BASE_EXPORT BasicStringPiece
<std::string
>;
356 extern template class BASE_EXPORT BasicStringPiece
<string16
>;
359 // StingPiece operators --------------------------------------------------------
361 BASE_EXPORT
bool operator==(const StringPiece
& x
, const StringPiece
& y
);
363 inline bool operator!=(const StringPiece
& x
, const StringPiece
& y
) {
367 inline 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())));
373 inline bool operator>(const StringPiece
& x
, const StringPiece
& y
) {
377 inline bool operator<=(const StringPiece
& x
, const StringPiece
& y
) {
381 inline bool operator>=(const StringPiece
& x
, const StringPiece
& y
) {
385 // StringPiece16 operators -----------------------------------------------------
387 inline bool operator==(const StringPiece16
& x
, const StringPiece16
& y
) {
388 if (x
.size() != y
.size())
391 return StringPiece16::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
394 inline bool operator!=(const StringPiece16
& x
, const StringPiece16
& y
) {
398 inline 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())));
404 inline bool operator>(const StringPiece16
& x
, const StringPiece16
& y
) {
408 inline bool operator<=(const StringPiece16
& x
, const StringPiece16
& y
) {
412 inline bool operator>=(const StringPiece16
& x
, const StringPiece16
& y
) {
416 BASE_EXPORT
std::ostream
& operator<<(std::ostream
& o
,
417 const StringPiece
& piece
);
421 // Hashing ---------------------------------------------------------------------
423 // We provide appropriate hash functions so StringPiece and StringPiece16 can
424 // be used as keys in hash sets and maps.
426 // 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.
429 #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; \
436 namespace BASE_HASH_NAMESPACE {
437 #if defined(COMPILER_GCC)
440 struct hash
<base::StringPiece
> {
441 std::size_t operator()(const base::StringPiece
& sp
) const {
442 HASH_STRING_PIECE(base::StringPiece
, sp
);
446 struct hash
<base::StringPiece16
> {
447 std::size_t operator()(const base::StringPiece16
& sp16
) const {
448 HASH_STRING_PIECE(base::StringPiece16
, sp16
);
452 #elif defined(COMPILER_MSVC)
454 inline size_t hash_value(const base::StringPiece
& sp
) {
455 HASH_STRING_PIECE(base::StringPiece
, sp
);
457 inline size_t hash_value(const base::StringPiece16
& sp16
) {
458 HASH_STRING_PIECE(base::StringPiece16
, sp16
);
463 } // namespace BASE_HASH_NAMESPACE
465 #endif // BASE_STRINGS_STRING_PIECE_H_