xref: /aosp_15_r20/external/libchrome/base/strings/string_piece.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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