1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker // Copied from strings/stringpiece.cc with modifications
5*635a8641SAndroid Build Coastguard Worker
6*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
7*635a8641SAndroid Build Coastguard Worker
8*635a8641SAndroid Build Coastguard Worker #include <limits.h>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include <algorithm>
11*635a8641SAndroid Build Coastguard Worker #include <ostream>
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard Worker namespace base {
16*635a8641SAndroid Build Coastguard Worker namespace {
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard Worker // For each character in characters_wanted, sets the index corresponding
19*635a8641SAndroid Build Coastguard Worker // to the ASCII code of that character to 1 in table. This is used by
20*635a8641SAndroid Build Coastguard Worker // the find_.*_of methods below to tell whether or not a character is in
21*635a8641SAndroid Build Coastguard Worker // the lookup table in constant time.
22*635a8641SAndroid Build Coastguard Worker // The argument `table' must be an array that is large enough to hold all
23*635a8641SAndroid Build Coastguard Worker // the possible values of an unsigned char. Thus it should be be declared
24*635a8641SAndroid Build Coastguard Worker // as follows:
25*635a8641SAndroid Build Coastguard Worker // bool table[UCHAR_MAX + 1]
BuildLookupTable(const StringPiece & characters_wanted,bool * table)26*635a8641SAndroid Build Coastguard Worker inline void BuildLookupTable(const StringPiece& characters_wanted,
27*635a8641SAndroid Build Coastguard Worker bool* table) {
28*635a8641SAndroid Build Coastguard Worker const size_t length = characters_wanted.length();
29*635a8641SAndroid Build Coastguard Worker const char* const data = characters_wanted.data();
30*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < length; ++i) {
31*635a8641SAndroid Build Coastguard Worker table[static_cast<unsigned char>(data[i])] = true;
32*635a8641SAndroid Build Coastguard Worker }
33*635a8641SAndroid Build Coastguard Worker }
34*635a8641SAndroid Build Coastguard Worker
35*635a8641SAndroid Build Coastguard Worker } // namespace
36*635a8641SAndroid Build Coastguard Worker
37*635a8641SAndroid Build Coastguard Worker // MSVC doesn't like complex extern templates and DLLs.
38*635a8641SAndroid Build Coastguard Worker #if !defined(COMPILER_MSVC)
39*635a8641SAndroid Build Coastguard Worker template class BasicStringPiece<std::string>;
40*635a8641SAndroid Build Coastguard Worker template class BasicStringPiece<string16>;
41*635a8641SAndroid Build Coastguard Worker #endif
42*635a8641SAndroid Build Coastguard Worker
operator ==(const StringPiece & x,const StringPiece & y)43*635a8641SAndroid Build Coastguard Worker bool operator==(const StringPiece& x, const StringPiece& y) {
44*635a8641SAndroid Build Coastguard Worker if (x.size() != y.size())
45*635a8641SAndroid Build Coastguard Worker return false;
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker return CharTraits<StringPiece::value_type>::compare(x.data(), y.data(),
48*635a8641SAndroid Build Coastguard Worker x.size()) == 0;
49*635a8641SAndroid Build Coastguard Worker }
50*635a8641SAndroid Build Coastguard Worker
operator <<(std::ostream & o,const StringPiece & piece)51*635a8641SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& o, const StringPiece& piece) {
52*635a8641SAndroid Build Coastguard Worker o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
53*635a8641SAndroid Build Coastguard Worker return o;
54*635a8641SAndroid Build Coastguard Worker }
55*635a8641SAndroid Build Coastguard Worker
56*635a8641SAndroid Build Coastguard Worker namespace internal {
57*635a8641SAndroid Build Coastguard Worker
58*635a8641SAndroid Build Coastguard Worker template<typename STR>
CopyToStringT(const BasicStringPiece<STR> & self,STR * target)59*635a8641SAndroid Build Coastguard Worker void CopyToStringT(const BasicStringPiece<STR>& self, STR* target) {
60*635a8641SAndroid Build Coastguard Worker if (self.empty())
61*635a8641SAndroid Build Coastguard Worker target->clear();
62*635a8641SAndroid Build Coastguard Worker else
63*635a8641SAndroid Build Coastguard Worker target->assign(self.data(), self.size());
64*635a8641SAndroid Build Coastguard Worker }
65*635a8641SAndroid Build Coastguard Worker
CopyToString(const StringPiece & self,std::string * target)66*635a8641SAndroid Build Coastguard Worker void CopyToString(const StringPiece& self, std::string* target) {
67*635a8641SAndroid Build Coastguard Worker CopyToStringT(self, target);
68*635a8641SAndroid Build Coastguard Worker }
69*635a8641SAndroid Build Coastguard Worker
CopyToString(const StringPiece16 & self,string16 * target)70*635a8641SAndroid Build Coastguard Worker void CopyToString(const StringPiece16& self, string16* target) {
71*635a8641SAndroid Build Coastguard Worker CopyToStringT(self, target);
72*635a8641SAndroid Build Coastguard Worker }
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker template<typename STR>
AppendToStringT(const BasicStringPiece<STR> & self,STR * target)75*635a8641SAndroid Build Coastguard Worker void AppendToStringT(const BasicStringPiece<STR>& self, STR* target) {
76*635a8641SAndroid Build Coastguard Worker if (!self.empty())
77*635a8641SAndroid Build Coastguard Worker target->append(self.data(), self.size());
78*635a8641SAndroid Build Coastguard Worker }
79*635a8641SAndroid Build Coastguard Worker
AppendToString(const StringPiece & self,std::string * target)80*635a8641SAndroid Build Coastguard Worker void AppendToString(const StringPiece& self, std::string* target) {
81*635a8641SAndroid Build Coastguard Worker AppendToStringT(self, target);
82*635a8641SAndroid Build Coastguard Worker }
83*635a8641SAndroid Build Coastguard Worker
AppendToString(const StringPiece16 & self,string16 * target)84*635a8641SAndroid Build Coastguard Worker void AppendToString(const StringPiece16& self, string16* target) {
85*635a8641SAndroid Build Coastguard Worker AppendToStringT(self, target);
86*635a8641SAndroid Build Coastguard Worker }
87*635a8641SAndroid Build Coastguard Worker
88*635a8641SAndroid Build Coastguard Worker template<typename STR>
copyT(const BasicStringPiece<STR> & self,typename STR::value_type * buf,size_t n,size_t pos)89*635a8641SAndroid Build Coastguard Worker size_t copyT(const BasicStringPiece<STR>& self,
90*635a8641SAndroid Build Coastguard Worker typename STR::value_type* buf,
91*635a8641SAndroid Build Coastguard Worker size_t n,
92*635a8641SAndroid Build Coastguard Worker size_t pos) {
93*635a8641SAndroid Build Coastguard Worker size_t ret = std::min(self.size() - pos, n);
94*635a8641SAndroid Build Coastguard Worker memcpy(buf, self.data() + pos, ret * sizeof(typename STR::value_type));
95*635a8641SAndroid Build Coastguard Worker return ret;
96*635a8641SAndroid Build Coastguard Worker }
97*635a8641SAndroid Build Coastguard Worker
copy(const StringPiece & self,char * buf,size_t n,size_t pos)98*635a8641SAndroid Build Coastguard Worker size_t copy(const StringPiece& self, char* buf, size_t n, size_t pos) {
99*635a8641SAndroid Build Coastguard Worker return copyT(self, buf, n, pos);
100*635a8641SAndroid Build Coastguard Worker }
101*635a8641SAndroid Build Coastguard Worker
copy(const StringPiece16 & self,char16 * buf,size_t n,size_t pos)102*635a8641SAndroid Build Coastguard Worker size_t copy(const StringPiece16& self, char16* buf, size_t n, size_t pos) {
103*635a8641SAndroid Build Coastguard Worker return copyT(self, buf, n, pos);
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
106*635a8641SAndroid Build Coastguard Worker template<typename STR>
findT(const BasicStringPiece<STR> & self,const BasicStringPiece<STR> & s,size_t pos)107*635a8641SAndroid Build Coastguard Worker size_t findT(const BasicStringPiece<STR>& self,
108*635a8641SAndroid Build Coastguard Worker const BasicStringPiece<STR>& s,
109*635a8641SAndroid Build Coastguard Worker size_t pos) {
110*635a8641SAndroid Build Coastguard Worker if (pos > self.size())
111*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker typename BasicStringPiece<STR>::const_iterator result =
114*635a8641SAndroid Build Coastguard Worker std::search(self.begin() + pos, self.end(), s.begin(), s.end());
115*635a8641SAndroid Build Coastguard Worker const size_t xpos =
116*635a8641SAndroid Build Coastguard Worker static_cast<size_t>(result - self.begin());
117*635a8641SAndroid Build Coastguard Worker return xpos + s.size() <= self.size() ? xpos : BasicStringPiece<STR>::npos;
118*635a8641SAndroid Build Coastguard Worker }
119*635a8641SAndroid Build Coastguard Worker
find(const StringPiece & self,const StringPiece & s,size_t pos)120*635a8641SAndroid Build Coastguard Worker size_t find(const StringPiece& self, const StringPiece& s, size_t pos) {
121*635a8641SAndroid Build Coastguard Worker return findT(self, s, pos);
122*635a8641SAndroid Build Coastguard Worker }
123*635a8641SAndroid Build Coastguard Worker
find(const StringPiece16 & self,const StringPiece16 & s,size_t pos)124*635a8641SAndroid Build Coastguard Worker size_t find(const StringPiece16& self, const StringPiece16& s, size_t pos) {
125*635a8641SAndroid Build Coastguard Worker return findT(self, s, pos);
126*635a8641SAndroid Build Coastguard Worker }
127*635a8641SAndroid Build Coastguard Worker
128*635a8641SAndroid Build Coastguard Worker template<typename STR>
findT(const BasicStringPiece<STR> & self,typename STR::value_type c,size_t pos)129*635a8641SAndroid Build Coastguard Worker size_t findT(const BasicStringPiece<STR>& self,
130*635a8641SAndroid Build Coastguard Worker typename STR::value_type c,
131*635a8641SAndroid Build Coastguard Worker size_t pos) {
132*635a8641SAndroid Build Coastguard Worker if (pos >= self.size())
133*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
134*635a8641SAndroid Build Coastguard Worker
135*635a8641SAndroid Build Coastguard Worker typename BasicStringPiece<STR>::const_iterator result =
136*635a8641SAndroid Build Coastguard Worker std::find(self.begin() + pos, self.end(), c);
137*635a8641SAndroid Build Coastguard Worker return result != self.end() ?
138*635a8641SAndroid Build Coastguard Worker static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos;
139*635a8641SAndroid Build Coastguard Worker }
140*635a8641SAndroid Build Coastguard Worker
find(const StringPiece & self,char c,size_t pos)141*635a8641SAndroid Build Coastguard Worker size_t find(const StringPiece& self, char c, size_t pos) {
142*635a8641SAndroid Build Coastguard Worker return findT(self, c, pos);
143*635a8641SAndroid Build Coastguard Worker }
144*635a8641SAndroid Build Coastguard Worker
find(const StringPiece16 & self,char16 c,size_t pos)145*635a8641SAndroid Build Coastguard Worker size_t find(const StringPiece16& self, char16 c, size_t pos) {
146*635a8641SAndroid Build Coastguard Worker return findT(self, c, pos);
147*635a8641SAndroid Build Coastguard Worker }
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard Worker template<typename STR>
rfindT(const BasicStringPiece<STR> & self,const BasicStringPiece<STR> & s,size_t pos)150*635a8641SAndroid Build Coastguard Worker size_t rfindT(const BasicStringPiece<STR>& self,
151*635a8641SAndroid Build Coastguard Worker const BasicStringPiece<STR>& s,
152*635a8641SAndroid Build Coastguard Worker size_t pos) {
153*635a8641SAndroid Build Coastguard Worker if (self.size() < s.size())
154*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
155*635a8641SAndroid Build Coastguard Worker
156*635a8641SAndroid Build Coastguard Worker if (s.empty())
157*635a8641SAndroid Build Coastguard Worker return std::min(self.size(), pos);
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard Worker typename BasicStringPiece<STR>::const_iterator last =
160*635a8641SAndroid Build Coastguard Worker self.begin() + std::min(self.size() - s.size(), pos) + s.size();
161*635a8641SAndroid Build Coastguard Worker typename BasicStringPiece<STR>::const_iterator result =
162*635a8641SAndroid Build Coastguard Worker std::find_end(self.begin(), last, s.begin(), s.end());
163*635a8641SAndroid Build Coastguard Worker return result != last ?
164*635a8641SAndroid Build Coastguard Worker static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos;
165*635a8641SAndroid Build Coastguard Worker }
166*635a8641SAndroid Build Coastguard Worker
rfind(const StringPiece & self,const StringPiece & s,size_t pos)167*635a8641SAndroid Build Coastguard Worker size_t rfind(const StringPiece& self, const StringPiece& s, size_t pos) {
168*635a8641SAndroid Build Coastguard Worker return rfindT(self, s, pos);
169*635a8641SAndroid Build Coastguard Worker }
170*635a8641SAndroid Build Coastguard Worker
rfind(const StringPiece16 & self,const StringPiece16 & s,size_t pos)171*635a8641SAndroid Build Coastguard Worker size_t rfind(const StringPiece16& self, const StringPiece16& s, size_t pos) {
172*635a8641SAndroid Build Coastguard Worker return rfindT(self, s, pos);
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker
175*635a8641SAndroid Build Coastguard Worker template<typename STR>
rfindT(const BasicStringPiece<STR> & self,typename STR::value_type c,size_t pos)176*635a8641SAndroid Build Coastguard Worker size_t rfindT(const BasicStringPiece<STR>& self,
177*635a8641SAndroid Build Coastguard Worker typename STR::value_type c,
178*635a8641SAndroid Build Coastguard Worker size_t pos) {
179*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
180*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
181*635a8641SAndroid Build Coastguard Worker
182*635a8641SAndroid Build Coastguard Worker for (size_t i = std::min(pos, self.size() - 1); ;
183*635a8641SAndroid Build Coastguard Worker --i) {
184*635a8641SAndroid Build Coastguard Worker if (self.data()[i] == c)
185*635a8641SAndroid Build Coastguard Worker return i;
186*635a8641SAndroid Build Coastguard Worker if (i == 0)
187*635a8641SAndroid Build Coastguard Worker break;
188*635a8641SAndroid Build Coastguard Worker }
189*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker
rfind(const StringPiece & self,char c,size_t pos)192*635a8641SAndroid Build Coastguard Worker size_t rfind(const StringPiece& self, char c, size_t pos) {
193*635a8641SAndroid Build Coastguard Worker return rfindT(self, c, pos);
194*635a8641SAndroid Build Coastguard Worker }
195*635a8641SAndroid Build Coastguard Worker
rfind(const StringPiece16 & self,char16 c,size_t pos)196*635a8641SAndroid Build Coastguard Worker size_t rfind(const StringPiece16& self, char16 c, size_t pos) {
197*635a8641SAndroid Build Coastguard Worker return rfindT(self, c, pos);
198*635a8641SAndroid Build Coastguard Worker }
199*635a8641SAndroid Build Coastguard Worker
200*635a8641SAndroid Build Coastguard Worker // 8-bit version using lookup table.
find_first_of(const StringPiece & self,const StringPiece & s,size_t pos)201*635a8641SAndroid Build Coastguard Worker size_t find_first_of(const StringPiece& self,
202*635a8641SAndroid Build Coastguard Worker const StringPiece& s,
203*635a8641SAndroid Build Coastguard Worker size_t pos) {
204*635a8641SAndroid Build Coastguard Worker if (self.size() == 0 || s.size() == 0)
205*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
206*635a8641SAndroid Build Coastguard Worker
207*635a8641SAndroid Build Coastguard Worker // Avoid the cost of BuildLookupTable() for a single-character search.
208*635a8641SAndroid Build Coastguard Worker if (s.size() == 1)
209*635a8641SAndroid Build Coastguard Worker return find(self, s.data()[0], pos);
210*635a8641SAndroid Build Coastguard Worker
211*635a8641SAndroid Build Coastguard Worker bool lookup[UCHAR_MAX + 1] = { false };
212*635a8641SAndroid Build Coastguard Worker BuildLookupTable(s, lookup);
213*635a8641SAndroid Build Coastguard Worker for (size_t i = pos; i < self.size(); ++i) {
214*635a8641SAndroid Build Coastguard Worker if (lookup[static_cast<unsigned char>(self.data()[i])]) {
215*635a8641SAndroid Build Coastguard Worker return i;
216*635a8641SAndroid Build Coastguard Worker }
217*635a8641SAndroid Build Coastguard Worker }
218*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
219*635a8641SAndroid Build Coastguard Worker }
220*635a8641SAndroid Build Coastguard Worker
221*635a8641SAndroid Build Coastguard Worker // 16-bit brute force version.
find_first_of(const StringPiece16 & self,const StringPiece16 & s,size_t pos)222*635a8641SAndroid Build Coastguard Worker size_t find_first_of(const StringPiece16& self,
223*635a8641SAndroid Build Coastguard Worker const StringPiece16& s,
224*635a8641SAndroid Build Coastguard Worker size_t pos) {
225*635a8641SAndroid Build Coastguard Worker StringPiece16::const_iterator found =
226*635a8641SAndroid Build Coastguard Worker std::find_first_of(self.begin() + pos, self.end(), s.begin(), s.end());
227*635a8641SAndroid Build Coastguard Worker if (found == self.end())
228*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
229*635a8641SAndroid Build Coastguard Worker return found - self.begin();
230*635a8641SAndroid Build Coastguard Worker }
231*635a8641SAndroid Build Coastguard Worker
232*635a8641SAndroid Build Coastguard Worker // 8-bit version using lookup table.
find_first_not_of(const StringPiece & self,const StringPiece & s,size_t pos)233*635a8641SAndroid Build Coastguard Worker size_t find_first_not_of(const StringPiece& self,
234*635a8641SAndroid Build Coastguard Worker const StringPiece& s,
235*635a8641SAndroid Build Coastguard Worker size_t pos) {
236*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
237*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
238*635a8641SAndroid Build Coastguard Worker
239*635a8641SAndroid Build Coastguard Worker if (s.size() == 0)
240*635a8641SAndroid Build Coastguard Worker return 0;
241*635a8641SAndroid Build Coastguard Worker
242*635a8641SAndroid Build Coastguard Worker // Avoid the cost of BuildLookupTable() for a single-character search.
243*635a8641SAndroid Build Coastguard Worker if (s.size() == 1)
244*635a8641SAndroid Build Coastguard Worker return find_first_not_of(self, s.data()[0], pos);
245*635a8641SAndroid Build Coastguard Worker
246*635a8641SAndroid Build Coastguard Worker bool lookup[UCHAR_MAX + 1] = { false };
247*635a8641SAndroid Build Coastguard Worker BuildLookupTable(s, lookup);
248*635a8641SAndroid Build Coastguard Worker for (size_t i = pos; i < self.size(); ++i) {
249*635a8641SAndroid Build Coastguard Worker if (!lookup[static_cast<unsigned char>(self.data()[i])]) {
250*635a8641SAndroid Build Coastguard Worker return i;
251*635a8641SAndroid Build Coastguard Worker }
252*635a8641SAndroid Build Coastguard Worker }
253*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
254*635a8641SAndroid Build Coastguard Worker }
255*635a8641SAndroid Build Coastguard Worker
256*635a8641SAndroid Build Coastguard Worker // 16-bit brute-force version.
find_first_not_of(const StringPiece16 & self,const StringPiece16 & s,size_t pos)257*635a8641SAndroid Build Coastguard Worker BASE_EXPORT size_t find_first_not_of(const StringPiece16& self,
258*635a8641SAndroid Build Coastguard Worker const StringPiece16& s,
259*635a8641SAndroid Build Coastguard Worker size_t pos) {
260*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
261*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
262*635a8641SAndroid Build Coastguard Worker
263*635a8641SAndroid Build Coastguard Worker for (size_t self_i = pos; self_i < self.size(); ++self_i) {
264*635a8641SAndroid Build Coastguard Worker bool found = false;
265*635a8641SAndroid Build Coastguard Worker for (size_t s_i = 0; s_i < s.size(); ++s_i) {
266*635a8641SAndroid Build Coastguard Worker if (self[self_i] == s[s_i]) {
267*635a8641SAndroid Build Coastguard Worker found = true;
268*635a8641SAndroid Build Coastguard Worker break;
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker }
271*635a8641SAndroid Build Coastguard Worker if (!found)
272*635a8641SAndroid Build Coastguard Worker return self_i;
273*635a8641SAndroid Build Coastguard Worker }
274*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
275*635a8641SAndroid Build Coastguard Worker }
276*635a8641SAndroid Build Coastguard Worker
277*635a8641SAndroid Build Coastguard Worker template<typename STR>
find_first_not_ofT(const BasicStringPiece<STR> & self,typename STR::value_type c,size_t pos)278*635a8641SAndroid Build Coastguard Worker size_t find_first_not_ofT(const BasicStringPiece<STR>& self,
279*635a8641SAndroid Build Coastguard Worker typename STR::value_type c,
280*635a8641SAndroid Build Coastguard Worker size_t pos) {
281*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
282*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
283*635a8641SAndroid Build Coastguard Worker
284*635a8641SAndroid Build Coastguard Worker for (; pos < self.size(); ++pos) {
285*635a8641SAndroid Build Coastguard Worker if (self.data()[pos] != c) {
286*635a8641SAndroid Build Coastguard Worker return pos;
287*635a8641SAndroid Build Coastguard Worker }
288*635a8641SAndroid Build Coastguard Worker }
289*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
290*635a8641SAndroid Build Coastguard Worker }
291*635a8641SAndroid Build Coastguard Worker
find_first_not_of(const StringPiece & self,char c,size_t pos)292*635a8641SAndroid Build Coastguard Worker size_t find_first_not_of(const StringPiece& self,
293*635a8641SAndroid Build Coastguard Worker char c,
294*635a8641SAndroid Build Coastguard Worker size_t pos) {
295*635a8641SAndroid Build Coastguard Worker return find_first_not_ofT(self, c, pos);
296*635a8641SAndroid Build Coastguard Worker }
297*635a8641SAndroid Build Coastguard Worker
find_first_not_of(const StringPiece16 & self,char16 c,size_t pos)298*635a8641SAndroid Build Coastguard Worker size_t find_first_not_of(const StringPiece16& self,
299*635a8641SAndroid Build Coastguard Worker char16 c,
300*635a8641SAndroid Build Coastguard Worker size_t pos) {
301*635a8641SAndroid Build Coastguard Worker return find_first_not_ofT(self, c, pos);
302*635a8641SAndroid Build Coastguard Worker }
303*635a8641SAndroid Build Coastguard Worker
304*635a8641SAndroid Build Coastguard Worker // 8-bit version using lookup table.
find_last_of(const StringPiece & self,const StringPiece & s,size_t pos)305*635a8641SAndroid Build Coastguard Worker size_t find_last_of(const StringPiece& self, const StringPiece& s, size_t pos) {
306*635a8641SAndroid Build Coastguard Worker if (self.size() == 0 || s.size() == 0)
307*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
308*635a8641SAndroid Build Coastguard Worker
309*635a8641SAndroid Build Coastguard Worker // Avoid the cost of BuildLookupTable() for a single-character search.
310*635a8641SAndroid Build Coastguard Worker if (s.size() == 1)
311*635a8641SAndroid Build Coastguard Worker return rfind(self, s.data()[0], pos);
312*635a8641SAndroid Build Coastguard Worker
313*635a8641SAndroid Build Coastguard Worker bool lookup[UCHAR_MAX + 1] = { false };
314*635a8641SAndroid Build Coastguard Worker BuildLookupTable(s, lookup);
315*635a8641SAndroid Build Coastguard Worker for (size_t i = std::min(pos, self.size() - 1); ; --i) {
316*635a8641SAndroid Build Coastguard Worker if (lookup[static_cast<unsigned char>(self.data()[i])])
317*635a8641SAndroid Build Coastguard Worker return i;
318*635a8641SAndroid Build Coastguard Worker if (i == 0)
319*635a8641SAndroid Build Coastguard Worker break;
320*635a8641SAndroid Build Coastguard Worker }
321*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
322*635a8641SAndroid Build Coastguard Worker }
323*635a8641SAndroid Build Coastguard Worker
324*635a8641SAndroid Build Coastguard Worker // 16-bit brute-force version.
find_last_of(const StringPiece16 & self,const StringPiece16 & s,size_t pos)325*635a8641SAndroid Build Coastguard Worker size_t find_last_of(const StringPiece16& self,
326*635a8641SAndroid Build Coastguard Worker const StringPiece16& s,
327*635a8641SAndroid Build Coastguard Worker size_t pos) {
328*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
329*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
330*635a8641SAndroid Build Coastguard Worker
331*635a8641SAndroid Build Coastguard Worker for (size_t self_i = std::min(pos, self.size() - 1); ;
332*635a8641SAndroid Build Coastguard Worker --self_i) {
333*635a8641SAndroid Build Coastguard Worker for (size_t s_i = 0; s_i < s.size(); s_i++) {
334*635a8641SAndroid Build Coastguard Worker if (self.data()[self_i] == s[s_i])
335*635a8641SAndroid Build Coastguard Worker return self_i;
336*635a8641SAndroid Build Coastguard Worker }
337*635a8641SAndroid Build Coastguard Worker if (self_i == 0)
338*635a8641SAndroid Build Coastguard Worker break;
339*635a8641SAndroid Build Coastguard Worker }
340*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
341*635a8641SAndroid Build Coastguard Worker }
342*635a8641SAndroid Build Coastguard Worker
343*635a8641SAndroid Build Coastguard Worker // 8-bit version using lookup table.
find_last_not_of(const StringPiece & self,const StringPiece & s,size_t pos)344*635a8641SAndroid Build Coastguard Worker size_t find_last_not_of(const StringPiece& self,
345*635a8641SAndroid Build Coastguard Worker const StringPiece& s,
346*635a8641SAndroid Build Coastguard Worker size_t pos) {
347*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
348*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
349*635a8641SAndroid Build Coastguard Worker
350*635a8641SAndroid Build Coastguard Worker size_t i = std::min(pos, self.size() - 1);
351*635a8641SAndroid Build Coastguard Worker if (s.size() == 0)
352*635a8641SAndroid Build Coastguard Worker return i;
353*635a8641SAndroid Build Coastguard Worker
354*635a8641SAndroid Build Coastguard Worker // Avoid the cost of BuildLookupTable() for a single-character search.
355*635a8641SAndroid Build Coastguard Worker if (s.size() == 1)
356*635a8641SAndroid Build Coastguard Worker return find_last_not_of(self, s.data()[0], pos);
357*635a8641SAndroid Build Coastguard Worker
358*635a8641SAndroid Build Coastguard Worker bool lookup[UCHAR_MAX + 1] = { false };
359*635a8641SAndroid Build Coastguard Worker BuildLookupTable(s, lookup);
360*635a8641SAndroid Build Coastguard Worker for (; ; --i) {
361*635a8641SAndroid Build Coastguard Worker if (!lookup[static_cast<unsigned char>(self.data()[i])])
362*635a8641SAndroid Build Coastguard Worker return i;
363*635a8641SAndroid Build Coastguard Worker if (i == 0)
364*635a8641SAndroid Build Coastguard Worker break;
365*635a8641SAndroid Build Coastguard Worker }
366*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
367*635a8641SAndroid Build Coastguard Worker }
368*635a8641SAndroid Build Coastguard Worker
369*635a8641SAndroid Build Coastguard Worker // 16-bit brute-force version.
find_last_not_of(const StringPiece16 & self,const StringPiece16 & s,size_t pos)370*635a8641SAndroid Build Coastguard Worker size_t find_last_not_of(const StringPiece16& self,
371*635a8641SAndroid Build Coastguard Worker const StringPiece16& s,
372*635a8641SAndroid Build Coastguard Worker size_t pos) {
373*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
374*635a8641SAndroid Build Coastguard Worker return StringPiece::npos;
375*635a8641SAndroid Build Coastguard Worker
376*635a8641SAndroid Build Coastguard Worker for (size_t self_i = std::min(pos, self.size() - 1); ; --self_i) {
377*635a8641SAndroid Build Coastguard Worker bool found = false;
378*635a8641SAndroid Build Coastguard Worker for (size_t s_i = 0; s_i < s.size(); s_i++) {
379*635a8641SAndroid Build Coastguard Worker if (self.data()[self_i] == s[s_i]) {
380*635a8641SAndroid Build Coastguard Worker found = true;
381*635a8641SAndroid Build Coastguard Worker break;
382*635a8641SAndroid Build Coastguard Worker }
383*635a8641SAndroid Build Coastguard Worker }
384*635a8641SAndroid Build Coastguard Worker if (!found)
385*635a8641SAndroid Build Coastguard Worker return self_i;
386*635a8641SAndroid Build Coastguard Worker if (self_i == 0)
387*635a8641SAndroid Build Coastguard Worker break;
388*635a8641SAndroid Build Coastguard Worker }
389*635a8641SAndroid Build Coastguard Worker return StringPiece16::npos;
390*635a8641SAndroid Build Coastguard Worker }
391*635a8641SAndroid Build Coastguard Worker
392*635a8641SAndroid Build Coastguard Worker template<typename STR>
find_last_not_ofT(const BasicStringPiece<STR> & self,typename STR::value_type c,size_t pos)393*635a8641SAndroid Build Coastguard Worker size_t find_last_not_ofT(const BasicStringPiece<STR>& self,
394*635a8641SAndroid Build Coastguard Worker typename STR::value_type c,
395*635a8641SAndroid Build Coastguard Worker size_t pos) {
396*635a8641SAndroid Build Coastguard Worker if (self.size() == 0)
397*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
398*635a8641SAndroid Build Coastguard Worker
399*635a8641SAndroid Build Coastguard Worker for (size_t i = std::min(pos, self.size() - 1); ; --i) {
400*635a8641SAndroid Build Coastguard Worker if (self.data()[i] != c)
401*635a8641SAndroid Build Coastguard Worker return i;
402*635a8641SAndroid Build Coastguard Worker if (i == 0)
403*635a8641SAndroid Build Coastguard Worker break;
404*635a8641SAndroid Build Coastguard Worker }
405*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>::npos;
406*635a8641SAndroid Build Coastguard Worker }
407*635a8641SAndroid Build Coastguard Worker
find_last_not_of(const StringPiece & self,char c,size_t pos)408*635a8641SAndroid Build Coastguard Worker size_t find_last_not_of(const StringPiece& self,
409*635a8641SAndroid Build Coastguard Worker char c,
410*635a8641SAndroid Build Coastguard Worker size_t pos) {
411*635a8641SAndroid Build Coastguard Worker return find_last_not_ofT(self, c, pos);
412*635a8641SAndroid Build Coastguard Worker }
413*635a8641SAndroid Build Coastguard Worker
find_last_not_of(const StringPiece16 & self,char16 c,size_t pos)414*635a8641SAndroid Build Coastguard Worker size_t find_last_not_of(const StringPiece16& self,
415*635a8641SAndroid Build Coastguard Worker char16 c,
416*635a8641SAndroid Build Coastguard Worker size_t pos) {
417*635a8641SAndroid Build Coastguard Worker return find_last_not_ofT(self, c, pos);
418*635a8641SAndroid Build Coastguard Worker }
419*635a8641SAndroid Build Coastguard Worker
420*635a8641SAndroid Build Coastguard Worker template<typename STR>
substrT(const BasicStringPiece<STR> & self,size_t pos,size_t n)421*635a8641SAndroid Build Coastguard Worker BasicStringPiece<STR> substrT(const BasicStringPiece<STR>& self,
422*635a8641SAndroid Build Coastguard Worker size_t pos,
423*635a8641SAndroid Build Coastguard Worker size_t n) {
424*635a8641SAndroid Build Coastguard Worker if (pos > self.size()) pos = self.size();
425*635a8641SAndroid Build Coastguard Worker if (n > self.size() - pos) n = self.size() - pos;
426*635a8641SAndroid Build Coastguard Worker return BasicStringPiece<STR>(self.data() + pos, n);
427*635a8641SAndroid Build Coastguard Worker }
428*635a8641SAndroid Build Coastguard Worker
substr(const StringPiece & self,size_t pos,size_t n)429*635a8641SAndroid Build Coastguard Worker StringPiece substr(const StringPiece& self,
430*635a8641SAndroid Build Coastguard Worker size_t pos,
431*635a8641SAndroid Build Coastguard Worker size_t n) {
432*635a8641SAndroid Build Coastguard Worker return substrT(self, pos, n);
433*635a8641SAndroid Build Coastguard Worker }
434*635a8641SAndroid Build Coastguard Worker
substr(const StringPiece16 & self,size_t pos,size_t n)435*635a8641SAndroid Build Coastguard Worker StringPiece16 substr(const StringPiece16& self,
436*635a8641SAndroid Build Coastguard Worker size_t pos,
437*635a8641SAndroid Build Coastguard Worker size_t n) {
438*635a8641SAndroid Build Coastguard Worker return substrT(self, pos, n);
439*635a8641SAndroid Build Coastguard Worker }
440*635a8641SAndroid Build Coastguard Worker
441*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
AssertIteratorsInOrder(std::string::const_iterator begin,std::string::const_iterator end)442*635a8641SAndroid Build Coastguard Worker void AssertIteratorsInOrder(std::string::const_iterator begin,
443*635a8641SAndroid Build Coastguard Worker std::string::const_iterator end) {
444*635a8641SAndroid Build Coastguard Worker DCHECK(begin <= end) << "StringPiece iterators swapped or invalid.";
445*635a8641SAndroid Build Coastguard Worker }
AssertIteratorsInOrder(string16::const_iterator begin,string16::const_iterator end)446*635a8641SAndroid Build Coastguard Worker void AssertIteratorsInOrder(string16::const_iterator begin,
447*635a8641SAndroid Build Coastguard Worker string16::const_iterator end) {
448*635a8641SAndroid Build Coastguard Worker DCHECK(begin <= end) << "StringPiece iterators swapped or invalid.";
449*635a8641SAndroid Build Coastguard Worker }
450*635a8641SAndroid Build Coastguard Worker #endif
451*635a8641SAndroid Build Coastguard Worker
452*635a8641SAndroid Build Coastguard Worker } // namespace internal
453*635a8641SAndroid Build Coastguard Worker } // namespace base
454