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.cc with modifications
6 #include "base/strings/string_piece.h"
11 #include "base/logging.h"
16 // For each character in characters_wanted, sets the index corresponding
17 // to the ASCII code of that character to 1 in table. This is used by
18 // the find_.*_of methods below to tell whether or not a character is in
19 // the lookup table in constant time.
20 // The argument `table' must be an array that is large enough to hold all
21 // the possible values of an unsigned char. Thus it should be be declared
23 // bool table[UCHAR_MAX + 1]
24 inline void BuildLookupTable(const StringPiece
& characters_wanted
,
26 const size_t length
= characters_wanted
.length();
27 const char* const data
= characters_wanted
.data();
28 for (size_t i
= 0; i
< length
; ++i
) {
29 table
[static_cast<unsigned char>(data
[i
])] = true;
35 // MSVC doesn't like complex extern templates and DLLs.
36 #if !defined(COMPILER_MSVC)
37 template class BasicStringPiece
<std::string
>;
38 template class BasicStringPiece
<string16
>;
41 bool operator==(const StringPiece
& x
, const StringPiece
& y
) {
42 if (x
.size() != y
.size())
45 return StringPiece::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
48 std::ostream
& operator<<(std::ostream
& o
, const StringPiece
& piece
) {
49 o
.write(piece
.data(), static_cast<std::streamsize
>(piece
.size()));
55 template<typename STR
>
56 void CopyToStringT(const BasicStringPiece
<STR
>& self
, STR
* target
) {
60 target
->assign(self
.data(), self
.size());
63 void CopyToString(const StringPiece
& self
, std::string
* target
) {
64 CopyToStringT(self
, target
);
67 void CopyToString(const StringPiece16
& self
, string16
* target
) {
68 CopyToStringT(self
, target
);
71 template<typename STR
>
72 void AppendToStringT(const BasicStringPiece
<STR
>& self
, STR
* target
) {
74 target
->append(self
.data(), self
.size());
77 void AppendToString(const StringPiece
& self
, std::string
* target
) {
78 AppendToStringT(self
, target
);
81 void AppendToString(const StringPiece16
& self
, string16
* target
) {
82 AppendToStringT(self
, target
);
85 template<typename STR
>
86 size_t copyT(const BasicStringPiece
<STR
>& self
,
87 typename
STR::value_type
* buf
,
90 size_t ret
= std::min(self
.size() - pos
, n
);
91 memcpy(buf
, self
.data() + pos
, ret
* sizeof(typename
STR::value_type
));
95 size_t copy(const StringPiece
& self
, char* buf
, size_t n
, size_t pos
) {
96 return copyT(self
, buf
, n
, pos
);
99 size_t copy(const StringPiece16
& self
, char16
* buf
, size_t n
, size_t pos
) {
100 return copyT(self
, buf
, n
, pos
);
103 template<typename STR
>
104 size_t findT(const BasicStringPiece
<STR
>& self
,
105 const BasicStringPiece
<STR
>& s
,
107 if (pos
> self
.size())
108 return BasicStringPiece
<STR
>::npos
;
110 typename BasicStringPiece
<STR
>::const_iterator result
=
111 std::search(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
113 static_cast<size_t>(result
- self
.begin());
114 return xpos
+ s
.size() <= self
.size() ? xpos
: BasicStringPiece
<STR
>::npos
;
117 size_t find(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
118 return findT(self
, s
, pos
);
121 size_t find(const StringPiece16
& self
, const StringPiece16
& s
, size_t pos
) {
122 return findT(self
, s
, pos
);
125 template<typename STR
>
126 size_t findT(const BasicStringPiece
<STR
>& self
,
127 typename
STR::value_type c
,
129 if (pos
>= self
.size())
130 return BasicStringPiece
<STR
>::npos
;
132 typename BasicStringPiece
<STR
>::const_iterator result
=
133 std::find(self
.begin() + pos
, self
.end(), c
);
134 return result
!= self
.end() ?
135 static_cast<size_t>(result
- self
.begin()) : BasicStringPiece
<STR
>::npos
;
138 size_t find(const StringPiece
& self
, char c
, size_t pos
) {
139 return findT(self
, c
, pos
);
142 size_t find(const StringPiece16
& self
, char16 c
, size_t pos
) {
143 return findT(self
, c
, pos
);
146 template<typename STR
>
147 size_t rfindT(const BasicStringPiece
<STR
>& self
,
148 const BasicStringPiece
<STR
>& s
,
150 if (self
.size() < s
.size())
151 return BasicStringPiece
<STR
>::npos
;
154 return std::min(self
.size(), pos
);
156 typename BasicStringPiece
<STR
>::const_iterator last
=
157 self
.begin() + std::min(self
.size() - s
.size(), pos
) + s
.size();
158 typename BasicStringPiece
<STR
>::const_iterator result
=
159 std::find_end(self
.begin(), last
, s
.begin(), s
.end());
160 return result
!= last
?
161 static_cast<size_t>(result
- self
.begin()) : BasicStringPiece
<STR
>::npos
;
164 size_t rfind(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
165 return rfindT(self
, s
, pos
);
168 size_t rfind(const StringPiece16
& self
, const StringPiece16
& s
, size_t pos
) {
169 return rfindT(self
, s
, pos
);
172 template<typename STR
>
173 size_t rfindT(const BasicStringPiece
<STR
>& self
,
174 typename
STR::value_type c
,
176 if (self
.size() == 0)
177 return BasicStringPiece
<STR
>::npos
;
179 for (size_t i
= std::min(pos
, self
.size() - 1); ;
181 if (self
.data()[i
] == c
)
186 return BasicStringPiece
<STR
>::npos
;
189 size_t rfind(const StringPiece
& self
, char c
, size_t pos
) {
190 return rfindT(self
, c
, pos
);
193 size_t rfind(const StringPiece16
& self
, char16 c
, size_t pos
) {
194 return rfindT(self
, c
, pos
);
197 // 8-bit version using lookup table.
198 size_t find_first_of(const StringPiece
& self
,
199 const StringPiece
& s
,
201 if (self
.size() == 0 || s
.size() == 0)
202 return StringPiece::npos
;
204 // Avoid the cost of BuildLookupTable() for a single-character search.
206 return find(self
, s
.data()[0], pos
);
208 bool lookup
[UCHAR_MAX
+ 1] = { false };
209 BuildLookupTable(s
, lookup
);
210 for (size_t i
= pos
; i
< self
.size(); ++i
) {
211 if (lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
215 return StringPiece::npos
;
218 // 16-bit brute force version.
219 size_t find_first_of(const StringPiece16
& self
,
220 const StringPiece16
& s
,
222 StringPiece16::const_iterator found
=
223 std::find_first_of(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
224 if (found
== self
.end())
225 return StringPiece16::npos
;
226 return found
- self
.begin();
229 // 8-bit version using lookup table.
230 size_t find_first_not_of(const StringPiece
& self
,
231 const StringPiece
& s
,
233 if (self
.size() == 0)
234 return StringPiece::npos
;
239 // Avoid the cost of BuildLookupTable() for a single-character search.
241 return find_first_not_of(self
, s
.data()[0], pos
);
243 bool lookup
[UCHAR_MAX
+ 1] = { false };
244 BuildLookupTable(s
, lookup
);
245 for (size_t i
= pos
; i
< self
.size(); ++i
) {
246 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
250 return StringPiece::npos
;
253 // 16-bit brute-force version.
254 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
255 const StringPiece16
& s
,
257 if (self
.size() == 0)
258 return StringPiece16::npos
;
260 for (size_t self_i
= pos
; self_i
< self
.size(); ++self_i
) {
262 for (size_t s_i
= 0; s_i
< s
.size(); ++s_i
) {
263 if (self
[self_i
] == s
[s_i
]) {
271 return StringPiece16::npos
;
274 template<typename STR
>
275 size_t find_first_not_ofT(const BasicStringPiece
<STR
>& self
,
276 typename
STR::value_type c
,
278 if (self
.size() == 0)
279 return BasicStringPiece
<STR
>::npos
;
281 for (; pos
< self
.size(); ++pos
) {
282 if (self
.data()[pos
] != c
) {
286 return BasicStringPiece
<STR
>::npos
;
289 size_t find_first_not_of(const StringPiece
& self
,
292 return find_first_not_ofT(self
, c
, pos
);
295 size_t find_first_not_of(const StringPiece16
& self
,
298 return find_first_not_ofT(self
, c
, pos
);
301 // 8-bit version using lookup table.
302 size_t find_last_of(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
303 if (self
.size() == 0 || s
.size() == 0)
304 return StringPiece::npos
;
306 // Avoid the cost of BuildLookupTable() for a single-character search.
308 return rfind(self
, s
.data()[0], pos
);
310 bool lookup
[UCHAR_MAX
+ 1] = { false };
311 BuildLookupTable(s
, lookup
);
312 for (size_t i
= std::min(pos
, self
.size() - 1); ; --i
) {
313 if (lookup
[static_cast<unsigned char>(self
.data()[i
])])
318 return StringPiece::npos
;
321 // 16-bit brute-force version.
322 size_t find_last_of(const StringPiece16
& self
,
323 const StringPiece16
& s
,
325 if (self
.size() == 0)
326 return StringPiece16::npos
;
328 for (size_t self_i
= std::min(pos
, self
.size() - 1); ;
330 for (size_t s_i
= 0; s_i
< s
.size(); s_i
++) {
331 if (self
.data()[self_i
] == s
[s_i
])
337 return StringPiece16::npos
;
340 // 8-bit version using lookup table.
341 size_t find_last_not_of(const StringPiece
& self
,
342 const StringPiece
& s
,
344 if (self
.size() == 0)
345 return StringPiece::npos
;
347 size_t i
= std::min(pos
, self
.size() - 1);
351 // Avoid the cost of BuildLookupTable() for a single-character search.
353 return find_last_not_of(self
, s
.data()[0], pos
);
355 bool lookup
[UCHAR_MAX
+ 1] = { false };
356 BuildLookupTable(s
, lookup
);
358 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])])
363 return StringPiece::npos
;
366 // 16-bit brute-force version.
367 size_t find_last_not_of(const StringPiece16
& self
,
368 const StringPiece16
& s
,
370 if (self
.size() == 0)
371 return StringPiece::npos
;
373 for (size_t self_i
= std::min(pos
, self
.size() - 1); ; --self_i
) {
375 for (size_t s_i
= 0; s_i
< s
.size(); s_i
++) {
376 if (self
.data()[self_i
] == s
[s_i
]) {
386 return StringPiece16::npos
;
389 template<typename STR
>
390 size_t find_last_not_ofT(const BasicStringPiece
<STR
>& self
,
391 typename
STR::value_type c
,
393 if (self
.size() == 0)
394 return BasicStringPiece
<STR
>::npos
;
396 for (size_t i
= std::min(pos
, self
.size() - 1); ; --i
) {
397 if (self
.data()[i
] != c
)
402 return BasicStringPiece
<STR
>::npos
;
405 size_t find_last_not_of(const StringPiece
& self
,
408 return find_last_not_ofT(self
, c
, pos
);
411 size_t find_last_not_of(const StringPiece16
& self
,
414 return find_last_not_ofT(self
, c
, pos
);
417 template<typename STR
>
418 BasicStringPiece
<STR
> substrT(const BasicStringPiece
<STR
>& self
,
421 if (pos
> self
.size()) pos
= self
.size();
422 if (n
> self
.size() - pos
) n
= self
.size() - pos
;
423 return BasicStringPiece
<STR
>(self
.data() + pos
, n
);
426 StringPiece
substr(const StringPiece
& self
,
429 return substrT(self
, pos
, n
);
432 StringPiece16
substr(const StringPiece16
& self
,
435 return substrT(self
, pos
, n
);
438 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
439 void AssertIteratorsInOrder(std::string::const_iterator begin
,
440 std::string::const_iterator end
) {
441 DCHECK(begin
<= end
) << "StringPiece iterators swapped or invalid.";
443 void AssertIteratorsInOrder(string16::const_iterator begin
,
444 string16::const_iterator end
) {
445 DCHECK(begin
<= end
) << "StringPiece iterators swapped or invalid.";
449 } // namespace internal