blob: eaec14de5da788ebab2137df35015b9998ec892e [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//
[email protected]16b200c2014-06-24 02:55:218// 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.
[email protected]7d7b0ac2013-03-28 20:07:4013//
[email protected]16b200c2014-06-24 02:55:2114// 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.
[email protected]7d7b0ac2013-03-28 20:07:4021
22#ifndef BASE_STRINGS_STRING_PIECE_H_
23#define BASE_STRINGS_STRING_PIECE_H_
24
25#include <stddef.h>
26
27#include <iosfwd>
28#include <string>
29
30#include "base/base_export.h"
olli.raula570930f2015-10-12 22:10:5631#include "base/logging.h"
[email protected]c851cfd2013-06-10 20:11:1432#include "base/strings/string16.h"
[email protected]7d7b0ac2013-03-28 20:07:4033
34namespace base {
35
36template <typename STRING_TYPE> class BasicStringPiece;
37typedef BasicStringPiece<std::string> StringPiece;
38typedef BasicStringPiece<string16> StringPiece16;
39
[email protected]0ecab7892014-03-11 21:15:4040// internal --------------------------------------------------------------------
41
42// Many of the StringPiece functions use different implementations for the
43// 8-bit and 16-bit versions, and we don't want lots of template expansions in
44// this (very common) header that will slow down compilation.
45//
46// So here we define overloaded functions called by the StringPiece template.
47// For those that share an implementation, the two versions will expand to a
48// template internal to the .cc file.
[email protected]7d7b0ac2013-03-28 20:07:4049namespace internal {
50
[email protected]0ecab7892014-03-11 21:15:4051BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target);
52BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target);
53
54BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target);
55BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target);
56
57BASE_EXPORT size_t copy(const StringPiece& self,
58 char* buf,
59 size_t n,
60 size_t pos);
61BASE_EXPORT size_t copy(const StringPiece16& self,
62 char16* buf,
63 size_t n,
64 size_t pos);
65
66BASE_EXPORT size_t find(const StringPiece& self,
67 const StringPiece& s,
68 size_t pos);
69BASE_EXPORT size_t find(const StringPiece16& self,
70 const StringPiece16& s,
71 size_t pos);
72BASE_EXPORT size_t find(const StringPiece& self,
73 char c,
74 size_t pos);
75BASE_EXPORT size_t find(const StringPiece16& self,
76 char16 c,
77 size_t pos);
78
79BASE_EXPORT size_t rfind(const StringPiece& self,
80 const StringPiece& s,
81 size_t pos);
82BASE_EXPORT size_t rfind(const StringPiece16& self,
83 const StringPiece16& s,
84 size_t pos);
85BASE_EXPORT size_t rfind(const StringPiece& self,
86 char c,
87 size_t pos);
88BASE_EXPORT size_t rfind(const StringPiece16& self,
89 char16 c,
90 size_t pos);
91
92BASE_EXPORT size_t find_first_of(const StringPiece& self,
93 const StringPiece& s,
94 size_t pos);
95BASE_EXPORT size_t find_first_of(const StringPiece16& self,
96 const StringPiece16& s,
97 size_t pos);
98
99BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
100 const StringPiece& s,
101 size_t pos);
102BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
103 const StringPiece16& s,
104 size_t pos);
105BASE_EXPORT size_t find_first_not_of(const StringPiece& self,
106 char c,
107 size_t pos);
108BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
109 char16 c,
110 size_t pos);
111
112BASE_EXPORT size_t find_last_of(const StringPiece& self,
113 const StringPiece& s,
114 size_t pos);
115BASE_EXPORT size_t find_last_of(const StringPiece16& self,
116 const StringPiece16& s,
117 size_t pos);
118BASE_EXPORT size_t find_last_of(const StringPiece& self,
119 char c,
120 size_t pos);
121BASE_EXPORT size_t find_last_of(const StringPiece16& self,
122 char16 c,
123 size_t pos);
124
125BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
126 const StringPiece& s,
127 size_t pos);
128BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
129 const StringPiece16& s,
130 size_t pos);
131BASE_EXPORT size_t find_last_not_of(const StringPiece16& self,
132 char16 c,
133 size_t pos);
134BASE_EXPORT size_t find_last_not_of(const StringPiece& self,
135 char c,
136 size_t pos);
137
138BASE_EXPORT StringPiece substr(const StringPiece& self,
139 size_t pos,
140 size_t n);
141BASE_EXPORT StringPiece16 substr(const StringPiece16& self,
142 size_t pos,
143 size_t n);
144
olli.raula570930f2015-10-12 22:10:56145#if DCHECK_IS_ON()
brettwf22866d2015-07-27 22:22:26146// Asserts that begin <= end to catch some errors with iterator usage.
147BASE_EXPORT void AssertIteratorsInOrder(std::string::const_iterator begin,
148 std::string::const_iterator end);
149BASE_EXPORT void AssertIteratorsInOrder(string16::const_iterator begin,
150 string16::const_iterator end);
151#endif
152
[email protected]0ecab7892014-03-11 21:15:40153} // namespace internal
154
155// BasicStringPiece ------------------------------------------------------------
156
[email protected]7d7b0ac2013-03-28 20:07:40157// Defines the types, methods, operators, and data members common to both
158// StringPiece and StringPiece16. Do not refer to this class directly, but
159// rather to BasicStringPiece, StringPiece, or StringPiece16.
[email protected]0ecab7892014-03-11 21:15:40160//
161// This is templatized by string class type rather than character type, so
162// BasicStringPiece<std::string> or BasicStringPiece<base::string16>.
163template <typename STRING_TYPE> class BasicStringPiece {
[email protected]7d7b0ac2013-03-28 20:07:40164 public:
[email protected]0ecab7892014-03-11 21:15:40165 // Standard STL container boilerplate.
[email protected]7d7b0ac2013-03-28 20:07:40166 typedef size_t size_type;
167 typedef typename STRING_TYPE::value_type value_type;
168 typedef const value_type* pointer;
169 typedef const value_type& reference;
170 typedef const value_type& const_reference;
171 typedef ptrdiff_t difference_type;
172 typedef const value_type* const_iterator;
173 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
174
175 static const size_type npos;
176
177 public:
178 // We provide non-explicit singleton constructors so users can pass
179 // in a "const char*" or a "string" wherever a "StringPiece" is
180 // expected (likewise for char16, string16, StringPiece16).
[email protected]0ecab7892014-03-11 21:15:40181 BasicStringPiece() : ptr_(NULL), length_(0) {}
182 BasicStringPiece(const value_type* str)
[email protected]7d7b0ac2013-03-28 20:07:40183 : ptr_(str),
184 length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
[email protected]0ecab7892014-03-11 21:15:40185 BasicStringPiece(const STRING_TYPE& str)
[email protected]7d7b0ac2013-03-28 20:07:40186 : ptr_(str.data()), length_(str.size()) {}
[email protected]0ecab7892014-03-11 21:15:40187 BasicStringPiece(const value_type* offset, size_type len)
[email protected]7d7b0ac2013-03-28 20:07:40188 : ptr_(offset), length_(len) {}
[email protected]0ecab7892014-03-11 21:15:40189 BasicStringPiece(const typename STRING_TYPE::const_iterator& begin,
brettwf22866d2015-07-27 22:22:26190 const typename STRING_TYPE::const_iterator& end) {
olli.raula570930f2015-10-12 22:10:56191#if DCHECK_IS_ON()
brettwf22866d2015-07-27 22:22:26192 // This assertion is done out-of-line to avoid bringing in logging.h and
193 // instantiating logging macros for every instantiation.
194 internal::AssertIteratorsInOrder(begin, end);
195#endif
196 length_ = static_cast<size_t>(std::distance(begin, end));
197
198 // The length test before assignment is to avoid dereferencing an iterator
199 // that may point to the end() of a string.
200 ptr_ = length_ > 0 ? &*begin : nullptr;
201 }
[email protected]7d7b0ac2013-03-28 20:07:40202
203 // data() may return a pointer to a buffer with embedded NULs, and the
204 // returned buffer may or may not be null terminated. Therefore it is
205 // typically a mistake to pass data() to a routine that expects a NUL
206 // terminated string.
207 const value_type* data() const { return ptr_; }
208 size_type size() const { return length_; }
209 size_type length() const { return length_; }
210 bool empty() const { return length_ == 0; }
211
212 void clear() {
213 ptr_ = NULL;
214 length_ = 0;
215 }
216 void set(const value_type* data, size_type len) {
217 ptr_ = data;
218 length_ = len;
219 }
220 void set(const value_type* str) {
221 ptr_ = str;
222 length_ = str ? STRING_TYPE::traits_type::length(str) : 0;
223 }
224
225 value_type operator[](size_type i) const { return ptr_[i]; }
pkasting9022cb42016-02-05 00:08:56226 value_type front() const { return ptr_[0]; }
227 value_type back() const { return ptr_[length_ - 1]; }
[email protected]7d7b0ac2013-03-28 20:07:40228
229 void remove_prefix(size_type n) {
230 ptr_ += n;
231 length_ -= n;
232 }
233
234 void remove_suffix(size_type n) {
235 length_ -= n;
236 }
237
238 int compare(const BasicStringPiece<STRING_TYPE>& x) const {
239 int r = wordmemcmp(
240 ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
241 if (r == 0) {
242 if (length_ < x.length_) r = -1;
243 else if (length_ > x.length_) r = +1;
244 }
245 return r;
246 }
247
248 STRING_TYPE as_string() const {
249 // std::string doesn't like to take a NULL pointer even with a 0 size.
250 return empty() ? STRING_TYPE() : STRING_TYPE(data(), size());
251 }
252
253 const_iterator begin() const { return ptr_; }
254 const_iterator end() const { return ptr_ + length_; }
255 const_reverse_iterator rbegin() const {
256 return const_reverse_iterator(ptr_ + length_);
257 }
258 const_reverse_iterator rend() const {
259 return const_reverse_iterator(ptr_);
260 }
261
262 size_type max_size() const { return length_; }
263 size_type capacity() const { return length_; }
264
265 static int wordmemcmp(const value_type* p,
266 const value_type* p2,
267 size_type N) {
268 return STRING_TYPE::traits_type::compare(p, p2, N);
269 }
270
[email protected]0ecab7892014-03-11 21:15:40271 // Sets the value of the given string target type to be the current string.
272 // This saves a temporary over doing |a = b.as_string()|
273 void CopyToString(STRING_TYPE* target) const {
274 internal::CopyToString(*this, target);
275 }
276
277 void AppendToString(STRING_TYPE* target) const {
278 internal::AppendToString(*this, target);
279 }
280
281 size_type copy(value_type* buf, size_type n, size_type pos = 0) const {
282 return internal::copy(*this, buf, n, pos);
283 }
284
285 // Does "this" start with "x"
286 bool starts_with(const BasicStringPiece& x) const {
287 return ((this->length_ >= x.length_) &&
288 (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0));
289 }
290
291 // Does "this" end with "x"
292 bool ends_with(const BasicStringPiece& x) const {
293 return ((this->length_ >= x.length_) &&
294 (wordmemcmp(this->ptr_ + (this->length_-x.length_),
295 x.ptr_, x.length_) == 0));
296 }
297
298 // find: Search for a character or substring at a given offset.
299 size_type find(const BasicStringPiece<STRING_TYPE>& s,
300 size_type pos = 0) const {
301 return internal::find(*this, s, pos);
302 }
303 size_type find(value_type c, size_type pos = 0) const {
304 return internal::find(*this, c, pos);
305 }
306
307 // rfind: Reverse find.
308 size_type rfind(const BasicStringPiece& s,
309 size_type pos = BasicStringPiece::npos) const {
310 return internal::rfind(*this, s, pos);
311 }
312 size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const {
313 return internal::rfind(*this, c, pos);
314 }
315
316 // find_first_of: Find the first occurence of one of a set of characters.
317 size_type find_first_of(const BasicStringPiece& s,
318 size_type pos = 0) const {
319 return internal::find_first_of(*this, s, pos);
320 }
321 size_type find_first_of(value_type c, size_type pos = 0) const {
322 return find(c, pos);
323 }
324
325 // find_first_not_of: Find the first occurence not of a set of characters.
326 size_type find_first_not_of(const BasicStringPiece& s,
327 size_type pos = 0) const {
328 return internal::find_first_not_of(*this, s, pos);
329 }
330 size_type find_first_not_of(value_type c, size_type pos = 0) const {
331 return internal::find_first_not_of(*this, c, pos);
332 }
333
334 // find_last_of: Find the last occurence of one of a set of characters.
335 size_type find_last_of(const BasicStringPiece& s,
336 size_type pos = BasicStringPiece::npos) const {
337 return internal::find_last_of(*this, s, pos);
338 }
339 size_type find_last_of(value_type c,
340 size_type pos = BasicStringPiece::npos) const {
341 return rfind(c, pos);
342 }
343
344 // find_last_not_of: Find the last occurence not of a set of characters.
345 size_type find_last_not_of(const BasicStringPiece& s,
346 size_type pos = BasicStringPiece::npos) const {
347 return internal::find_last_not_of(*this, s, pos);
348 }
349 size_type find_last_not_of(value_type c,
350 size_type pos = BasicStringPiece::npos) const {
351 return internal::find_last_not_of(*this, c, pos);
352 }
353
354 // substr.
355 BasicStringPiece substr(size_type pos,
356 size_type n = BasicStringPiece::npos) const {
357 return internal::substr(*this, pos, n);
358 }
359
[email protected]7d7b0ac2013-03-28 20:07:40360 protected:
361 const value_type* ptr_;
362 size_type length_;
363};
364
365template <typename STRING_TYPE>
[email protected]0ecab7892014-03-11 21:15:40366const typename BasicStringPiece<STRING_TYPE>::size_type
367BasicStringPiece<STRING_TYPE>::npos =
368 typename BasicStringPiece<STRING_TYPE>::size_type(-1);
[email protected]7d7b0ac2013-03-28 20:07:40369
370// MSVC doesn't like complex extern templates and DLLs.
371#if !defined(COMPILER_MSVC)
[email protected]0ecab7892014-03-11 21:15:40372extern template class BASE_EXPORT BasicStringPiece<std::string>;
[email protected]50bc27c2014-03-07 01:45:03373extern template class BASE_EXPORT BasicStringPiece<string16>;
374#endif
[email protected]51cb94c2014-03-06 17:54:33375
[email protected]0ecab7892014-03-11 21:15:40376// StingPiece operators --------------------------------------------------------
377
[email protected]7d7b0ac2013-03-28 20:07:40378BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
379
380inline bool operator!=(const StringPiece& x, const StringPiece& y) {
381 return !(x == y);
382}
383
384inline bool operator<(const StringPiece& x, const StringPiece& y) {
385 const int r = StringPiece::wordmemcmp(
386 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
387 return ((r < 0) || ((r == 0) && (x.size() < y.size())));
388}
389
390inline bool operator>(const StringPiece& x, const StringPiece& y) {
391 return y < x;
392}
393
394inline bool operator<=(const StringPiece& x, const StringPiece& y) {
395 return !(x > y);
396}
397
398inline bool operator>=(const StringPiece& x, const StringPiece& y) {
399 return !(x < y);
400}
401
[email protected]0ecab7892014-03-11 21:15:40402// StringPiece16 operators -----------------------------------------------------
403
[email protected]7d7b0ac2013-03-28 20:07:40404inline bool operator==(const StringPiece16& x, const StringPiece16& y) {
405 if (x.size() != y.size())
406 return false;
407
408 return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0;
409}
410
411inline bool operator!=(const StringPiece16& x, const StringPiece16& y) {
412 return !(x == y);
413}
414
415inline bool operator<(const StringPiece16& x, const StringPiece16& y) {
416 const int r = StringPiece16::wordmemcmp(
417 x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
418 return ((r < 0) || ((r == 0) && (x.size() < y.size())));
419}
420
421inline bool operator>(const StringPiece16& x, const StringPiece16& y) {
422 return y < x;
423}
424
425inline bool operator<=(const StringPiece16& x, const StringPiece16& y) {
426 return !(x > y);
427}
428
429inline bool operator>=(const StringPiece16& x, const StringPiece16& y) {
430 return !(x < y);
431}
432
433BASE_EXPORT std::ostream& operator<<(std::ostream& o,
434 const StringPiece& piece);
435
[email protected]0ecab7892014-03-11 21:15:40436// Hashing ---------------------------------------------------------------------
437
[email protected]7d7b0ac2013-03-28 20:07:40438// We provide appropriate hash functions so StringPiece and StringPiece16 can
439// be used as keys in hash sets and maps.
440
davidben411d3f72016-01-22 01:41:41441// This hash function is copied from base/strings/string16.h. We don't use the
442// ones already defined for string and string16 directly because it would
443// require the string constructors to be called, which we don't want.
bnc63c013002016-02-06 03:58:14444#define HASH_STRING_PIECE(StringPieceType, string_piece) \
445 std::size_t result = 0; \
446 for (StringPieceType::const_iterator i = string_piece.begin(); \
447 i != string_piece.end(); ++i) \
448 result = (result * 131) + *i; \
449 return result;
[email protected]7d7b0ac2013-03-28 20:07:40450
bnc63c013002016-02-06 03:58:14451struct StringPieceHash {
452 std::size_t operator()(const StringPiece& sp) const {
453 HASH_STRING_PIECE(StringPiece, sp);
[email protected]7d7b0ac2013-03-28 20:07:40454 }
455};
bnc63c013002016-02-06 03:58:14456struct StringPiece16Hash {
457 std::size_t operator()(const StringPiece16& sp16) const {
458 HASH_STRING_PIECE(StringPiece16, sp16);
[email protected]7d7b0ac2013-03-28 20:07:40459 }
460};
461
bnc63c013002016-02-06 03:58:14462} // namespace base
[email protected]7d7b0ac2013-03-28 20:07:40463
464#endif // BASE_STRINGS_STRING_PIECE_H_