Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / base / strings / string_piece.cc
blob99975725afcc1d7d5dc104b076be55e674d031b1
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"
8 #include <algorithm>
9 #include <ostream>
11 #include "base/logging.h"
13 namespace base {
14 namespace {
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
22 // as follows:
23 // bool table[UCHAR_MAX + 1]
24 inline void BuildLookupTable(const StringPiece& characters_wanted,
25 bool* table) {
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;
33 } // namespace
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>;
39 #endif
41 bool operator==(const StringPiece& x, const StringPiece& y) {
42 if (x.size() != y.size())
43 return false;
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()));
50 return o;
53 namespace internal {
55 template<typename STR>
56 void CopyToStringT(const BasicStringPiece<STR>& self, STR* target) {
57 if (self.empty())
58 target->clear();
59 else
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) {
73 if (!self.empty())
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,
88 size_t n,
89 size_t pos) {
90 size_t ret = std::min(self.size() - pos, n);
91 memcpy(buf, self.data() + pos, ret * sizeof(typename STR::value_type));
92 return ret;
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,
106 size_t pos) {
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());
112 const size_t xpos =
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,
128 size_t pos) {
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,
149 size_t pos) {
150 if (self.size() < s.size())
151 return BasicStringPiece<STR>::npos;
153 if (s.empty())
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,
175 size_t pos) {
176 if (self.size() == 0)
177 return BasicStringPiece<STR>::npos;
179 for (size_t i = std::min(pos, self.size() - 1); ;
180 --i) {
181 if (self.data()[i] == c)
182 return i;
183 if (i == 0)
184 break;
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,
200 size_t pos) {
201 if (self.size() == 0 || s.size() == 0)
202 return StringPiece::npos;
204 // Avoid the cost of BuildLookupTable() for a single-character search.
205 if (s.size() == 1)
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])]) {
212 return i;
215 return StringPiece::npos;
218 // 16-bit brute force version.
219 size_t find_first_of(const StringPiece16& self,
220 const StringPiece16& s,
221 size_t pos) {
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,
232 size_t pos) {
233 if (self.size() == 0)
234 return StringPiece::npos;
236 if (s.size() == 0)
237 return 0;
239 // Avoid the cost of BuildLookupTable() for a single-character search.
240 if (s.size() == 1)
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])]) {
247 return 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,
256 size_t pos) {
257 if (self.size() == 0)
258 return StringPiece16::npos;
260 for (size_t self_i = pos; self_i < self.size(); ++self_i) {
261 bool found = false;
262 for (size_t s_i = 0; s_i < s.size(); ++s_i) {
263 if (self[self_i] == s[s_i]) {
264 found = true;
265 break;
268 if (!found)
269 return self_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,
277 size_t pos) {
278 if (self.size() == 0)
279 return BasicStringPiece<STR>::npos;
281 for (; pos < self.size(); ++pos) {
282 if (self.data()[pos] != c) {
283 return pos;
286 return BasicStringPiece<STR>::npos;
289 size_t find_first_not_of(const StringPiece& self,
290 char c,
291 size_t pos) {
292 return find_first_not_ofT(self, c, pos);
295 size_t find_first_not_of(const StringPiece16& self,
296 char16 c,
297 size_t pos) {
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.
307 if (s.size() == 1)
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])])
314 return i;
315 if (i == 0)
316 break;
318 return StringPiece::npos;
321 // 16-bit brute-force version.
322 size_t find_last_of(const StringPiece16& self,
323 const StringPiece16& s,
324 size_t pos) {
325 if (self.size() == 0)
326 return StringPiece16::npos;
328 for (size_t self_i = std::min(pos, self.size() - 1); ;
329 --self_i) {
330 for (size_t s_i = 0; s_i < s.size(); s_i++) {
331 if (self.data()[self_i] == s[s_i])
332 return self_i;
334 if (self_i == 0)
335 break;
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,
343 size_t pos) {
344 if (self.size() == 0)
345 return StringPiece::npos;
347 size_t i = std::min(pos, self.size() - 1);
348 if (s.size() == 0)
349 return i;
351 // Avoid the cost of BuildLookupTable() for a single-character search.
352 if (s.size() == 1)
353 return find_last_not_of(self, s.data()[0], pos);
355 bool lookup[UCHAR_MAX + 1] = { false };
356 BuildLookupTable(s, lookup);
357 for (; ; --i) {
358 if (!lookup[static_cast<unsigned char>(self.data()[i])])
359 return i;
360 if (i == 0)
361 break;
363 return StringPiece::npos;
366 // 16-bit brute-force version.
367 size_t find_last_not_of(const StringPiece16& self,
368 const StringPiece16& s,
369 size_t pos) {
370 if (self.size() == 0)
371 return StringPiece::npos;
373 for (size_t self_i = std::min(pos, self.size() - 1); ; --self_i) {
374 bool found = false;
375 for (size_t s_i = 0; s_i < s.size(); s_i++) {
376 if (self.data()[self_i] == s[s_i]) {
377 found = true;
378 break;
381 if (!found)
382 return self_i;
383 if (self_i == 0)
384 break;
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,
392 size_t pos) {
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)
398 return i;
399 if (i == 0)
400 break;
402 return BasicStringPiece<STR>::npos;
405 size_t find_last_not_of(const StringPiece& self,
406 char c,
407 size_t pos) {
408 return find_last_not_ofT(self, c, pos);
411 size_t find_last_not_of(const StringPiece16& self,
412 char16 c,
413 size_t pos) {
414 return find_last_not_ofT(self, c, pos);
417 template<typename STR>
418 BasicStringPiece<STR> substrT(const BasicStringPiece<STR>& self,
419 size_t pos,
420 size_t n) {
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,
427 size_t pos,
428 size_t n) {
429 return substrT(self, pos, n);
432 StringPiece16 substr(const StringPiece16& self,
433 size_t pos,
434 size_t n) {
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.";
447 #endif
449 } // namespace internal
450 } // namespace base