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 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
147 // Asserts that begin <= end to catch some errors with iterator usage.
148 BASE_EXPORT
void AssertIteratorsInOrder(std::string::const_iterator begin
,
149 std::string::const_iterator end
);
150 BASE_EXPORT
void AssertIteratorsInOrder(string16::const_iterator begin
,
151 string16::const_iterator end
);
154 } // namespace internal
156 // BasicStringPiece ------------------------------------------------------------
158 // Defines the types, methods, operators, and data members common to both
159 // StringPiece and StringPiece16. Do not refer to this class directly, but
160 // rather to BasicStringPiece, StringPiece, or StringPiece16.
162 // This is templatized by string class type rather than character type, so
163 // BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
164 template <typename STRING_TYPE
> class BasicStringPiece
{
166 // Standard STL container boilerplate.
167 typedef size_t size_type
;
168 typedef typename
STRING_TYPE::value_type value_type
;
169 typedef const value_type
* pointer
;
170 typedef const value_type
& reference
;
171 typedef const value_type
& const_reference
;
172 typedef ptrdiff_t difference_type
;
173 typedef const value_type
* const_iterator
;
174 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
176 static const size_type npos
;
179 // We provide non-explicit singleton constructors so users can pass
180 // in a "const char*" or a "string" wherever a "StringPiece" is
181 // expected (likewise for char16, string16, StringPiece16).
182 BasicStringPiece() : ptr_(NULL
), length_(0) {}
183 BasicStringPiece(const value_type
* str
)
185 length_((str
== NULL
) ? 0 : STRING_TYPE::traits_type::length(str
)) {}
186 BasicStringPiece(const STRING_TYPE
& str
)
187 : ptr_(str
.data()), length_(str
.size()) {}
188 BasicStringPiece(const value_type
* offset
, size_type len
)
189 : ptr_(offset
), length_(len
) {}
190 BasicStringPiece(const typename
STRING_TYPE::const_iterator
& begin
,
191 const typename
STRING_TYPE::const_iterator
& end
) {
192 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
193 // This assertion is done out-of-line to avoid bringing in logging.h and
194 // instantiating logging macros for every instantiation.
195 internal::AssertIteratorsInOrder(begin
, end
);
197 length_
= static_cast<size_t>(std::distance(begin
, end
));
199 // The length test before assignment is to avoid dereferencing an iterator
200 // that may point to the end() of a string.
201 ptr_
= length_
> 0 ? &*begin
: nullptr;
204 // data() may return a pointer to a buffer with embedded NULs, and the
205 // returned buffer may or may not be null terminated. Therefore it is
206 // typically a mistake to pass data() to a routine that expects a NUL
207 // terminated string.
208 const value_type
* data() const { return ptr_
; }
209 size_type
size() const { return length_
; }
210 size_type
length() const { return length_
; }
211 bool empty() const { return length_
== 0; }
217 void set(const value_type
* data
, size_type len
) {
221 void set(const value_type
* str
) {
223 length_
= str
? STRING_TYPE::traits_type::length(str
) : 0;
226 value_type
operator[](size_type i
) const { return ptr_
[i
]; }
228 void remove_prefix(size_type n
) {
233 void remove_suffix(size_type n
) {
237 int compare(const BasicStringPiece
<STRING_TYPE
>& x
) const {
239 ptr_
, x
.ptr_
, (length_
< x
.length_
? length_
: x
.length_
));
241 if (length_
< x
.length_
) r
= -1;
242 else if (length_
> x
.length_
) r
= +1;
247 STRING_TYPE
as_string() const {
248 // std::string doesn't like to take a NULL pointer even with a 0 size.
249 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
252 const_iterator
begin() const { return ptr_
; }
253 const_iterator
end() const { return ptr_
+ length_
; }
254 const_reverse_iterator
rbegin() const {
255 return const_reverse_iterator(ptr_
+ length_
);
257 const_reverse_iterator
rend() const {
258 return const_reverse_iterator(ptr_
);
261 size_type
max_size() const { return length_
; }
262 size_type
capacity() const { return length_
; }
264 static int wordmemcmp(const value_type
* p
,
265 const value_type
* p2
,
267 return STRING_TYPE::traits_type::compare(p
, p2
, N
);
270 // Sets the value of the given string target type to be the current string.
271 // This saves a temporary over doing |a = b.as_string()|
272 void CopyToString(STRING_TYPE
* target
) const {
273 internal::CopyToString(*this, target
);
276 void AppendToString(STRING_TYPE
* target
) const {
277 internal::AppendToString(*this, target
);
280 size_type
copy(value_type
* buf
, size_type n
, size_type pos
= 0) const {
281 return internal::copy(*this, buf
, n
, pos
);
284 // Does "this" start with "x"
285 bool starts_with(const BasicStringPiece
& x
) const {
286 return ((this->length_
>= x
.length_
) &&
287 (wordmemcmp(this->ptr_
, x
.ptr_
, x
.length_
) == 0));
290 // Does "this" end with "x"
291 bool ends_with(const BasicStringPiece
& x
) const {
292 return ((this->length_
>= x
.length_
) &&
293 (wordmemcmp(this->ptr_
+ (this->length_
-x
.length_
),
294 x
.ptr_
, x
.length_
) == 0));
297 // find: Search for a character or substring at a given offset.
298 size_type
find(const BasicStringPiece
<STRING_TYPE
>& s
,
299 size_type pos
= 0) const {
300 return internal::find(*this, s
, pos
);
302 size_type
find(value_type c
, size_type pos
= 0) const {
303 return internal::find(*this, c
, pos
);
306 // rfind: Reverse find.
307 size_type
rfind(const BasicStringPiece
& s
,
308 size_type pos
= BasicStringPiece::npos
) const {
309 return internal::rfind(*this, s
, pos
);
311 size_type
rfind(value_type c
, size_type pos
= BasicStringPiece::npos
) const {
312 return internal::rfind(*this, c
, pos
);
315 // find_first_of: Find the first occurence of one of a set of characters.
316 size_type
find_first_of(const BasicStringPiece
& s
,
317 size_type pos
= 0) const {
318 return internal::find_first_of(*this, s
, pos
);
320 size_type
find_first_of(value_type c
, size_type pos
= 0) const {
324 // find_first_not_of: Find the first occurence not of a set of characters.
325 size_type
find_first_not_of(const BasicStringPiece
& s
,
326 size_type pos
= 0) const {
327 return internal::find_first_not_of(*this, s
, pos
);
329 size_type
find_first_not_of(value_type c
, size_type pos
= 0) const {
330 return internal::find_first_not_of(*this, c
, pos
);
333 // find_last_of: Find the last occurence of one of a set of characters.
334 size_type
find_last_of(const BasicStringPiece
& s
,
335 size_type pos
= BasicStringPiece::npos
) const {
336 return internal::find_last_of(*this, s
, pos
);
338 size_type
find_last_of(value_type c
,
339 size_type pos
= BasicStringPiece::npos
) const {
340 return rfind(c
, pos
);
343 // find_last_not_of: Find the last occurence not of a set of characters.
344 size_type
find_last_not_of(const BasicStringPiece
& s
,
345 size_type pos
= BasicStringPiece::npos
) const {
346 return internal::find_last_not_of(*this, s
, pos
);
348 size_type
find_last_not_of(value_type c
,
349 size_type pos
= BasicStringPiece::npos
) const {
350 return internal::find_last_not_of(*this, c
, pos
);
354 BasicStringPiece
substr(size_type pos
,
355 size_type n
= BasicStringPiece::npos
) const {
356 return internal::substr(*this, pos
, n
);
360 const value_type
* ptr_
;
364 template <typename STRING_TYPE
>
365 const typename BasicStringPiece
<STRING_TYPE
>::size_type
366 BasicStringPiece
<STRING_TYPE
>::npos
=
367 typename BasicStringPiece
<STRING_TYPE
>::size_type(-1);
369 // MSVC doesn't like complex extern templates and DLLs.
370 #if !defined(COMPILER_MSVC)
371 extern template class BASE_EXPORT BasicStringPiece
<std::string
>;
372 extern template class BASE_EXPORT BasicStringPiece
<string16
>;
375 // StingPiece operators --------------------------------------------------------
377 BASE_EXPORT
bool operator==(const StringPiece
& x
, const StringPiece
& y
);
379 inline bool operator!=(const StringPiece
& x
, const StringPiece
& y
) {
383 inline bool operator<(const StringPiece
& x
, const StringPiece
& y
) {
384 const int r
= StringPiece::wordmemcmp(
385 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
386 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
389 inline bool operator>(const StringPiece
& x
, const StringPiece
& y
) {
393 inline bool operator<=(const StringPiece
& x
, const StringPiece
& y
) {
397 inline bool operator>=(const StringPiece
& x
, const StringPiece
& y
) {
401 // StringPiece16 operators -----------------------------------------------------
403 inline bool operator==(const StringPiece16
& x
, const StringPiece16
& y
) {
404 if (x
.size() != y
.size())
407 return StringPiece16::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
410 inline bool operator!=(const StringPiece16
& x
, const StringPiece16
& y
) {
414 inline bool operator<(const StringPiece16
& x
, const StringPiece16
& y
) {
415 const int r
= StringPiece16::wordmemcmp(
416 x
.data(), y
.data(), (x
.size() < y
.size() ? x
.size() : y
.size()));
417 return ((r
< 0) || ((r
== 0) && (x
.size() < y
.size())));
420 inline bool operator>(const StringPiece16
& x
, const StringPiece16
& y
) {
424 inline bool operator<=(const StringPiece16
& x
, const StringPiece16
& y
) {
428 inline bool operator>=(const StringPiece16
& x
, const StringPiece16
& y
) {
432 BASE_EXPORT
std::ostream
& operator<<(std::ostream
& o
,
433 const StringPiece
& piece
);
437 // Hashing ---------------------------------------------------------------------
439 // We provide appropriate hash functions so StringPiece and StringPiece16 can
440 // be used as keys in hash sets and maps.
442 // This hash function is copied from base/containers/hash_tables.h. We don't
443 // use the ones already defined for string and string16 directly because it
444 // would require the string constructors to be called, which we don't want.
445 #define HASH_STRING_PIECE(StringPieceType, string_piece) \
446 std::size_t result = 0; \
447 for (StringPieceType::const_iterator i = string_piece.begin(); \
448 i != string_piece.end(); ++i) \
449 result = (result * 131) + *i; \
452 namespace BASE_HASH_NAMESPACE {
455 struct hash
<base::StringPiece
> {
456 std::size_t operator()(const base::StringPiece
& sp
) const {
457 HASH_STRING_PIECE(base::StringPiece
, sp
);
461 struct hash
<base::StringPiece16
> {
462 std::size_t operator()(const base::StringPiece16
& sp16
) const {
463 HASH_STRING_PIECE(base::StringPiece16
, sp16
);
467 } // namespace BASE_HASH_NAMESPACE
469 #endif // BASE_STRINGS_STRING_PIECE_H_