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"
14 // For each character in characters_wanted, sets the index corresponding
15 // to the ASCII code of that character to 1 in table. This is used by
16 // the find_.*_of methods below to tell whether or not a character is in
17 // the lookup table in constant time.
18 // The argument `table' must be an array that is large enough to hold all
19 // the possible values of an unsigned char. Thus it should be be declared
21 // bool table[UCHAR_MAX + 1]
22 inline void BuildLookupTable(const StringPiece
& characters_wanted
,
24 const size_t length
= characters_wanted
.length();
25 const char* const data
= characters_wanted
.data();
26 for (size_t i
= 0; i
< length
; ++i
) {
27 table
[static_cast<unsigned char>(data
[i
])] = true;
33 // MSVC doesn't like complex extern templates and DLLs.
34 #if !defined(COMPILER_MSVC)
35 template class BasicStringPiece
<std::string
>;
36 template class BasicStringPiece
<string16
>;
39 bool operator==(const StringPiece
& x
, const StringPiece
& y
) {
40 if (x
.size() != y
.size())
43 return StringPiece::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
46 std::ostream
& operator<<(std::ostream
& o
, const StringPiece
& piece
) {
47 o
.write(piece
.data(), static_cast<std::streamsize
>(piece
.size()));
53 template<typename STR
>
54 void CopyToStringT(const BasicStringPiece
<STR
>& self
, STR
* target
) {
58 target
->assign(self
.data(), self
.size());
61 void CopyToString(const StringPiece
& self
, std::string
* target
) {
62 CopyToStringT(self
, target
);
65 void CopyToString(const StringPiece16
& self
, string16
* target
) {
66 CopyToStringT(self
, target
);
69 template<typename STR
>
70 void AppendToStringT(const BasicStringPiece
<STR
>& self
, STR
* target
) {
72 target
->append(self
.data(), self
.size());
75 void AppendToString(const StringPiece
& self
, std::string
* target
) {
76 AppendToStringT(self
, target
);
79 void AppendToString(const StringPiece16
& self
, string16
* target
) {
80 AppendToStringT(self
, target
);
83 template<typename STR
>
84 size_t copyT(const BasicStringPiece
<STR
>& self
,
85 typename
STR::value_type
* buf
,
88 size_t ret
= std::min(self
.size() - pos
, n
);
89 memcpy(buf
, self
.data() + pos
, ret
* sizeof(typename
STR::value_type
));
93 size_t copy(const StringPiece
& self
, char* buf
, size_t n
, size_t pos
) {
94 return copyT(self
, buf
, n
, pos
);
97 size_t copy(const StringPiece16
& self
, char16
* buf
, size_t n
, size_t pos
) {
98 return copyT(self
, buf
, n
, pos
);
101 template<typename STR
>
102 size_t findT(const BasicStringPiece
<STR
>& self
,
103 const BasicStringPiece
<STR
>& s
,
105 if (pos
> self
.size())
106 return BasicStringPiece
<STR
>::npos
;
108 typename BasicStringPiece
<STR
>::const_iterator result
=
109 std::search(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
111 static_cast<size_t>(result
- self
.begin());
112 return xpos
+ s
.size() <= self
.size() ? xpos
: BasicStringPiece
<STR
>::npos
;
115 size_t find(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
116 return findT(self
, s
, pos
);
119 size_t find(const StringPiece16
& self
, const StringPiece16
& s
, size_t pos
) {
120 return findT(self
, s
, pos
);
123 template<typename STR
>
124 size_t findT(const BasicStringPiece
<STR
>& self
,
125 typename
STR::value_type c
,
127 if (pos
>= self
.size())
128 return BasicStringPiece
<STR
>::npos
;
130 typename BasicStringPiece
<STR
>::const_iterator result
=
131 std::find(self
.begin() + pos
, self
.end(), c
);
132 return result
!= self
.end() ?
133 static_cast<size_t>(result
- self
.begin()) : BasicStringPiece
<STR
>::npos
;
136 size_t find(const StringPiece
& self
, char c
, size_t pos
) {
137 return findT(self
, c
, pos
);
140 size_t find(const StringPiece16
& self
, char16 c
, size_t pos
) {
141 return findT(self
, c
, pos
);
144 template<typename STR
>
145 size_t rfindT(const BasicStringPiece
<STR
>& self
,
146 const BasicStringPiece
<STR
>& s
,
148 if (self
.size() < s
.size())
149 return BasicStringPiece
<STR
>::npos
;
152 return std::min(self
.size(), pos
);
154 typename BasicStringPiece
<STR
>::const_iterator last
=
155 self
.begin() + std::min(self
.size() - s
.size(), pos
) + s
.size();
156 typename BasicStringPiece
<STR
>::const_iterator result
=
157 std::find_end(self
.begin(), last
, s
.begin(), s
.end());
158 return result
!= last
?
159 static_cast<size_t>(result
- self
.begin()) : BasicStringPiece
<STR
>::npos
;
162 size_t rfind(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
163 return rfindT(self
, s
, pos
);
166 size_t rfind(const StringPiece16
& self
, const StringPiece16
& s
, size_t pos
) {
167 return rfindT(self
, s
, pos
);
170 template<typename STR
>
171 size_t rfindT(const BasicStringPiece
<STR
>& self
,
172 typename
STR::value_type c
,
174 if (self
.size() == 0)
175 return BasicStringPiece
<STR
>::npos
;
177 for (size_t i
= std::min(pos
, self
.size() - 1); ;
179 if (self
.data()[i
] == c
)
184 return BasicStringPiece
<STR
>::npos
;
187 size_t rfind(const StringPiece
& self
, char c
, size_t pos
) {
188 return rfindT(self
, c
, pos
);
191 size_t rfind(const StringPiece16
& self
, char16 c
, size_t pos
) {
192 return rfindT(self
, c
, pos
);
195 // 8-bit version using lookup table.
196 size_t find_first_of(const StringPiece
& self
,
197 const StringPiece
& s
,
199 if (self
.size() == 0 || s
.size() == 0)
200 return StringPiece::npos
;
202 // Avoid the cost of BuildLookupTable() for a single-character search.
204 return find(self
, s
.data()[0], pos
);
206 bool lookup
[UCHAR_MAX
+ 1] = { false };
207 BuildLookupTable(s
, lookup
);
208 for (size_t i
= pos
; i
< self
.size(); ++i
) {
209 if (lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
213 return StringPiece::npos
;
216 // 16-bit brute force version.
217 size_t find_first_of(const StringPiece16
& self
,
218 const StringPiece16
& s
,
220 StringPiece16::const_iterator found
=
221 std::find_first_of(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
222 if (found
== self
.end())
223 return StringPiece16::npos
;
224 return found
- self
.begin();
227 // 8-bit version using lookup table.
228 size_t find_first_not_of(const StringPiece
& self
,
229 const StringPiece
& s
,
231 if (self
.size() == 0)
232 return StringPiece::npos
;
237 // Avoid the cost of BuildLookupTable() for a single-character search.
239 return find_first_not_of(self
, s
.data()[0], pos
);
241 bool lookup
[UCHAR_MAX
+ 1] = { false };
242 BuildLookupTable(s
, lookup
);
243 for (size_t i
= pos
; i
< self
.size(); ++i
) {
244 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
248 return StringPiece::npos
;
251 // 16-bit brute-force version.
252 BASE_EXPORT
size_t find_first_not_of(const StringPiece16
& self
,
253 const StringPiece16
& s
,
255 if (self
.size() == 0)
256 return StringPiece16::npos
;
258 for (size_t self_i
= pos
; self_i
< self
.size(); ++self_i
) {
260 for (size_t s_i
= 0; s_i
< s
.size(); ++s_i
) {
261 if (self
[self_i
] == s
[s_i
]) {
269 return StringPiece16::npos
;
272 template<typename STR
>
273 size_t find_first_not_ofT(const BasicStringPiece
<STR
>& self
,
274 typename
STR::value_type c
,
276 if (self
.size() == 0)
277 return BasicStringPiece
<STR
>::npos
;
279 for (; pos
< self
.size(); ++pos
) {
280 if (self
.data()[pos
] != c
) {
284 return BasicStringPiece
<STR
>::npos
;
287 size_t find_first_not_of(const StringPiece
& self
,
290 return find_first_not_ofT(self
, c
, pos
);
293 size_t find_first_not_of(const StringPiece16
& self
,
296 return find_first_not_ofT(self
, c
, pos
);
299 // 8-bit version using lookup table.
300 size_t find_last_of(const StringPiece
& self
, const StringPiece
& s
, size_t pos
) {
301 if (self
.size() == 0 || s
.size() == 0)
302 return StringPiece::npos
;
304 // Avoid the cost of BuildLookupTable() for a single-character search.
306 return rfind(self
, s
.data()[0], pos
);
308 bool lookup
[UCHAR_MAX
+ 1] = { false };
309 BuildLookupTable(s
, lookup
);
310 for (size_t i
= std::min(pos
, self
.size() - 1); ; --i
) {
311 if (lookup
[static_cast<unsigned char>(self
.data()[i
])])
316 return StringPiece::npos
;
319 // 16-bit brute-force version.
320 size_t find_last_of(const StringPiece16
& self
,
321 const StringPiece16
& s
,
323 if (self
.size() == 0)
324 return StringPiece16::npos
;
326 for (size_t self_i
= std::min(pos
, self
.size() - 1); ;
328 for (size_t s_i
= 0; s_i
< s
.size(); s_i
++) {
329 if (self
.data()[self_i
] == s
[s_i
])
335 return StringPiece16::npos
;
338 // 8-bit version using lookup table.
339 size_t find_last_not_of(const StringPiece
& self
,
340 const StringPiece
& s
,
342 if (self
.size() == 0)
343 return StringPiece::npos
;
345 size_t i
= std::min(pos
, self
.size() - 1);
349 // Avoid the cost of BuildLookupTable() for a single-character search.
351 return find_last_not_of(self
, s
.data()[0], pos
);
353 bool lookup
[UCHAR_MAX
+ 1] = { false };
354 BuildLookupTable(s
, lookup
);
356 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])])
361 return StringPiece::npos
;
364 // 16-bit brute-force version.
365 size_t find_last_not_of(const StringPiece16
& self
,
366 const StringPiece16
& s
,
368 if (self
.size() == 0)
369 return StringPiece::npos
;
371 for (size_t self_i
= std::min(pos
, self
.size() - 1); ; --self_i
) {
373 for (size_t s_i
= 0; s_i
< s
.size(); s_i
++) {
374 if (self
.data()[self_i
] == s
[s_i
]) {
384 return StringPiece16::npos
;
387 template<typename STR
>
388 size_t find_last_not_ofT(const BasicStringPiece
<STR
>& self
,
389 typename
STR::value_type c
,
391 if (self
.size() == 0)
392 return BasicStringPiece
<STR
>::npos
;
394 for (size_t i
= std::min(pos
, self
.size() - 1); ; --i
) {
395 if (self
.data()[i
] != c
)
400 return BasicStringPiece
<STR
>::npos
;
403 size_t find_last_not_of(const StringPiece
& self
,
406 return find_last_not_ofT(self
, c
, pos
);
409 size_t find_last_not_of(const StringPiece16
& self
,
412 return find_last_not_ofT(self
, c
, pos
);
415 template<typename STR
>
416 BasicStringPiece
<STR
> substrT(const BasicStringPiece
<STR
>& self
,
419 if (pos
> self
.size()) pos
= self
.size();
420 if (n
> self
.size() - pos
) n
= self
.size() - pos
;
421 return BasicStringPiece
<STR
>(self
.data() + pos
, n
);
424 StringPiece
substr(const StringPiece
& self
,
427 return substrT(self
, pos
, n
);
430 StringPiece16
substr(const StringPiece16
& self
,
433 return substrT(self
, pos
, n
);
436 } // namespace internal