xref: /aosp_15_r20/external/libchrome/base/strings/string_util.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2013 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 
5*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <ctype.h>
8*635a8641SAndroid Build Coastguard Worker #include <errno.h>
9*635a8641SAndroid Build Coastguard Worker #include <math.h>
10*635a8641SAndroid Build Coastguard Worker #include <stdarg.h>
11*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
12*635a8641SAndroid Build Coastguard Worker #include <stdio.h>
13*635a8641SAndroid Build Coastguard Worker #include <stdlib.h>
14*635a8641SAndroid Build Coastguard Worker #include <string.h>
15*635a8641SAndroid Build Coastguard Worker #include <time.h>
16*635a8641SAndroid Build Coastguard Worker #include <wchar.h>
17*635a8641SAndroid Build Coastguard Worker #include <wctype.h>
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker #include <algorithm>
20*635a8641SAndroid Build Coastguard Worker #include <limits>
21*635a8641SAndroid Build Coastguard Worker #include <vector>
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
24*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
25*635a8641SAndroid Build Coastguard Worker #include "base/memory/singleton.h"
26*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversion_utils.h"
27*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
28*635a8641SAndroid Build Coastguard Worker #include "base/third_party/icu/icu_utf.h"
29*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker namespace base {
32*635a8641SAndroid Build Coastguard Worker 
33*635a8641SAndroid Build Coastguard Worker namespace {
34*635a8641SAndroid Build Coastguard Worker 
35*635a8641SAndroid Build Coastguard Worker // Force the singleton used by EmptyString[16] to be a unique type. This
36*635a8641SAndroid Build Coastguard Worker // prevents other code that might accidentally use Singleton<string> from
37*635a8641SAndroid Build Coastguard Worker // getting our internal one.
38*635a8641SAndroid Build Coastguard Worker struct EmptyStrings {
39*635a8641SAndroid Build Coastguard Worker   EmptyStrings() = default;
40*635a8641SAndroid Build Coastguard Worker   const std::string s;
41*635a8641SAndroid Build Coastguard Worker   const string16 s16;
42*635a8641SAndroid Build Coastguard Worker 
GetInstancebase::__anone93bcdd60111::EmptyStrings43*635a8641SAndroid Build Coastguard Worker   static EmptyStrings* GetInstance() {
44*635a8641SAndroid Build Coastguard Worker     return Singleton<EmptyStrings>::get();
45*635a8641SAndroid Build Coastguard Worker   }
46*635a8641SAndroid Build Coastguard Worker };
47*635a8641SAndroid Build Coastguard Worker 
48*635a8641SAndroid Build Coastguard Worker // Used by ReplaceStringPlaceholders to track the position in the string of
49*635a8641SAndroid Build Coastguard Worker // replaced parameters.
50*635a8641SAndroid Build Coastguard Worker struct ReplacementOffset {
ReplacementOffsetbase::__anone93bcdd60111::ReplacementOffset51*635a8641SAndroid Build Coastguard Worker   ReplacementOffset(uintptr_t parameter, size_t offset)
52*635a8641SAndroid Build Coastguard Worker       : parameter(parameter),
53*635a8641SAndroid Build Coastguard Worker         offset(offset) {}
54*635a8641SAndroid Build Coastguard Worker 
55*635a8641SAndroid Build Coastguard Worker   // Index of the parameter.
56*635a8641SAndroid Build Coastguard Worker   uintptr_t parameter;
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker   // Starting position in the string.
59*635a8641SAndroid Build Coastguard Worker   size_t offset;
60*635a8641SAndroid Build Coastguard Worker };
61*635a8641SAndroid Build Coastguard Worker 
CompareParameter(const ReplacementOffset & elem1,const ReplacementOffset & elem2)62*635a8641SAndroid Build Coastguard Worker static bool CompareParameter(const ReplacementOffset& elem1,
63*635a8641SAndroid Build Coastguard Worker                              const ReplacementOffset& elem2) {
64*635a8641SAndroid Build Coastguard Worker   return elem1.parameter < elem2.parameter;
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker // Overloaded function to append one string onto the end of another. Having a
68*635a8641SAndroid Build Coastguard Worker // separate overload for |source| as both string and StringPiece allows for more
69*635a8641SAndroid Build Coastguard Worker // efficient usage from functions templated to work with either type (avoiding a
70*635a8641SAndroid Build Coastguard Worker // redundant call to the BasicStringPiece constructor in both cases).
71*635a8641SAndroid Build Coastguard Worker template <typename string_type>
AppendToString(string_type * target,const string_type & source)72*635a8641SAndroid Build Coastguard Worker inline void AppendToString(string_type* target, const string_type& source) {
73*635a8641SAndroid Build Coastguard Worker   target->append(source);
74*635a8641SAndroid Build Coastguard Worker }
75*635a8641SAndroid Build Coastguard Worker 
76*635a8641SAndroid Build Coastguard Worker template <typename string_type>
AppendToString(string_type * target,const BasicStringPiece<string_type> & source)77*635a8641SAndroid Build Coastguard Worker inline void AppendToString(string_type* target,
78*635a8641SAndroid Build Coastguard Worker                            const BasicStringPiece<string_type>& source) {
79*635a8641SAndroid Build Coastguard Worker   source.AppendToString(target);
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker // Assuming that a pointer is the size of a "machine word", then
83*635a8641SAndroid Build Coastguard Worker // uintptr_t is an integer type that is also a machine word.
84*635a8641SAndroid Build Coastguard Worker typedef uintptr_t MachineWord;
85*635a8641SAndroid Build Coastguard Worker const uintptr_t kMachineWordAlignmentMask = sizeof(MachineWord) - 1;
86*635a8641SAndroid Build Coastguard Worker 
IsAlignedToMachineWord(const void * pointer)87*635a8641SAndroid Build Coastguard Worker inline bool IsAlignedToMachineWord(const void* pointer) {
88*635a8641SAndroid Build Coastguard Worker   return !(reinterpret_cast<MachineWord>(pointer) & kMachineWordAlignmentMask);
89*635a8641SAndroid Build Coastguard Worker }
90*635a8641SAndroid Build Coastguard Worker 
AlignToMachineWord(T * pointer)91*635a8641SAndroid Build Coastguard Worker template<typename T> inline T* AlignToMachineWord(T* pointer) {
92*635a8641SAndroid Build Coastguard Worker   return reinterpret_cast<T*>(reinterpret_cast<MachineWord>(pointer) &
93*635a8641SAndroid Build Coastguard Worker                               ~kMachineWordAlignmentMask);
94*635a8641SAndroid Build Coastguard Worker }
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker template<size_t size, typename CharacterType> struct NonASCIIMask;
97*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<4, char16> {
valuebase::__anone93bcdd60111::NonASCIIMask98*635a8641SAndroid Build Coastguard Worker     static inline uint32_t value() { return 0xFF80FF80U; }
99*635a8641SAndroid Build Coastguard Worker };
100*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<4, char> {
valuebase::__anone93bcdd60111::NonASCIIMask101*635a8641SAndroid Build Coastguard Worker     static inline uint32_t value() { return 0x80808080U; }
102*635a8641SAndroid Build Coastguard Worker };
103*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<8, char16> {
valuebase::__anone93bcdd60111::NonASCIIMask104*635a8641SAndroid Build Coastguard Worker     static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; }
105*635a8641SAndroid Build Coastguard Worker };
106*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<8, char> {
valuebase::__anone93bcdd60111::NonASCIIMask107*635a8641SAndroid Build Coastguard Worker     static inline uint64_t value() { return 0x8080808080808080ULL; }
108*635a8641SAndroid Build Coastguard Worker };
109*635a8641SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_UTF32)
110*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<4, wchar_t> {
valuebase::__anone93bcdd60111::NonASCIIMask111*635a8641SAndroid Build Coastguard Worker     static inline uint32_t value() { return 0xFFFFFF80U; }
112*635a8641SAndroid Build Coastguard Worker };
113*635a8641SAndroid Build Coastguard Worker template<> struct NonASCIIMask<8, wchar_t> {
valuebase::__anone93bcdd60111::NonASCIIMask114*635a8641SAndroid Build Coastguard Worker     static inline uint64_t value() { return 0xFFFFFF80FFFFFF80ULL; }
115*635a8641SAndroid Build Coastguard Worker };
116*635a8641SAndroid Build Coastguard Worker #endif  // WCHAR_T_IS_UTF32
117*635a8641SAndroid Build Coastguard Worker 
118*635a8641SAndroid Build Coastguard Worker }  // namespace
119*635a8641SAndroid Build Coastguard Worker 
IsWprintfFormatPortable(const wchar_t * format)120*635a8641SAndroid Build Coastguard Worker bool IsWprintfFormatPortable(const wchar_t* format) {
121*635a8641SAndroid Build Coastguard Worker   for (const wchar_t* position = format; *position != '\0'; ++position) {
122*635a8641SAndroid Build Coastguard Worker     if (*position == '%') {
123*635a8641SAndroid Build Coastguard Worker       bool in_specification = true;
124*635a8641SAndroid Build Coastguard Worker       bool modifier_l = false;
125*635a8641SAndroid Build Coastguard Worker       while (in_specification) {
126*635a8641SAndroid Build Coastguard Worker         // Eat up characters until reaching a known specifier.
127*635a8641SAndroid Build Coastguard Worker         if (*++position == '\0') {
128*635a8641SAndroid Build Coastguard Worker           // The format string ended in the middle of a specification.  Call
129*635a8641SAndroid Build Coastguard Worker           // it portable because no unportable specifications were found.  The
130*635a8641SAndroid Build Coastguard Worker           // string is equally broken on all platforms.
131*635a8641SAndroid Build Coastguard Worker           return true;
132*635a8641SAndroid Build Coastguard Worker         }
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker         if (*position == 'l') {
135*635a8641SAndroid Build Coastguard Worker           // 'l' is the only thing that can save the 's' and 'c' specifiers.
136*635a8641SAndroid Build Coastguard Worker           modifier_l = true;
137*635a8641SAndroid Build Coastguard Worker         } else if (((*position == 's' || *position == 'c') && !modifier_l) ||
138*635a8641SAndroid Build Coastguard Worker                    *position == 'S' || *position == 'C' || *position == 'F' ||
139*635a8641SAndroid Build Coastguard Worker                    *position == 'D' || *position == 'O' || *position == 'U') {
140*635a8641SAndroid Build Coastguard Worker           // Not portable.
141*635a8641SAndroid Build Coastguard Worker           return false;
142*635a8641SAndroid Build Coastguard Worker         }
143*635a8641SAndroid Build Coastguard Worker 
144*635a8641SAndroid Build Coastguard Worker         if (wcschr(L"diouxXeEfgGaAcspn%", *position)) {
145*635a8641SAndroid Build Coastguard Worker           // Portable, keep scanning the rest of the format string.
146*635a8641SAndroid Build Coastguard Worker           in_specification = false;
147*635a8641SAndroid Build Coastguard Worker         }
148*635a8641SAndroid Build Coastguard Worker       }
149*635a8641SAndroid Build Coastguard Worker     }
150*635a8641SAndroid Build Coastguard Worker   }
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker   return true;
153*635a8641SAndroid Build Coastguard Worker }
154*635a8641SAndroid Build Coastguard Worker 
155*635a8641SAndroid Build Coastguard Worker namespace {
156*635a8641SAndroid Build Coastguard Worker 
157*635a8641SAndroid Build Coastguard Worker template<typename StringType>
ToLowerASCIIImpl(BasicStringPiece<StringType> str)158*635a8641SAndroid Build Coastguard Worker StringType ToLowerASCIIImpl(BasicStringPiece<StringType> str) {
159*635a8641SAndroid Build Coastguard Worker   StringType ret;
160*635a8641SAndroid Build Coastguard Worker   ret.reserve(str.size());
161*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < str.size(); i++)
162*635a8641SAndroid Build Coastguard Worker     ret.push_back(ToLowerASCII(str[i]));
163*635a8641SAndroid Build Coastguard Worker   return ret;
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker 
166*635a8641SAndroid Build Coastguard Worker template<typename StringType>
ToUpperASCIIImpl(BasicStringPiece<StringType> str)167*635a8641SAndroid Build Coastguard Worker StringType ToUpperASCIIImpl(BasicStringPiece<StringType> str) {
168*635a8641SAndroid Build Coastguard Worker   StringType ret;
169*635a8641SAndroid Build Coastguard Worker   ret.reserve(str.size());
170*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < str.size(); i++)
171*635a8641SAndroid Build Coastguard Worker     ret.push_back(ToUpperASCII(str[i]));
172*635a8641SAndroid Build Coastguard Worker   return ret;
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker 
175*635a8641SAndroid Build Coastguard Worker }  // namespace
176*635a8641SAndroid Build Coastguard Worker 
ToLowerASCII(StringPiece str)177*635a8641SAndroid Build Coastguard Worker std::string ToLowerASCII(StringPiece str) {
178*635a8641SAndroid Build Coastguard Worker   return ToLowerASCIIImpl<std::string>(str);
179*635a8641SAndroid Build Coastguard Worker }
180*635a8641SAndroid Build Coastguard Worker 
ToLowerASCII(StringPiece16 str)181*635a8641SAndroid Build Coastguard Worker string16 ToLowerASCII(StringPiece16 str) {
182*635a8641SAndroid Build Coastguard Worker   return ToLowerASCIIImpl<string16>(str);
183*635a8641SAndroid Build Coastguard Worker }
184*635a8641SAndroid Build Coastguard Worker 
ToUpperASCII(StringPiece str)185*635a8641SAndroid Build Coastguard Worker std::string ToUpperASCII(StringPiece str) {
186*635a8641SAndroid Build Coastguard Worker   return ToUpperASCIIImpl<std::string>(str);
187*635a8641SAndroid Build Coastguard Worker }
188*635a8641SAndroid Build Coastguard Worker 
ToUpperASCII(StringPiece16 str)189*635a8641SAndroid Build Coastguard Worker string16 ToUpperASCII(StringPiece16 str) {
190*635a8641SAndroid Build Coastguard Worker   return ToUpperASCIIImpl<string16>(str);
191*635a8641SAndroid Build Coastguard Worker }
192*635a8641SAndroid Build Coastguard Worker 
193*635a8641SAndroid Build Coastguard Worker template<class StringType>
CompareCaseInsensitiveASCIIT(BasicStringPiece<StringType> a,BasicStringPiece<StringType> b)194*635a8641SAndroid Build Coastguard Worker int CompareCaseInsensitiveASCIIT(BasicStringPiece<StringType> a,
195*635a8641SAndroid Build Coastguard Worker                                  BasicStringPiece<StringType> b) {
196*635a8641SAndroid Build Coastguard Worker   // Find the first characters that aren't equal and compare them.  If the end
197*635a8641SAndroid Build Coastguard Worker   // of one of the strings is found before a nonequal character, the lengths
198*635a8641SAndroid Build Coastguard Worker   // of the strings are compared.
199*635a8641SAndroid Build Coastguard Worker   size_t i = 0;
200*635a8641SAndroid Build Coastguard Worker   while (i < a.length() && i < b.length()) {
201*635a8641SAndroid Build Coastguard Worker     typename StringType::value_type lower_a = ToLowerASCII(a[i]);
202*635a8641SAndroid Build Coastguard Worker     typename StringType::value_type lower_b = ToLowerASCII(b[i]);
203*635a8641SAndroid Build Coastguard Worker     if (lower_a < lower_b)
204*635a8641SAndroid Build Coastguard Worker       return -1;
205*635a8641SAndroid Build Coastguard Worker     if (lower_a > lower_b)
206*635a8641SAndroid Build Coastguard Worker       return 1;
207*635a8641SAndroid Build Coastguard Worker     i++;
208*635a8641SAndroid Build Coastguard Worker   }
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker   // End of one string hit before finding a different character. Expect the
211*635a8641SAndroid Build Coastguard Worker   // common case to be "strings equal" at this point so check that first.
212*635a8641SAndroid Build Coastguard Worker   if (a.length() == b.length())
213*635a8641SAndroid Build Coastguard Worker     return 0;
214*635a8641SAndroid Build Coastguard Worker 
215*635a8641SAndroid Build Coastguard Worker   if (a.length() < b.length())
216*635a8641SAndroid Build Coastguard Worker     return -1;
217*635a8641SAndroid Build Coastguard Worker   return 1;
218*635a8641SAndroid Build Coastguard Worker }
219*635a8641SAndroid Build Coastguard Worker 
CompareCaseInsensitiveASCII(StringPiece a,StringPiece b)220*635a8641SAndroid Build Coastguard Worker int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) {
221*635a8641SAndroid Build Coastguard Worker   return CompareCaseInsensitiveASCIIT<std::string>(a, b);
222*635a8641SAndroid Build Coastguard Worker }
223*635a8641SAndroid Build Coastguard Worker 
CompareCaseInsensitiveASCII(StringPiece16 a,StringPiece16 b)224*635a8641SAndroid Build Coastguard Worker int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) {
225*635a8641SAndroid Build Coastguard Worker   return CompareCaseInsensitiveASCIIT<string16>(a, b);
226*635a8641SAndroid Build Coastguard Worker }
227*635a8641SAndroid Build Coastguard Worker 
EqualsCaseInsensitiveASCII(StringPiece a,StringPiece b)228*635a8641SAndroid Build Coastguard Worker bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) {
229*635a8641SAndroid Build Coastguard Worker   if (a.length() != b.length())
230*635a8641SAndroid Build Coastguard Worker     return false;
231*635a8641SAndroid Build Coastguard Worker   return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0;
232*635a8641SAndroid Build Coastguard Worker }
233*635a8641SAndroid Build Coastguard Worker 
EqualsCaseInsensitiveASCII(StringPiece16 a,StringPiece16 b)234*635a8641SAndroid Build Coastguard Worker bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) {
235*635a8641SAndroid Build Coastguard Worker   if (a.length() != b.length())
236*635a8641SAndroid Build Coastguard Worker     return false;
237*635a8641SAndroid Build Coastguard Worker   return CompareCaseInsensitiveASCIIT<string16>(a, b) == 0;
238*635a8641SAndroid Build Coastguard Worker }
239*635a8641SAndroid Build Coastguard Worker 
EmptyString()240*635a8641SAndroid Build Coastguard Worker const std::string& EmptyString() {
241*635a8641SAndroid Build Coastguard Worker   return EmptyStrings::GetInstance()->s;
242*635a8641SAndroid Build Coastguard Worker }
243*635a8641SAndroid Build Coastguard Worker 
EmptyString16()244*635a8641SAndroid Build Coastguard Worker const string16& EmptyString16() {
245*635a8641SAndroid Build Coastguard Worker   return EmptyStrings::GetInstance()->s16;
246*635a8641SAndroid Build Coastguard Worker }
247*635a8641SAndroid Build Coastguard Worker 
248*635a8641SAndroid Build Coastguard Worker template <class StringType>
249*635a8641SAndroid Build Coastguard Worker bool ReplaceCharsT(const StringType& input,
250*635a8641SAndroid Build Coastguard Worker                    BasicStringPiece<StringType> find_any_of_these,
251*635a8641SAndroid Build Coastguard Worker                    BasicStringPiece<StringType> replace_with,
252*635a8641SAndroid Build Coastguard Worker                    StringType* output);
253*635a8641SAndroid Build Coastguard Worker 
ReplaceChars(const string16 & input,StringPiece16 replace_chars,const string16 & replace_with,string16 * output)254*635a8641SAndroid Build Coastguard Worker bool ReplaceChars(const string16& input,
255*635a8641SAndroid Build Coastguard Worker                   StringPiece16 replace_chars,
256*635a8641SAndroid Build Coastguard Worker                   const string16& replace_with,
257*635a8641SAndroid Build Coastguard Worker                   string16* output) {
258*635a8641SAndroid Build Coastguard Worker   return ReplaceCharsT(input, replace_chars, StringPiece16(replace_with),
259*635a8641SAndroid Build Coastguard Worker                        output);
260*635a8641SAndroid Build Coastguard Worker }
261*635a8641SAndroid Build Coastguard Worker 
ReplaceChars(const std::string & input,StringPiece replace_chars,const std::string & replace_with,std::string * output)262*635a8641SAndroid Build Coastguard Worker bool ReplaceChars(const std::string& input,
263*635a8641SAndroid Build Coastguard Worker                   StringPiece replace_chars,
264*635a8641SAndroid Build Coastguard Worker                   const std::string& replace_with,
265*635a8641SAndroid Build Coastguard Worker                   std::string* output) {
266*635a8641SAndroid Build Coastguard Worker   return ReplaceCharsT(input, replace_chars, StringPiece(replace_with), output);
267*635a8641SAndroid Build Coastguard Worker }
268*635a8641SAndroid Build Coastguard Worker 
RemoveChars(const string16 & input,StringPiece16 remove_chars,string16 * output)269*635a8641SAndroid Build Coastguard Worker bool RemoveChars(const string16& input,
270*635a8641SAndroid Build Coastguard Worker                  StringPiece16 remove_chars,
271*635a8641SAndroid Build Coastguard Worker                  string16* output) {
272*635a8641SAndroid Build Coastguard Worker   return ReplaceCharsT(input, remove_chars, StringPiece16(), output);
273*635a8641SAndroid Build Coastguard Worker }
274*635a8641SAndroid Build Coastguard Worker 
RemoveChars(const std::string & input,StringPiece remove_chars,std::string * output)275*635a8641SAndroid Build Coastguard Worker bool RemoveChars(const std::string& input,
276*635a8641SAndroid Build Coastguard Worker                  StringPiece remove_chars,
277*635a8641SAndroid Build Coastguard Worker                  std::string* output) {
278*635a8641SAndroid Build Coastguard Worker   return ReplaceCharsT(input, remove_chars, StringPiece(), output);
279*635a8641SAndroid Build Coastguard Worker }
280*635a8641SAndroid Build Coastguard Worker 
281*635a8641SAndroid Build Coastguard Worker template<typename Str>
TrimStringT(const Str & input,BasicStringPiece<Str> trim_chars,TrimPositions positions,Str * output)282*635a8641SAndroid Build Coastguard Worker TrimPositions TrimStringT(const Str& input,
283*635a8641SAndroid Build Coastguard Worker                           BasicStringPiece<Str> trim_chars,
284*635a8641SAndroid Build Coastguard Worker                           TrimPositions positions,
285*635a8641SAndroid Build Coastguard Worker                           Str* output) {
286*635a8641SAndroid Build Coastguard Worker   // Find the edges of leading/trailing whitespace as desired. Need to use
287*635a8641SAndroid Build Coastguard Worker   // a StringPiece version of input to be able to call find* on it with the
288*635a8641SAndroid Build Coastguard Worker   // StringPiece version of trim_chars (normally the trim_chars will be a
289*635a8641SAndroid Build Coastguard Worker   // constant so avoid making a copy).
290*635a8641SAndroid Build Coastguard Worker   BasicStringPiece<Str> input_piece(input);
291*635a8641SAndroid Build Coastguard Worker   const size_t last_char = input.length() - 1;
292*635a8641SAndroid Build Coastguard Worker   const size_t first_good_char = (positions & TRIM_LEADING) ?
293*635a8641SAndroid Build Coastguard Worker       input_piece.find_first_not_of(trim_chars) : 0;
294*635a8641SAndroid Build Coastguard Worker   const size_t last_good_char = (positions & TRIM_TRAILING) ?
295*635a8641SAndroid Build Coastguard Worker       input_piece.find_last_not_of(trim_chars) : last_char;
296*635a8641SAndroid Build Coastguard Worker 
297*635a8641SAndroid Build Coastguard Worker   // When the string was all trimmed, report that we stripped off characters
298*635a8641SAndroid Build Coastguard Worker   // from whichever position the caller was interested in. For empty input, we
299*635a8641SAndroid Build Coastguard Worker   // stripped no characters, but we still need to clear |output|.
300*635a8641SAndroid Build Coastguard Worker   if (input.empty() ||
301*635a8641SAndroid Build Coastguard Worker       (first_good_char == Str::npos) || (last_good_char == Str::npos)) {
302*635a8641SAndroid Build Coastguard Worker     bool input_was_empty = input.empty();  // in case output == &input
303*635a8641SAndroid Build Coastguard Worker     output->clear();
304*635a8641SAndroid Build Coastguard Worker     return input_was_empty ? TRIM_NONE : positions;
305*635a8641SAndroid Build Coastguard Worker   }
306*635a8641SAndroid Build Coastguard Worker 
307*635a8641SAndroid Build Coastguard Worker   // Trim.
308*635a8641SAndroid Build Coastguard Worker   *output =
309*635a8641SAndroid Build Coastguard Worker       input.substr(first_good_char, last_good_char - first_good_char + 1);
310*635a8641SAndroid Build Coastguard Worker 
311*635a8641SAndroid Build Coastguard Worker   // Return where we trimmed from.
312*635a8641SAndroid Build Coastguard Worker   return static_cast<TrimPositions>(
313*635a8641SAndroid Build Coastguard Worker       ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) |
314*635a8641SAndroid Build Coastguard Worker       ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING));
315*635a8641SAndroid Build Coastguard Worker }
316*635a8641SAndroid Build Coastguard Worker 
TrimString(const string16 & input,StringPiece16 trim_chars,string16 * output)317*635a8641SAndroid Build Coastguard Worker bool TrimString(const string16& input,
318*635a8641SAndroid Build Coastguard Worker                 StringPiece16 trim_chars,
319*635a8641SAndroid Build Coastguard Worker                 string16* output) {
320*635a8641SAndroid Build Coastguard Worker   return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
321*635a8641SAndroid Build Coastguard Worker }
322*635a8641SAndroid Build Coastguard Worker 
TrimString(const std::string & input,StringPiece trim_chars,std::string * output)323*635a8641SAndroid Build Coastguard Worker bool TrimString(const std::string& input,
324*635a8641SAndroid Build Coastguard Worker                 StringPiece trim_chars,
325*635a8641SAndroid Build Coastguard Worker                 std::string* output) {
326*635a8641SAndroid Build Coastguard Worker   return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
327*635a8641SAndroid Build Coastguard Worker }
328*635a8641SAndroid Build Coastguard Worker 
329*635a8641SAndroid Build Coastguard Worker template<typename Str>
TrimStringPieceT(BasicStringPiece<Str> input,BasicStringPiece<Str> trim_chars,TrimPositions positions)330*635a8641SAndroid Build Coastguard Worker BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input,
331*635a8641SAndroid Build Coastguard Worker                                        BasicStringPiece<Str> trim_chars,
332*635a8641SAndroid Build Coastguard Worker                                        TrimPositions positions) {
333*635a8641SAndroid Build Coastguard Worker   size_t begin = (positions & TRIM_LEADING) ?
334*635a8641SAndroid Build Coastguard Worker       input.find_first_not_of(trim_chars) : 0;
335*635a8641SAndroid Build Coastguard Worker   size_t end = (positions & TRIM_TRAILING) ?
336*635a8641SAndroid Build Coastguard Worker       input.find_last_not_of(trim_chars) + 1 : input.size();
337*635a8641SAndroid Build Coastguard Worker   return input.substr(begin, end - begin);
338*635a8641SAndroid Build Coastguard Worker }
339*635a8641SAndroid Build Coastguard Worker 
TrimString(StringPiece16 input,StringPiece16 trim_chars,TrimPositions positions)340*635a8641SAndroid Build Coastguard Worker StringPiece16 TrimString(StringPiece16 input,
341*635a8641SAndroid Build Coastguard Worker                          StringPiece16 trim_chars,
342*635a8641SAndroid Build Coastguard Worker                          TrimPositions positions) {
343*635a8641SAndroid Build Coastguard Worker   return TrimStringPieceT(input, trim_chars, positions);
344*635a8641SAndroid Build Coastguard Worker }
345*635a8641SAndroid Build Coastguard Worker 
TrimString(StringPiece input,StringPiece trim_chars,TrimPositions positions)346*635a8641SAndroid Build Coastguard Worker StringPiece TrimString(StringPiece input,
347*635a8641SAndroid Build Coastguard Worker                        StringPiece trim_chars,
348*635a8641SAndroid Build Coastguard Worker                        TrimPositions positions) {
349*635a8641SAndroid Build Coastguard Worker   return TrimStringPieceT(input, trim_chars, positions);
350*635a8641SAndroid Build Coastguard Worker }
351*635a8641SAndroid Build Coastguard Worker 
TruncateUTF8ToByteSize(const std::string & input,const size_t byte_size,std::string * output)352*635a8641SAndroid Build Coastguard Worker void TruncateUTF8ToByteSize(const std::string& input,
353*635a8641SAndroid Build Coastguard Worker                             const size_t byte_size,
354*635a8641SAndroid Build Coastguard Worker                             std::string* output) {
355*635a8641SAndroid Build Coastguard Worker   DCHECK(output);
356*635a8641SAndroid Build Coastguard Worker   if (byte_size > input.length()) {
357*635a8641SAndroid Build Coastguard Worker     *output = input;
358*635a8641SAndroid Build Coastguard Worker     return;
359*635a8641SAndroid Build Coastguard Worker   }
360*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(byte_size,
361*635a8641SAndroid Build Coastguard Worker             static_cast<uint32_t>(std::numeric_limits<int32_t>::max()));
362*635a8641SAndroid Build Coastguard Worker   // Note: This cast is necessary because CBU8_NEXT uses int32_ts.
363*635a8641SAndroid Build Coastguard Worker   int32_t truncation_length = static_cast<int32_t>(byte_size);
364*635a8641SAndroid Build Coastguard Worker   int32_t char_index = truncation_length - 1;
365*635a8641SAndroid Build Coastguard Worker   const char* data = input.data();
366*635a8641SAndroid Build Coastguard Worker 
367*635a8641SAndroid Build Coastguard Worker   // Using CBU8, we will move backwards from the truncation point
368*635a8641SAndroid Build Coastguard Worker   // to the beginning of the string looking for a valid UTF8
369*635a8641SAndroid Build Coastguard Worker   // character.  Once a full UTF8 character is found, we will
370*635a8641SAndroid Build Coastguard Worker   // truncate the string to the end of that character.
371*635a8641SAndroid Build Coastguard Worker   while (char_index >= 0) {
372*635a8641SAndroid Build Coastguard Worker     int32_t prev = char_index;
373*635a8641SAndroid Build Coastguard Worker     base_icu::UChar32 code_point = 0;
374*635a8641SAndroid Build Coastguard Worker     CBU8_NEXT(data, char_index, truncation_length, code_point);
375*635a8641SAndroid Build Coastguard Worker     if (!IsValidCharacter(code_point) ||
376*635a8641SAndroid Build Coastguard Worker         !IsValidCodepoint(code_point)) {
377*635a8641SAndroid Build Coastguard Worker       char_index = prev - 1;
378*635a8641SAndroid Build Coastguard Worker     } else {
379*635a8641SAndroid Build Coastguard Worker       break;
380*635a8641SAndroid Build Coastguard Worker     }
381*635a8641SAndroid Build Coastguard Worker   }
382*635a8641SAndroid Build Coastguard Worker 
383*635a8641SAndroid Build Coastguard Worker   if (char_index >= 0 )
384*635a8641SAndroid Build Coastguard Worker     *output = input.substr(0, char_index);
385*635a8641SAndroid Build Coastguard Worker   else
386*635a8641SAndroid Build Coastguard Worker     output->clear();
387*635a8641SAndroid Build Coastguard Worker }
388*635a8641SAndroid Build Coastguard Worker 
TrimWhitespace(const string16 & input,TrimPositions positions,string16 * output)389*635a8641SAndroid Build Coastguard Worker TrimPositions TrimWhitespace(const string16& input,
390*635a8641SAndroid Build Coastguard Worker                              TrimPositions positions,
391*635a8641SAndroid Build Coastguard Worker                              string16* output) {
392*635a8641SAndroid Build Coastguard Worker   return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output);
393*635a8641SAndroid Build Coastguard Worker }
394*635a8641SAndroid Build Coastguard Worker 
TrimWhitespace(StringPiece16 input,TrimPositions positions)395*635a8641SAndroid Build Coastguard Worker StringPiece16 TrimWhitespace(StringPiece16 input,
396*635a8641SAndroid Build Coastguard Worker                              TrimPositions positions) {
397*635a8641SAndroid Build Coastguard Worker   return TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), positions);
398*635a8641SAndroid Build Coastguard Worker }
399*635a8641SAndroid Build Coastguard Worker 
TrimWhitespaceASCII(const std::string & input,TrimPositions positions,std::string * output)400*635a8641SAndroid Build Coastguard Worker TrimPositions TrimWhitespaceASCII(const std::string& input,
401*635a8641SAndroid Build Coastguard Worker                                   TrimPositions positions,
402*635a8641SAndroid Build Coastguard Worker                                   std::string* output) {
403*635a8641SAndroid Build Coastguard Worker   return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output);
404*635a8641SAndroid Build Coastguard Worker }
405*635a8641SAndroid Build Coastguard Worker 
TrimWhitespaceASCII(StringPiece input,TrimPositions positions)406*635a8641SAndroid Build Coastguard Worker StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions) {
407*635a8641SAndroid Build Coastguard Worker   return TrimStringPieceT(input, StringPiece(kWhitespaceASCII), positions);
408*635a8641SAndroid Build Coastguard Worker }
409*635a8641SAndroid Build Coastguard Worker 
410*635a8641SAndroid Build Coastguard Worker template<typename STR>
CollapseWhitespaceT(const STR & text,bool trim_sequences_with_line_breaks)411*635a8641SAndroid Build Coastguard Worker STR CollapseWhitespaceT(const STR& text,
412*635a8641SAndroid Build Coastguard Worker                         bool trim_sequences_with_line_breaks) {
413*635a8641SAndroid Build Coastguard Worker   STR result;
414*635a8641SAndroid Build Coastguard Worker   result.resize(text.size());
415*635a8641SAndroid Build Coastguard Worker 
416*635a8641SAndroid Build Coastguard Worker   // Set flags to pretend we're already in a trimmed whitespace sequence, so we
417*635a8641SAndroid Build Coastguard Worker   // will trim any leading whitespace.
418*635a8641SAndroid Build Coastguard Worker   bool in_whitespace = true;
419*635a8641SAndroid Build Coastguard Worker   bool already_trimmed = true;
420*635a8641SAndroid Build Coastguard Worker 
421*635a8641SAndroid Build Coastguard Worker   int chars_written = 0;
422*635a8641SAndroid Build Coastguard Worker   for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) {
423*635a8641SAndroid Build Coastguard Worker     if (IsUnicodeWhitespace(*i)) {
424*635a8641SAndroid Build Coastguard Worker       if (!in_whitespace) {
425*635a8641SAndroid Build Coastguard Worker         // Reduce all whitespace sequences to a single space.
426*635a8641SAndroid Build Coastguard Worker         in_whitespace = true;
427*635a8641SAndroid Build Coastguard Worker         result[chars_written++] = L' ';
428*635a8641SAndroid Build Coastguard Worker       }
429*635a8641SAndroid Build Coastguard Worker       if (trim_sequences_with_line_breaks && !already_trimmed &&
430*635a8641SAndroid Build Coastguard Worker           ((*i == '\n') || (*i == '\r'))) {
431*635a8641SAndroid Build Coastguard Worker         // Whitespace sequences containing CR or LF are eliminated entirely.
432*635a8641SAndroid Build Coastguard Worker         already_trimmed = true;
433*635a8641SAndroid Build Coastguard Worker         --chars_written;
434*635a8641SAndroid Build Coastguard Worker       }
435*635a8641SAndroid Build Coastguard Worker     } else {
436*635a8641SAndroid Build Coastguard Worker       // Non-whitespace chracters are copied straight across.
437*635a8641SAndroid Build Coastguard Worker       in_whitespace = false;
438*635a8641SAndroid Build Coastguard Worker       already_trimmed = false;
439*635a8641SAndroid Build Coastguard Worker       result[chars_written++] = *i;
440*635a8641SAndroid Build Coastguard Worker     }
441*635a8641SAndroid Build Coastguard Worker   }
442*635a8641SAndroid Build Coastguard Worker 
443*635a8641SAndroid Build Coastguard Worker   if (in_whitespace && !already_trimmed) {
444*635a8641SAndroid Build Coastguard Worker     // Any trailing whitespace is eliminated.
445*635a8641SAndroid Build Coastguard Worker     --chars_written;
446*635a8641SAndroid Build Coastguard Worker   }
447*635a8641SAndroid Build Coastguard Worker 
448*635a8641SAndroid Build Coastguard Worker   result.resize(chars_written);
449*635a8641SAndroid Build Coastguard Worker   return result;
450*635a8641SAndroid Build Coastguard Worker }
451*635a8641SAndroid Build Coastguard Worker 
CollapseWhitespace(const string16 & text,bool trim_sequences_with_line_breaks)452*635a8641SAndroid Build Coastguard Worker string16 CollapseWhitespace(const string16& text,
453*635a8641SAndroid Build Coastguard Worker                             bool trim_sequences_with_line_breaks) {
454*635a8641SAndroid Build Coastguard Worker   return CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
455*635a8641SAndroid Build Coastguard Worker }
456*635a8641SAndroid Build Coastguard Worker 
CollapseWhitespaceASCII(const std::string & text,bool trim_sequences_with_line_breaks)457*635a8641SAndroid Build Coastguard Worker std::string CollapseWhitespaceASCII(const std::string& text,
458*635a8641SAndroid Build Coastguard Worker                                     bool trim_sequences_with_line_breaks) {
459*635a8641SAndroid Build Coastguard Worker   return CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
460*635a8641SAndroid Build Coastguard Worker }
461*635a8641SAndroid Build Coastguard Worker 
ContainsOnlyChars(StringPiece input,StringPiece characters)462*635a8641SAndroid Build Coastguard Worker bool ContainsOnlyChars(StringPiece input, StringPiece characters) {
463*635a8641SAndroid Build Coastguard Worker   return input.find_first_not_of(characters) == StringPiece::npos;
464*635a8641SAndroid Build Coastguard Worker }
465*635a8641SAndroid Build Coastguard Worker 
ContainsOnlyChars(StringPiece16 input,StringPiece16 characters)466*635a8641SAndroid Build Coastguard Worker bool ContainsOnlyChars(StringPiece16 input, StringPiece16 characters) {
467*635a8641SAndroid Build Coastguard Worker   return input.find_first_not_of(characters) == StringPiece16::npos;
468*635a8641SAndroid Build Coastguard Worker }
469*635a8641SAndroid Build Coastguard Worker 
470*635a8641SAndroid Build Coastguard Worker template <class Char>
DoIsStringASCII(const Char * characters,size_t length)471*635a8641SAndroid Build Coastguard Worker inline bool DoIsStringASCII(const Char* characters, size_t length) {
472*635a8641SAndroid Build Coastguard Worker   MachineWord all_char_bits = 0;
473*635a8641SAndroid Build Coastguard Worker   const Char* end = characters + length;
474*635a8641SAndroid Build Coastguard Worker 
475*635a8641SAndroid Build Coastguard Worker   // Prologue: align the input.
476*635a8641SAndroid Build Coastguard Worker   while (!IsAlignedToMachineWord(characters) && characters != end) {
477*635a8641SAndroid Build Coastguard Worker     all_char_bits |= *characters;
478*635a8641SAndroid Build Coastguard Worker     ++characters;
479*635a8641SAndroid Build Coastguard Worker   }
480*635a8641SAndroid Build Coastguard Worker 
481*635a8641SAndroid Build Coastguard Worker   // Compare the values of CPU word size.
482*635a8641SAndroid Build Coastguard Worker   const Char* word_end = AlignToMachineWord(end);
483*635a8641SAndroid Build Coastguard Worker   const size_t loop_increment = sizeof(MachineWord) / sizeof(Char);
484*635a8641SAndroid Build Coastguard Worker   while (characters < word_end) {
485*635a8641SAndroid Build Coastguard Worker     all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters));
486*635a8641SAndroid Build Coastguard Worker     characters += loop_increment;
487*635a8641SAndroid Build Coastguard Worker   }
488*635a8641SAndroid Build Coastguard Worker 
489*635a8641SAndroid Build Coastguard Worker   // Process the remaining bytes.
490*635a8641SAndroid Build Coastguard Worker   while (characters != end) {
491*635a8641SAndroid Build Coastguard Worker     all_char_bits |= *characters;
492*635a8641SAndroid Build Coastguard Worker     ++characters;
493*635a8641SAndroid Build Coastguard Worker   }
494*635a8641SAndroid Build Coastguard Worker 
495*635a8641SAndroid Build Coastguard Worker   MachineWord non_ascii_bit_mask =
496*635a8641SAndroid Build Coastguard Worker       NonASCIIMask<sizeof(MachineWord), Char>::value();
497*635a8641SAndroid Build Coastguard Worker   return !(all_char_bits & non_ascii_bit_mask);
498*635a8641SAndroid Build Coastguard Worker }
499*635a8641SAndroid Build Coastguard Worker 
IsStringASCII(StringPiece str)500*635a8641SAndroid Build Coastguard Worker bool IsStringASCII(StringPiece str) {
501*635a8641SAndroid Build Coastguard Worker   return DoIsStringASCII(str.data(), str.length());
502*635a8641SAndroid Build Coastguard Worker }
503*635a8641SAndroid Build Coastguard Worker 
IsStringASCII(StringPiece16 str)504*635a8641SAndroid Build Coastguard Worker bool IsStringASCII(StringPiece16 str) {
505*635a8641SAndroid Build Coastguard Worker   return DoIsStringASCII(str.data(), str.length());
506*635a8641SAndroid Build Coastguard Worker }
507*635a8641SAndroid Build Coastguard Worker 
508*635a8641SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_UTF32)
IsStringASCII(WStringPiece str)509*635a8641SAndroid Build Coastguard Worker bool IsStringASCII(WStringPiece str) {
510*635a8641SAndroid Build Coastguard Worker   return DoIsStringASCII(str.data(), str.length());
511*635a8641SAndroid Build Coastguard Worker }
512*635a8641SAndroid Build Coastguard Worker #endif
513*635a8641SAndroid Build Coastguard Worker 
IsStringUTF8(StringPiece str)514*635a8641SAndroid Build Coastguard Worker bool IsStringUTF8(StringPiece str) {
515*635a8641SAndroid Build Coastguard Worker   const char *src = str.data();
516*635a8641SAndroid Build Coastguard Worker   int32_t src_len = static_cast<int32_t>(str.length());
517*635a8641SAndroid Build Coastguard Worker   int32_t char_index = 0;
518*635a8641SAndroid Build Coastguard Worker 
519*635a8641SAndroid Build Coastguard Worker   while (char_index < src_len) {
520*635a8641SAndroid Build Coastguard Worker     int32_t code_point;
521*635a8641SAndroid Build Coastguard Worker     CBU8_NEXT(src, char_index, src_len, code_point);
522*635a8641SAndroid Build Coastguard Worker     if (!IsValidCharacter(code_point))
523*635a8641SAndroid Build Coastguard Worker       return false;
524*635a8641SAndroid Build Coastguard Worker   }
525*635a8641SAndroid Build Coastguard Worker   return true;
526*635a8641SAndroid Build Coastguard Worker }
527*635a8641SAndroid Build Coastguard Worker 
528*635a8641SAndroid Build Coastguard Worker // Implementation note: Normally this function will be called with a hardcoded
529*635a8641SAndroid Build Coastguard Worker // constant for the lowercase_ascii parameter. Constructing a StringPiece from
530*635a8641SAndroid Build Coastguard Worker // a C constant requires running strlen, so the result will be two passes
531*635a8641SAndroid Build Coastguard Worker // through the buffers, one to file the length of lowercase_ascii, and one to
532*635a8641SAndroid Build Coastguard Worker // compare each letter.
533*635a8641SAndroid Build Coastguard Worker //
534*635a8641SAndroid Build Coastguard Worker // This function could have taken a const char* to avoid this and only do one
535*635a8641SAndroid Build Coastguard Worker // pass through the string. But the strlen is faster than the case-insensitive
536*635a8641SAndroid Build Coastguard Worker // compares and lets us early-exit in the case that the strings are different
537*635a8641SAndroid Build Coastguard Worker // lengths (will often be the case for non-matches). So whether one approach or
538*635a8641SAndroid Build Coastguard Worker // the other will be faster depends on the case.
539*635a8641SAndroid Build Coastguard Worker //
540*635a8641SAndroid Build Coastguard Worker // The hardcoded strings are typically very short so it doesn't matter, and the
541*635a8641SAndroid Build Coastguard Worker // string piece gives additional flexibility for the caller (doesn't have to be
542*635a8641SAndroid Build Coastguard Worker // null terminated) so we choose the StringPiece route.
543*635a8641SAndroid Build Coastguard Worker template<typename Str>
DoLowerCaseEqualsASCII(BasicStringPiece<Str> str,StringPiece lowercase_ascii)544*635a8641SAndroid Build Coastguard Worker static inline bool DoLowerCaseEqualsASCII(BasicStringPiece<Str> str,
545*635a8641SAndroid Build Coastguard Worker                                           StringPiece lowercase_ascii) {
546*635a8641SAndroid Build Coastguard Worker   if (str.size() != lowercase_ascii.size())
547*635a8641SAndroid Build Coastguard Worker     return false;
548*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < str.size(); i++) {
549*635a8641SAndroid Build Coastguard Worker     if (ToLowerASCII(str[i]) != lowercase_ascii[i])
550*635a8641SAndroid Build Coastguard Worker       return false;
551*635a8641SAndroid Build Coastguard Worker   }
552*635a8641SAndroid Build Coastguard Worker   return true;
553*635a8641SAndroid Build Coastguard Worker }
554*635a8641SAndroid Build Coastguard Worker 
LowerCaseEqualsASCII(StringPiece str,StringPiece lowercase_ascii)555*635a8641SAndroid Build Coastguard Worker bool LowerCaseEqualsASCII(StringPiece str, StringPiece lowercase_ascii) {
556*635a8641SAndroid Build Coastguard Worker   return DoLowerCaseEqualsASCII<std::string>(str, lowercase_ascii);
557*635a8641SAndroid Build Coastguard Worker }
558*635a8641SAndroid Build Coastguard Worker 
LowerCaseEqualsASCII(StringPiece16 str,StringPiece lowercase_ascii)559*635a8641SAndroid Build Coastguard Worker bool LowerCaseEqualsASCII(StringPiece16 str, StringPiece lowercase_ascii) {
560*635a8641SAndroid Build Coastguard Worker   return DoLowerCaseEqualsASCII<string16>(str, lowercase_ascii);
561*635a8641SAndroid Build Coastguard Worker }
562*635a8641SAndroid Build Coastguard Worker 
EqualsASCII(StringPiece16 str,StringPiece ascii)563*635a8641SAndroid Build Coastguard Worker bool EqualsASCII(StringPiece16 str, StringPiece ascii) {
564*635a8641SAndroid Build Coastguard Worker   if (str.length() != ascii.length())
565*635a8641SAndroid Build Coastguard Worker     return false;
566*635a8641SAndroid Build Coastguard Worker   return std::equal(ascii.begin(), ascii.end(), str.begin());
567*635a8641SAndroid Build Coastguard Worker }
568*635a8641SAndroid Build Coastguard Worker 
569*635a8641SAndroid Build Coastguard Worker template<typename Str>
StartsWithT(BasicStringPiece<Str> str,BasicStringPiece<Str> search_for,CompareCase case_sensitivity)570*635a8641SAndroid Build Coastguard Worker bool StartsWithT(BasicStringPiece<Str> str,
571*635a8641SAndroid Build Coastguard Worker                  BasicStringPiece<Str> search_for,
572*635a8641SAndroid Build Coastguard Worker                  CompareCase case_sensitivity) {
573*635a8641SAndroid Build Coastguard Worker   if (search_for.size() > str.size())
574*635a8641SAndroid Build Coastguard Worker     return false;
575*635a8641SAndroid Build Coastguard Worker 
576*635a8641SAndroid Build Coastguard Worker   BasicStringPiece<Str> source = str.substr(0, search_for.size());
577*635a8641SAndroid Build Coastguard Worker 
578*635a8641SAndroid Build Coastguard Worker   switch (case_sensitivity) {
579*635a8641SAndroid Build Coastguard Worker     case CompareCase::SENSITIVE:
580*635a8641SAndroid Build Coastguard Worker       return source == search_for;
581*635a8641SAndroid Build Coastguard Worker 
582*635a8641SAndroid Build Coastguard Worker     case CompareCase::INSENSITIVE_ASCII:
583*635a8641SAndroid Build Coastguard Worker       return std::equal(
584*635a8641SAndroid Build Coastguard Worker           search_for.begin(), search_for.end(),
585*635a8641SAndroid Build Coastguard Worker           source.begin(),
586*635a8641SAndroid Build Coastguard Worker           CaseInsensitiveCompareASCII<typename Str::value_type>());
587*635a8641SAndroid Build Coastguard Worker 
588*635a8641SAndroid Build Coastguard Worker     default:
589*635a8641SAndroid Build Coastguard Worker       NOTREACHED();
590*635a8641SAndroid Build Coastguard Worker       return false;
591*635a8641SAndroid Build Coastguard Worker   }
592*635a8641SAndroid Build Coastguard Worker }
593*635a8641SAndroid Build Coastguard Worker 
StartsWith(StringPiece str,StringPiece search_for,CompareCase case_sensitivity)594*635a8641SAndroid Build Coastguard Worker bool StartsWith(StringPiece str,
595*635a8641SAndroid Build Coastguard Worker                 StringPiece search_for,
596*635a8641SAndroid Build Coastguard Worker                 CompareCase case_sensitivity) {
597*635a8641SAndroid Build Coastguard Worker   return StartsWithT<std::string>(str, search_for, case_sensitivity);
598*635a8641SAndroid Build Coastguard Worker }
599*635a8641SAndroid Build Coastguard Worker 
StartsWith(StringPiece16 str,StringPiece16 search_for,CompareCase case_sensitivity)600*635a8641SAndroid Build Coastguard Worker bool StartsWith(StringPiece16 str,
601*635a8641SAndroid Build Coastguard Worker                 StringPiece16 search_for,
602*635a8641SAndroid Build Coastguard Worker                 CompareCase case_sensitivity) {
603*635a8641SAndroid Build Coastguard Worker   return StartsWithT<string16>(str, search_for, case_sensitivity);
604*635a8641SAndroid Build Coastguard Worker }
605*635a8641SAndroid Build Coastguard Worker 
606*635a8641SAndroid Build Coastguard Worker template <typename Str>
EndsWithT(BasicStringPiece<Str> str,BasicStringPiece<Str> search_for,CompareCase case_sensitivity)607*635a8641SAndroid Build Coastguard Worker bool EndsWithT(BasicStringPiece<Str> str,
608*635a8641SAndroid Build Coastguard Worker                BasicStringPiece<Str> search_for,
609*635a8641SAndroid Build Coastguard Worker                CompareCase case_sensitivity) {
610*635a8641SAndroid Build Coastguard Worker   if (search_for.size() > str.size())
611*635a8641SAndroid Build Coastguard Worker     return false;
612*635a8641SAndroid Build Coastguard Worker 
613*635a8641SAndroid Build Coastguard Worker   BasicStringPiece<Str> source = str.substr(str.size() - search_for.size(),
614*635a8641SAndroid Build Coastguard Worker                                             search_for.size());
615*635a8641SAndroid Build Coastguard Worker 
616*635a8641SAndroid Build Coastguard Worker   switch (case_sensitivity) {
617*635a8641SAndroid Build Coastguard Worker     case CompareCase::SENSITIVE:
618*635a8641SAndroid Build Coastguard Worker       return source == search_for;
619*635a8641SAndroid Build Coastguard Worker 
620*635a8641SAndroid Build Coastguard Worker     case CompareCase::INSENSITIVE_ASCII:
621*635a8641SAndroid Build Coastguard Worker       return std::equal(
622*635a8641SAndroid Build Coastguard Worker           source.begin(), source.end(),
623*635a8641SAndroid Build Coastguard Worker           search_for.begin(),
624*635a8641SAndroid Build Coastguard Worker           CaseInsensitiveCompareASCII<typename Str::value_type>());
625*635a8641SAndroid Build Coastguard Worker 
626*635a8641SAndroid Build Coastguard Worker     default:
627*635a8641SAndroid Build Coastguard Worker       NOTREACHED();
628*635a8641SAndroid Build Coastguard Worker       return false;
629*635a8641SAndroid Build Coastguard Worker   }
630*635a8641SAndroid Build Coastguard Worker }
631*635a8641SAndroid Build Coastguard Worker 
EndsWith(StringPiece str,StringPiece search_for,CompareCase case_sensitivity)632*635a8641SAndroid Build Coastguard Worker bool EndsWith(StringPiece str,
633*635a8641SAndroid Build Coastguard Worker               StringPiece search_for,
634*635a8641SAndroid Build Coastguard Worker               CompareCase case_sensitivity) {
635*635a8641SAndroid Build Coastguard Worker   return EndsWithT<std::string>(str, search_for, case_sensitivity);
636*635a8641SAndroid Build Coastguard Worker }
637*635a8641SAndroid Build Coastguard Worker 
EndsWith(StringPiece16 str,StringPiece16 search_for,CompareCase case_sensitivity)638*635a8641SAndroid Build Coastguard Worker bool EndsWith(StringPiece16 str,
639*635a8641SAndroid Build Coastguard Worker               StringPiece16 search_for,
640*635a8641SAndroid Build Coastguard Worker               CompareCase case_sensitivity) {
641*635a8641SAndroid Build Coastguard Worker   return EndsWithT<string16>(str, search_for, case_sensitivity);
642*635a8641SAndroid Build Coastguard Worker }
643*635a8641SAndroid Build Coastguard Worker 
HexDigitToInt(wchar_t c)644*635a8641SAndroid Build Coastguard Worker char HexDigitToInt(wchar_t c) {
645*635a8641SAndroid Build Coastguard Worker   DCHECK(IsHexDigit(c));
646*635a8641SAndroid Build Coastguard Worker   if (c >= '0' && c <= '9')
647*635a8641SAndroid Build Coastguard Worker     return static_cast<char>(c - '0');
648*635a8641SAndroid Build Coastguard Worker   if (c >= 'A' && c <= 'F')
649*635a8641SAndroid Build Coastguard Worker     return static_cast<char>(c - 'A' + 10);
650*635a8641SAndroid Build Coastguard Worker   if (c >= 'a' && c <= 'f')
651*635a8641SAndroid Build Coastguard Worker     return static_cast<char>(c - 'a' + 10);
652*635a8641SAndroid Build Coastguard Worker   return 0;
653*635a8641SAndroid Build Coastguard Worker }
654*635a8641SAndroid Build Coastguard Worker 
IsUnicodeWhitespace(wchar_t c)655*635a8641SAndroid Build Coastguard Worker bool IsUnicodeWhitespace(wchar_t c) {
656*635a8641SAndroid Build Coastguard Worker   // kWhitespaceWide is a NULL-terminated string
657*635a8641SAndroid Build Coastguard Worker   for (const wchar_t* cur = kWhitespaceWide; *cur; ++cur) {
658*635a8641SAndroid Build Coastguard Worker     if (*cur == c)
659*635a8641SAndroid Build Coastguard Worker       return true;
660*635a8641SAndroid Build Coastguard Worker   }
661*635a8641SAndroid Build Coastguard Worker   return false;
662*635a8641SAndroid Build Coastguard Worker }
663*635a8641SAndroid Build Coastguard Worker 
664*635a8641SAndroid Build Coastguard Worker static const char* const kByteStringsUnlocalized[] = {
665*635a8641SAndroid Build Coastguard Worker   " B",
666*635a8641SAndroid Build Coastguard Worker   " kB",
667*635a8641SAndroid Build Coastguard Worker   " MB",
668*635a8641SAndroid Build Coastguard Worker   " GB",
669*635a8641SAndroid Build Coastguard Worker   " TB",
670*635a8641SAndroid Build Coastguard Worker   " PB"
671*635a8641SAndroid Build Coastguard Worker };
672*635a8641SAndroid Build Coastguard Worker 
FormatBytesUnlocalized(int64_t bytes)673*635a8641SAndroid Build Coastguard Worker string16 FormatBytesUnlocalized(int64_t bytes) {
674*635a8641SAndroid Build Coastguard Worker   double unit_amount = static_cast<double>(bytes);
675*635a8641SAndroid Build Coastguard Worker   size_t dimension = 0;
676*635a8641SAndroid Build Coastguard Worker   const int kKilo = 1024;
677*635a8641SAndroid Build Coastguard Worker   while (unit_amount >= kKilo &&
678*635a8641SAndroid Build Coastguard Worker          dimension < arraysize(kByteStringsUnlocalized) - 1) {
679*635a8641SAndroid Build Coastguard Worker     unit_amount /= kKilo;
680*635a8641SAndroid Build Coastguard Worker     dimension++;
681*635a8641SAndroid Build Coastguard Worker   }
682*635a8641SAndroid Build Coastguard Worker 
683*635a8641SAndroid Build Coastguard Worker   char buf[64];
684*635a8641SAndroid Build Coastguard Worker   if (bytes != 0 && dimension > 0 && unit_amount < 100) {
685*635a8641SAndroid Build Coastguard Worker     base::snprintf(buf, arraysize(buf), "%.1lf%s", unit_amount,
686*635a8641SAndroid Build Coastguard Worker                    kByteStringsUnlocalized[dimension]);
687*635a8641SAndroid Build Coastguard Worker   } else {
688*635a8641SAndroid Build Coastguard Worker     base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount,
689*635a8641SAndroid Build Coastguard Worker                    kByteStringsUnlocalized[dimension]);
690*635a8641SAndroid Build Coastguard Worker   }
691*635a8641SAndroid Build Coastguard Worker 
692*635a8641SAndroid Build Coastguard Worker   return ASCIIToUTF16(buf);
693*635a8641SAndroid Build Coastguard Worker }
694*635a8641SAndroid Build Coastguard Worker 
695*635a8641SAndroid Build Coastguard Worker // A Matcher for DoReplaceMatchesAfterOffset() that matches substrings.
696*635a8641SAndroid Build Coastguard Worker template <class StringType>
697*635a8641SAndroid Build Coastguard Worker struct SubstringMatcher {
698*635a8641SAndroid Build Coastguard Worker   BasicStringPiece<StringType> find_this;
699*635a8641SAndroid Build Coastguard Worker 
Findbase::SubstringMatcher700*635a8641SAndroid Build Coastguard Worker   size_t Find(const StringType& input, size_t pos) {
701*635a8641SAndroid Build Coastguard Worker     return input.find(find_this.data(), pos, find_this.length());
702*635a8641SAndroid Build Coastguard Worker   }
MatchSizebase::SubstringMatcher703*635a8641SAndroid Build Coastguard Worker   size_t MatchSize() { return find_this.length(); }
704*635a8641SAndroid Build Coastguard Worker };
705*635a8641SAndroid Build Coastguard Worker 
706*635a8641SAndroid Build Coastguard Worker // A Matcher for DoReplaceMatchesAfterOffset() that matches single characters.
707*635a8641SAndroid Build Coastguard Worker template <class StringType>
708*635a8641SAndroid Build Coastguard Worker struct CharacterMatcher {
709*635a8641SAndroid Build Coastguard Worker   BasicStringPiece<StringType> find_any_of_these;
710*635a8641SAndroid Build Coastguard Worker 
Findbase::CharacterMatcher711*635a8641SAndroid Build Coastguard Worker   size_t Find(const StringType& input, size_t pos) {
712*635a8641SAndroid Build Coastguard Worker     return input.find_first_of(find_any_of_these.data(), pos,
713*635a8641SAndroid Build Coastguard Worker                                find_any_of_these.length());
714*635a8641SAndroid Build Coastguard Worker   }
MatchSizebase::CharacterMatcher715*635a8641SAndroid Build Coastguard Worker   constexpr size_t MatchSize() { return 1; }
716*635a8641SAndroid Build Coastguard Worker };
717*635a8641SAndroid Build Coastguard Worker 
718*635a8641SAndroid Build Coastguard Worker enum class ReplaceType { REPLACE_ALL, REPLACE_FIRST };
719*635a8641SAndroid Build Coastguard Worker 
720*635a8641SAndroid Build Coastguard Worker // Runs in O(n) time in the length of |str|, and transforms the string without
721*635a8641SAndroid Build Coastguard Worker // reallocating when possible. Returns |true| if any matches were found.
722*635a8641SAndroid Build Coastguard Worker //
723*635a8641SAndroid Build Coastguard Worker // This is parameterized on a |Matcher| traits type, so that it can be the
724*635a8641SAndroid Build Coastguard Worker // implementation for both ReplaceChars() and ReplaceSubstringsAfterOffset().
725*635a8641SAndroid Build Coastguard Worker template <class StringType, class Matcher>
DoReplaceMatchesAfterOffset(StringType * str,size_t initial_offset,Matcher matcher,BasicStringPiece<StringType> replace_with,ReplaceType replace_type)726*635a8641SAndroid Build Coastguard Worker bool DoReplaceMatchesAfterOffset(StringType* str,
727*635a8641SAndroid Build Coastguard Worker                                  size_t initial_offset,
728*635a8641SAndroid Build Coastguard Worker                                  Matcher matcher,
729*635a8641SAndroid Build Coastguard Worker                                  BasicStringPiece<StringType> replace_with,
730*635a8641SAndroid Build Coastguard Worker                                  ReplaceType replace_type) {
731*635a8641SAndroid Build Coastguard Worker   using CharTraits = typename StringType::traits_type;
732*635a8641SAndroid Build Coastguard Worker 
733*635a8641SAndroid Build Coastguard Worker   const size_t find_length = matcher.MatchSize();
734*635a8641SAndroid Build Coastguard Worker   if (!find_length)
735*635a8641SAndroid Build Coastguard Worker     return false;
736*635a8641SAndroid Build Coastguard Worker 
737*635a8641SAndroid Build Coastguard Worker   // If the find string doesn't appear, there's nothing to do.
738*635a8641SAndroid Build Coastguard Worker   size_t first_match = matcher.Find(*str, initial_offset);
739*635a8641SAndroid Build Coastguard Worker   if (first_match == StringType::npos)
740*635a8641SAndroid Build Coastguard Worker     return false;
741*635a8641SAndroid Build Coastguard Worker 
742*635a8641SAndroid Build Coastguard Worker   // If we're only replacing one instance, there's no need to do anything
743*635a8641SAndroid Build Coastguard Worker   // complicated.
744*635a8641SAndroid Build Coastguard Worker   const size_t replace_length = replace_with.length();
745*635a8641SAndroid Build Coastguard Worker   if (replace_type == ReplaceType::REPLACE_FIRST) {
746*635a8641SAndroid Build Coastguard Worker     str->replace(first_match, find_length, replace_with.data(), replace_length);
747*635a8641SAndroid Build Coastguard Worker     return true;
748*635a8641SAndroid Build Coastguard Worker   }
749*635a8641SAndroid Build Coastguard Worker 
750*635a8641SAndroid Build Coastguard Worker   // If the find and replace strings are the same length, we can simply use
751*635a8641SAndroid Build Coastguard Worker   // replace() on each instance, and finish the entire operation in O(n) time.
752*635a8641SAndroid Build Coastguard Worker   if (find_length == replace_length) {
753*635a8641SAndroid Build Coastguard Worker     auto* buffer = &((*str)[0]);
754*635a8641SAndroid Build Coastguard Worker     for (size_t offset = first_match; offset != StringType::npos;
755*635a8641SAndroid Build Coastguard Worker          offset = matcher.Find(*str, offset + replace_length)) {
756*635a8641SAndroid Build Coastguard Worker       CharTraits::copy(buffer + offset, replace_with.data(), replace_length);
757*635a8641SAndroid Build Coastguard Worker     }
758*635a8641SAndroid Build Coastguard Worker     return true;
759*635a8641SAndroid Build Coastguard Worker   }
760*635a8641SAndroid Build Coastguard Worker 
761*635a8641SAndroid Build Coastguard Worker   // Since the find and replace strings aren't the same length, a loop like the
762*635a8641SAndroid Build Coastguard Worker   // one above would be O(n^2) in the worst case, as replace() will shift the
763*635a8641SAndroid Build Coastguard Worker   // entire remaining string each time. We need to be more clever to keep things
764*635a8641SAndroid Build Coastguard Worker   // O(n).
765*635a8641SAndroid Build Coastguard Worker   //
766*635a8641SAndroid Build Coastguard Worker   // When the string is being shortened, it's possible to just shift the matches
767*635a8641SAndroid Build Coastguard Worker   // down in one pass while finding, and truncate the length at the end of the
768*635a8641SAndroid Build Coastguard Worker   // search.
769*635a8641SAndroid Build Coastguard Worker   //
770*635a8641SAndroid Build Coastguard Worker   // If the string is being lengthened, more work is required. The strategy used
771*635a8641SAndroid Build Coastguard Worker   // here is to make two find() passes through the string. The first pass counts
772*635a8641SAndroid Build Coastguard Worker   // the number of matches to determine the new size. The second pass will
773*635a8641SAndroid Build Coastguard Worker   // either construct the new string into a new buffer (if the existing buffer
774*635a8641SAndroid Build Coastguard Worker   // lacked capacity), or else -- if there is room -- create a region of scratch
775*635a8641SAndroid Build Coastguard Worker   // space after |first_match| by shifting the tail of the string to a higher
776*635a8641SAndroid Build Coastguard Worker   // index, and doing in-place moves from the tail to lower indices thereafter.
777*635a8641SAndroid Build Coastguard Worker   size_t str_length = str->length();
778*635a8641SAndroid Build Coastguard Worker   size_t expansion = 0;
779*635a8641SAndroid Build Coastguard Worker   if (replace_length > find_length) {
780*635a8641SAndroid Build Coastguard Worker     // This operation lengthens the string; determine the new length by counting
781*635a8641SAndroid Build Coastguard Worker     // matches.
782*635a8641SAndroid Build Coastguard Worker     const size_t expansion_per_match = (replace_length - find_length);
783*635a8641SAndroid Build Coastguard Worker     size_t num_matches = 0;
784*635a8641SAndroid Build Coastguard Worker     for (size_t match = first_match; match != StringType::npos;
785*635a8641SAndroid Build Coastguard Worker          match = matcher.Find(*str, match + find_length)) {
786*635a8641SAndroid Build Coastguard Worker       expansion += expansion_per_match;
787*635a8641SAndroid Build Coastguard Worker       ++num_matches;
788*635a8641SAndroid Build Coastguard Worker     }
789*635a8641SAndroid Build Coastguard Worker     const size_t final_length = str_length + expansion;
790*635a8641SAndroid Build Coastguard Worker 
791*635a8641SAndroid Build Coastguard Worker     if (str->capacity() < final_length) {
792*635a8641SAndroid Build Coastguard Worker       // If we'd have to allocate a new buffer to grow the string, build the
793*635a8641SAndroid Build Coastguard Worker       // result directly into the new allocation via append().
794*635a8641SAndroid Build Coastguard Worker       StringType src(str->get_allocator());
795*635a8641SAndroid Build Coastguard Worker       str->swap(src);
796*635a8641SAndroid Build Coastguard Worker       str->reserve(final_length);
797*635a8641SAndroid Build Coastguard Worker 
798*635a8641SAndroid Build Coastguard Worker       size_t pos = 0;
799*635a8641SAndroid Build Coastguard Worker       for (size_t match = first_match;; match = matcher.Find(src, pos)) {
800*635a8641SAndroid Build Coastguard Worker         str->append(src, pos, match - pos);
801*635a8641SAndroid Build Coastguard Worker         str->append(replace_with.data(), replace_length);
802*635a8641SAndroid Build Coastguard Worker         pos = match + find_length;
803*635a8641SAndroid Build Coastguard Worker 
804*635a8641SAndroid Build Coastguard Worker         // A mid-loop test/break enables skipping the final Find() call; the
805*635a8641SAndroid Build Coastguard Worker         // number of matches is known, so don't search past the last one.
806*635a8641SAndroid Build Coastguard Worker         if (!--num_matches)
807*635a8641SAndroid Build Coastguard Worker           break;
808*635a8641SAndroid Build Coastguard Worker       }
809*635a8641SAndroid Build Coastguard Worker 
810*635a8641SAndroid Build Coastguard Worker       // Handle substring after the final match.
811*635a8641SAndroid Build Coastguard Worker       str->append(src, pos, str_length - pos);
812*635a8641SAndroid Build Coastguard Worker       return true;
813*635a8641SAndroid Build Coastguard Worker     }
814*635a8641SAndroid Build Coastguard Worker 
815*635a8641SAndroid Build Coastguard Worker     // Prepare for the copy/move loop below -- expand the string to its final
816*635a8641SAndroid Build Coastguard Worker     // size by shifting the data after the first match to the end of the resized
817*635a8641SAndroid Build Coastguard Worker     // string.
818*635a8641SAndroid Build Coastguard Worker     size_t shift_src = first_match + find_length;
819*635a8641SAndroid Build Coastguard Worker     size_t shift_dst = shift_src + expansion;
820*635a8641SAndroid Build Coastguard Worker 
821*635a8641SAndroid Build Coastguard Worker     // Big |expansion| factors (relative to |str_length|) require padding up to
822*635a8641SAndroid Build Coastguard Worker     // |shift_dst|.
823*635a8641SAndroid Build Coastguard Worker     if (shift_dst > str_length)
824*635a8641SAndroid Build Coastguard Worker       str->resize(shift_dst);
825*635a8641SAndroid Build Coastguard Worker 
826*635a8641SAndroid Build Coastguard Worker     str->replace(shift_dst, str_length - shift_src, *str, shift_src,
827*635a8641SAndroid Build Coastguard Worker                  str_length - shift_src);
828*635a8641SAndroid Build Coastguard Worker     str_length = final_length;
829*635a8641SAndroid Build Coastguard Worker   }
830*635a8641SAndroid Build Coastguard Worker 
831*635a8641SAndroid Build Coastguard Worker   // We can alternate replacement and move operations. This won't overwrite the
832*635a8641SAndroid Build Coastguard Worker   // unsearched region of the string so long as |write_offset| <= |read_offset|;
833*635a8641SAndroid Build Coastguard Worker   // that condition is always satisfied because:
834*635a8641SAndroid Build Coastguard Worker   //
835*635a8641SAndroid Build Coastguard Worker   //   (a) If the string is being shortened, |expansion| is zero and
836*635a8641SAndroid Build Coastguard Worker   //       |write_offset| grows slower than |read_offset|.
837*635a8641SAndroid Build Coastguard Worker   //
838*635a8641SAndroid Build Coastguard Worker   //   (b) If the string is being lengthened, |write_offset| grows faster than
839*635a8641SAndroid Build Coastguard Worker   //       |read_offset|, but |expansion| is big enough so that |write_offset|
840*635a8641SAndroid Build Coastguard Worker   //       will only catch up to |read_offset| at the point of the last match.
841*635a8641SAndroid Build Coastguard Worker   auto* buffer = &((*str)[0]);
842*635a8641SAndroid Build Coastguard Worker   size_t write_offset = first_match;
843*635a8641SAndroid Build Coastguard Worker   size_t read_offset = first_match + expansion;
844*635a8641SAndroid Build Coastguard Worker   do {
845*635a8641SAndroid Build Coastguard Worker     if (replace_length) {
846*635a8641SAndroid Build Coastguard Worker       CharTraits::copy(buffer + write_offset, replace_with.data(),
847*635a8641SAndroid Build Coastguard Worker                        replace_length);
848*635a8641SAndroid Build Coastguard Worker       write_offset += replace_length;
849*635a8641SAndroid Build Coastguard Worker     }
850*635a8641SAndroid Build Coastguard Worker     read_offset += find_length;
851*635a8641SAndroid Build Coastguard Worker 
852*635a8641SAndroid Build Coastguard Worker     // min() clamps StringType::npos (the largest unsigned value) to str_length.
853*635a8641SAndroid Build Coastguard Worker     size_t match = std::min(matcher.Find(*str, read_offset), str_length);
854*635a8641SAndroid Build Coastguard Worker 
855*635a8641SAndroid Build Coastguard Worker     size_t length = match - read_offset;
856*635a8641SAndroid Build Coastguard Worker     if (length) {
857*635a8641SAndroid Build Coastguard Worker       CharTraits::move(buffer + write_offset, buffer + read_offset, length);
858*635a8641SAndroid Build Coastguard Worker       write_offset += length;
859*635a8641SAndroid Build Coastguard Worker       read_offset += length;
860*635a8641SAndroid Build Coastguard Worker     }
861*635a8641SAndroid Build Coastguard Worker   } while (read_offset < str_length);
862*635a8641SAndroid Build Coastguard Worker 
863*635a8641SAndroid Build Coastguard Worker   // If we're shortening the string, truncate it now.
864*635a8641SAndroid Build Coastguard Worker   str->resize(write_offset);
865*635a8641SAndroid Build Coastguard Worker   return true;
866*635a8641SAndroid Build Coastguard Worker }
867*635a8641SAndroid Build Coastguard Worker 
868*635a8641SAndroid Build Coastguard Worker template <class StringType>
ReplaceCharsT(const StringType & input,BasicStringPiece<StringType> find_any_of_these,BasicStringPiece<StringType> replace_with,StringType * output)869*635a8641SAndroid Build Coastguard Worker bool ReplaceCharsT(const StringType& input,
870*635a8641SAndroid Build Coastguard Worker                    BasicStringPiece<StringType> find_any_of_these,
871*635a8641SAndroid Build Coastguard Worker                    BasicStringPiece<StringType> replace_with,
872*635a8641SAndroid Build Coastguard Worker                    StringType* output) {
873*635a8641SAndroid Build Coastguard Worker   // Commonly, this is called with output and input being the same string; in
874*635a8641SAndroid Build Coastguard Worker   // that case, this assignment is inexpensive.
875*635a8641SAndroid Build Coastguard Worker   *output = input;
876*635a8641SAndroid Build Coastguard Worker 
877*635a8641SAndroid Build Coastguard Worker   return DoReplaceMatchesAfterOffset(
878*635a8641SAndroid Build Coastguard Worker       output, 0, CharacterMatcher<StringType>{find_any_of_these}, replace_with,
879*635a8641SAndroid Build Coastguard Worker       ReplaceType::REPLACE_ALL);
880*635a8641SAndroid Build Coastguard Worker }
881*635a8641SAndroid Build Coastguard Worker 
ReplaceFirstSubstringAfterOffset(string16 * str,size_t start_offset,StringPiece16 find_this,StringPiece16 replace_with)882*635a8641SAndroid Build Coastguard Worker void ReplaceFirstSubstringAfterOffset(string16* str,
883*635a8641SAndroid Build Coastguard Worker                                       size_t start_offset,
884*635a8641SAndroid Build Coastguard Worker                                       StringPiece16 find_this,
885*635a8641SAndroid Build Coastguard Worker                                       StringPiece16 replace_with) {
886*635a8641SAndroid Build Coastguard Worker   DoReplaceMatchesAfterOffset(str, start_offset,
887*635a8641SAndroid Build Coastguard Worker                               SubstringMatcher<string16>{find_this},
888*635a8641SAndroid Build Coastguard Worker                               replace_with, ReplaceType::REPLACE_FIRST);
889*635a8641SAndroid Build Coastguard Worker }
890*635a8641SAndroid Build Coastguard Worker 
ReplaceFirstSubstringAfterOffset(std::string * str,size_t start_offset,StringPiece find_this,StringPiece replace_with)891*635a8641SAndroid Build Coastguard Worker void ReplaceFirstSubstringAfterOffset(std::string* str,
892*635a8641SAndroid Build Coastguard Worker                                       size_t start_offset,
893*635a8641SAndroid Build Coastguard Worker                                       StringPiece find_this,
894*635a8641SAndroid Build Coastguard Worker                                       StringPiece replace_with) {
895*635a8641SAndroid Build Coastguard Worker   DoReplaceMatchesAfterOffset(str, start_offset,
896*635a8641SAndroid Build Coastguard Worker                               SubstringMatcher<std::string>{find_this},
897*635a8641SAndroid Build Coastguard Worker                               replace_with, ReplaceType::REPLACE_FIRST);
898*635a8641SAndroid Build Coastguard Worker }
899*635a8641SAndroid Build Coastguard Worker 
ReplaceSubstringsAfterOffset(string16 * str,size_t start_offset,StringPiece16 find_this,StringPiece16 replace_with)900*635a8641SAndroid Build Coastguard Worker void ReplaceSubstringsAfterOffset(string16* str,
901*635a8641SAndroid Build Coastguard Worker                                   size_t start_offset,
902*635a8641SAndroid Build Coastguard Worker                                   StringPiece16 find_this,
903*635a8641SAndroid Build Coastguard Worker                                   StringPiece16 replace_with) {
904*635a8641SAndroid Build Coastguard Worker   DoReplaceMatchesAfterOffset(str, start_offset,
905*635a8641SAndroid Build Coastguard Worker                               SubstringMatcher<string16>{find_this},
906*635a8641SAndroid Build Coastguard Worker                               replace_with, ReplaceType::REPLACE_ALL);
907*635a8641SAndroid Build Coastguard Worker }
908*635a8641SAndroid Build Coastguard Worker 
ReplaceSubstringsAfterOffset(std::string * str,size_t start_offset,StringPiece find_this,StringPiece replace_with)909*635a8641SAndroid Build Coastguard Worker void ReplaceSubstringsAfterOffset(std::string* str,
910*635a8641SAndroid Build Coastguard Worker                                   size_t start_offset,
911*635a8641SAndroid Build Coastguard Worker                                   StringPiece find_this,
912*635a8641SAndroid Build Coastguard Worker                                   StringPiece replace_with) {
913*635a8641SAndroid Build Coastguard Worker   DoReplaceMatchesAfterOffset(str, start_offset,
914*635a8641SAndroid Build Coastguard Worker                               SubstringMatcher<std::string>{find_this},
915*635a8641SAndroid Build Coastguard Worker                               replace_with, ReplaceType::REPLACE_ALL);
916*635a8641SAndroid Build Coastguard Worker }
917*635a8641SAndroid Build Coastguard Worker 
918*635a8641SAndroid Build Coastguard Worker template <class string_type>
WriteIntoT(string_type * str,size_t length_with_null)919*635a8641SAndroid Build Coastguard Worker inline typename string_type::value_type* WriteIntoT(string_type* str,
920*635a8641SAndroid Build Coastguard Worker                                                     size_t length_with_null) {
921*635a8641SAndroid Build Coastguard Worker   DCHECK_GT(length_with_null, 1u);
922*635a8641SAndroid Build Coastguard Worker   str->reserve(length_with_null);
923*635a8641SAndroid Build Coastguard Worker   str->resize(length_with_null - 1);
924*635a8641SAndroid Build Coastguard Worker   return &((*str)[0]);
925*635a8641SAndroid Build Coastguard Worker }
926*635a8641SAndroid Build Coastguard Worker 
WriteInto(std::string * str,size_t length_with_null)927*635a8641SAndroid Build Coastguard Worker char* WriteInto(std::string* str, size_t length_with_null) {
928*635a8641SAndroid Build Coastguard Worker   return WriteIntoT(str, length_with_null);
929*635a8641SAndroid Build Coastguard Worker }
930*635a8641SAndroid Build Coastguard Worker 
WriteInto(string16 * str,size_t length_with_null)931*635a8641SAndroid Build Coastguard Worker char16* WriteInto(string16* str, size_t length_with_null) {
932*635a8641SAndroid Build Coastguard Worker   return WriteIntoT(str, length_with_null);
933*635a8641SAndroid Build Coastguard Worker }
934*635a8641SAndroid Build Coastguard Worker 
935*635a8641SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(__clang__)
936*635a8641SAndroid Build Coastguard Worker // Work around VC++ code-gen bug. https://crbug.com/804884
937*635a8641SAndroid Build Coastguard Worker #pragma optimize("", off)
938*635a8641SAndroid Build Coastguard Worker #endif
939*635a8641SAndroid Build Coastguard Worker 
940*635a8641SAndroid Build Coastguard Worker // Generic version for all JoinString overloads. |list_type| must be a sequence
941*635a8641SAndroid Build Coastguard Worker // (std::vector or std::initializer_list) of strings/StringPieces (std::string,
942*635a8641SAndroid Build Coastguard Worker // string16, StringPiece or StringPiece16). |string_type| is either std::string
943*635a8641SAndroid Build Coastguard Worker // or string16.
944*635a8641SAndroid Build Coastguard Worker template <typename list_type, typename string_type>
JoinStringT(const list_type & parts,BasicStringPiece<string_type> sep)945*635a8641SAndroid Build Coastguard Worker static string_type JoinStringT(const list_type& parts,
946*635a8641SAndroid Build Coastguard Worker                                BasicStringPiece<string_type> sep) {
947*635a8641SAndroid Build Coastguard Worker   if (parts.size() == 0)
948*635a8641SAndroid Build Coastguard Worker     return string_type();
949*635a8641SAndroid Build Coastguard Worker 
950*635a8641SAndroid Build Coastguard Worker   // Pre-allocate the eventual size of the string. Start with the size of all of
951*635a8641SAndroid Build Coastguard Worker   // the separators (note that this *assumes* parts.size() > 0).
952*635a8641SAndroid Build Coastguard Worker   size_t total_size = (parts.size() - 1) * sep.size();
953*635a8641SAndroid Build Coastguard Worker   for (const auto& part : parts)
954*635a8641SAndroid Build Coastguard Worker     total_size += part.size();
955*635a8641SAndroid Build Coastguard Worker   string_type result;
956*635a8641SAndroid Build Coastguard Worker   result.reserve(total_size);
957*635a8641SAndroid Build Coastguard Worker 
958*635a8641SAndroid Build Coastguard Worker   auto iter = parts.begin();
959*635a8641SAndroid Build Coastguard Worker   DCHECK(iter != parts.end());
960*635a8641SAndroid Build Coastguard Worker   AppendToString(&result, *iter);
961*635a8641SAndroid Build Coastguard Worker   ++iter;
962*635a8641SAndroid Build Coastguard Worker 
963*635a8641SAndroid Build Coastguard Worker   for (; iter != parts.end(); ++iter) {
964*635a8641SAndroid Build Coastguard Worker     sep.AppendToString(&result);
965*635a8641SAndroid Build Coastguard Worker     // Using the overloaded AppendToString allows this template function to work
966*635a8641SAndroid Build Coastguard Worker     // on both strings and StringPieces without creating an intermediate
967*635a8641SAndroid Build Coastguard Worker     // StringPiece object.
968*635a8641SAndroid Build Coastguard Worker     AppendToString(&result, *iter);
969*635a8641SAndroid Build Coastguard Worker   }
970*635a8641SAndroid Build Coastguard Worker 
971*635a8641SAndroid Build Coastguard Worker   // Sanity-check that we pre-allocated correctly.
972*635a8641SAndroid Build Coastguard Worker   DCHECK_EQ(total_size, result.size());
973*635a8641SAndroid Build Coastguard Worker 
974*635a8641SAndroid Build Coastguard Worker   return result;
975*635a8641SAndroid Build Coastguard Worker }
976*635a8641SAndroid Build Coastguard Worker 
JoinString(const std::vector<std::string> & parts,StringPiece separator)977*635a8641SAndroid Build Coastguard Worker std::string JoinString(const std::vector<std::string>& parts,
978*635a8641SAndroid Build Coastguard Worker                        StringPiece separator) {
979*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
980*635a8641SAndroid Build Coastguard Worker }
981*635a8641SAndroid Build Coastguard Worker 
JoinString(const std::vector<string16> & parts,StringPiece16 separator)982*635a8641SAndroid Build Coastguard Worker string16 JoinString(const std::vector<string16>& parts,
983*635a8641SAndroid Build Coastguard Worker                     StringPiece16 separator) {
984*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
985*635a8641SAndroid Build Coastguard Worker }
986*635a8641SAndroid Build Coastguard Worker 
987*635a8641SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(__clang__)
988*635a8641SAndroid Build Coastguard Worker // Work around VC++ code-gen bug. https://crbug.com/804884
989*635a8641SAndroid Build Coastguard Worker #pragma optimize("", on)
990*635a8641SAndroid Build Coastguard Worker #endif
991*635a8641SAndroid Build Coastguard Worker 
JoinString(const std::vector<StringPiece> & parts,StringPiece separator)992*635a8641SAndroid Build Coastguard Worker std::string JoinString(const std::vector<StringPiece>& parts,
993*635a8641SAndroid Build Coastguard Worker                        StringPiece separator) {
994*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
995*635a8641SAndroid Build Coastguard Worker }
996*635a8641SAndroid Build Coastguard Worker 
JoinString(const std::vector<StringPiece16> & parts,StringPiece16 separator)997*635a8641SAndroid Build Coastguard Worker string16 JoinString(const std::vector<StringPiece16>& parts,
998*635a8641SAndroid Build Coastguard Worker                     StringPiece16 separator) {
999*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
1000*635a8641SAndroid Build Coastguard Worker }
1001*635a8641SAndroid Build Coastguard Worker 
JoinString(std::initializer_list<StringPiece> parts,StringPiece separator)1002*635a8641SAndroid Build Coastguard Worker std::string JoinString(std::initializer_list<StringPiece> parts,
1003*635a8641SAndroid Build Coastguard Worker                        StringPiece separator) {
1004*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
1005*635a8641SAndroid Build Coastguard Worker }
1006*635a8641SAndroid Build Coastguard Worker 
JoinString(std::initializer_list<StringPiece16> parts,StringPiece16 separator)1007*635a8641SAndroid Build Coastguard Worker string16 JoinString(std::initializer_list<StringPiece16> parts,
1008*635a8641SAndroid Build Coastguard Worker                     StringPiece16 separator) {
1009*635a8641SAndroid Build Coastguard Worker   return JoinStringT(parts, separator);
1010*635a8641SAndroid Build Coastguard Worker }
1011*635a8641SAndroid Build Coastguard Worker 
1012*635a8641SAndroid Build Coastguard Worker template<class FormatStringType, class OutStringType>
DoReplaceStringPlaceholders(const FormatStringType & format_string,const std::vector<OutStringType> & subst,std::vector<size_t> * offsets)1013*635a8641SAndroid Build Coastguard Worker OutStringType DoReplaceStringPlaceholders(
1014*635a8641SAndroid Build Coastguard Worker     const FormatStringType& format_string,
1015*635a8641SAndroid Build Coastguard Worker     const std::vector<OutStringType>& subst,
1016*635a8641SAndroid Build Coastguard Worker     std::vector<size_t>* offsets) {
1017*635a8641SAndroid Build Coastguard Worker   size_t substitutions = subst.size();
1018*635a8641SAndroid Build Coastguard Worker   DCHECK_LT(substitutions, 10U);
1019*635a8641SAndroid Build Coastguard Worker 
1020*635a8641SAndroid Build Coastguard Worker   size_t sub_length = 0;
1021*635a8641SAndroid Build Coastguard Worker   for (const auto& cur : subst)
1022*635a8641SAndroid Build Coastguard Worker     sub_length += cur.length();
1023*635a8641SAndroid Build Coastguard Worker 
1024*635a8641SAndroid Build Coastguard Worker   OutStringType formatted;
1025*635a8641SAndroid Build Coastguard Worker   formatted.reserve(format_string.length() + sub_length);
1026*635a8641SAndroid Build Coastguard Worker 
1027*635a8641SAndroid Build Coastguard Worker   std::vector<ReplacementOffset> r_offsets;
1028*635a8641SAndroid Build Coastguard Worker   for (auto i = format_string.begin(); i != format_string.end(); ++i) {
1029*635a8641SAndroid Build Coastguard Worker     if ('$' == *i) {
1030*635a8641SAndroid Build Coastguard Worker       if (i + 1 != format_string.end()) {
1031*635a8641SAndroid Build Coastguard Worker         ++i;
1032*635a8641SAndroid Build Coastguard Worker         if ('$' == *i) {
1033*635a8641SAndroid Build Coastguard Worker           while (i != format_string.end() && '$' == *i) {
1034*635a8641SAndroid Build Coastguard Worker             formatted.push_back('$');
1035*635a8641SAndroid Build Coastguard Worker             ++i;
1036*635a8641SAndroid Build Coastguard Worker           }
1037*635a8641SAndroid Build Coastguard Worker           --i;
1038*635a8641SAndroid Build Coastguard Worker         } else {
1039*635a8641SAndroid Build Coastguard Worker           if (*i < '1' || *i > '9') {
1040*635a8641SAndroid Build Coastguard Worker             DLOG(ERROR) << "Invalid placeholder: $" << *i;
1041*635a8641SAndroid Build Coastguard Worker             continue;
1042*635a8641SAndroid Build Coastguard Worker           }
1043*635a8641SAndroid Build Coastguard Worker           uintptr_t index = *i - '1';
1044*635a8641SAndroid Build Coastguard Worker           if (offsets) {
1045*635a8641SAndroid Build Coastguard Worker             ReplacementOffset r_offset(index,
1046*635a8641SAndroid Build Coastguard Worker                                        static_cast<int>(formatted.size()));
1047*635a8641SAndroid Build Coastguard Worker             r_offsets.insert(
1048*635a8641SAndroid Build Coastguard Worker                 std::upper_bound(r_offsets.begin(), r_offsets.end(), r_offset,
1049*635a8641SAndroid Build Coastguard Worker                                  &CompareParameter),
1050*635a8641SAndroid Build Coastguard Worker                 r_offset);
1051*635a8641SAndroid Build Coastguard Worker           }
1052*635a8641SAndroid Build Coastguard Worker           if (index < substitutions)
1053*635a8641SAndroid Build Coastguard Worker             formatted.append(subst.at(index));
1054*635a8641SAndroid Build Coastguard Worker         }
1055*635a8641SAndroid Build Coastguard Worker       }
1056*635a8641SAndroid Build Coastguard Worker     } else {
1057*635a8641SAndroid Build Coastguard Worker       formatted.push_back(*i);
1058*635a8641SAndroid Build Coastguard Worker     }
1059*635a8641SAndroid Build Coastguard Worker   }
1060*635a8641SAndroid Build Coastguard Worker   if (offsets) {
1061*635a8641SAndroid Build Coastguard Worker     for (const auto& cur : r_offsets)
1062*635a8641SAndroid Build Coastguard Worker       offsets->push_back(cur.offset);
1063*635a8641SAndroid Build Coastguard Worker   }
1064*635a8641SAndroid Build Coastguard Worker   return formatted;
1065*635a8641SAndroid Build Coastguard Worker }
1066*635a8641SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(const string16 & format_string,const std::vector<string16> & subst,std::vector<size_t> * offsets)1067*635a8641SAndroid Build Coastguard Worker string16 ReplaceStringPlaceholders(const string16& format_string,
1068*635a8641SAndroid Build Coastguard Worker                                    const std::vector<string16>& subst,
1069*635a8641SAndroid Build Coastguard Worker                                    std::vector<size_t>* offsets) {
1070*635a8641SAndroid Build Coastguard Worker   return DoReplaceStringPlaceholders(format_string, subst, offsets);
1071*635a8641SAndroid Build Coastguard Worker }
1072*635a8641SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(StringPiece format_string,const std::vector<std::string> & subst,std::vector<size_t> * offsets)1073*635a8641SAndroid Build Coastguard Worker std::string ReplaceStringPlaceholders(StringPiece format_string,
1074*635a8641SAndroid Build Coastguard Worker                                       const std::vector<std::string>& subst,
1075*635a8641SAndroid Build Coastguard Worker                                       std::vector<size_t>* offsets) {
1076*635a8641SAndroid Build Coastguard Worker   return DoReplaceStringPlaceholders(format_string, subst, offsets);
1077*635a8641SAndroid Build Coastguard Worker }
1078*635a8641SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(const string16 & format_string,const string16 & a,size_t * offset)1079*635a8641SAndroid Build Coastguard Worker string16 ReplaceStringPlaceholders(const string16& format_string,
1080*635a8641SAndroid Build Coastguard Worker                                    const string16& a,
1081*635a8641SAndroid Build Coastguard Worker                                    size_t* offset) {
1082*635a8641SAndroid Build Coastguard Worker   std::vector<size_t> offsets;
1083*635a8641SAndroid Build Coastguard Worker   std::vector<string16> subst;
1084*635a8641SAndroid Build Coastguard Worker   subst.push_back(a);
1085*635a8641SAndroid Build Coastguard Worker   string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets);
1086*635a8641SAndroid Build Coastguard Worker 
1087*635a8641SAndroid Build Coastguard Worker   DCHECK_EQ(1U, offsets.size());
1088*635a8641SAndroid Build Coastguard Worker   if (offset)
1089*635a8641SAndroid Build Coastguard Worker     *offset = offsets[0];
1090*635a8641SAndroid Build Coastguard Worker   return result;
1091*635a8641SAndroid Build Coastguard Worker }
1092*635a8641SAndroid Build Coastguard Worker 
1093*635a8641SAndroid Build Coastguard Worker // The following code is compatible with the OpenBSD lcpy interface.  See:
1094*635a8641SAndroid Build Coastguard Worker //   http://www.gratisoft.us/todd/papers/strlcpy.html
1095*635a8641SAndroid Build Coastguard Worker //   ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
1096*635a8641SAndroid Build Coastguard Worker 
1097*635a8641SAndroid Build Coastguard Worker namespace {
1098*635a8641SAndroid Build Coastguard Worker 
1099*635a8641SAndroid Build Coastguard Worker template <typename CHAR>
lcpyT(CHAR * dst,const CHAR * src,size_t dst_size)1100*635a8641SAndroid Build Coastguard Worker size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) {
1101*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < dst_size; ++i) {
1102*635a8641SAndroid Build Coastguard Worker     if ((dst[i] = src[i]) == 0)  // We hit and copied the terminating NULL.
1103*635a8641SAndroid Build Coastguard Worker       return i;
1104*635a8641SAndroid Build Coastguard Worker   }
1105*635a8641SAndroid Build Coastguard Worker 
1106*635a8641SAndroid Build Coastguard Worker   // We were left off at dst_size.  We over copied 1 byte.  Null terminate.
1107*635a8641SAndroid Build Coastguard Worker   if (dst_size != 0)
1108*635a8641SAndroid Build Coastguard Worker     dst[dst_size - 1] = 0;
1109*635a8641SAndroid Build Coastguard Worker 
1110*635a8641SAndroid Build Coastguard Worker   // Count the rest of the |src|, and return it's length in characters.
1111*635a8641SAndroid Build Coastguard Worker   while (src[dst_size]) ++dst_size;
1112*635a8641SAndroid Build Coastguard Worker   return dst_size;
1113*635a8641SAndroid Build Coastguard Worker }
1114*635a8641SAndroid Build Coastguard Worker 
1115*635a8641SAndroid Build Coastguard Worker }  // namespace
1116*635a8641SAndroid Build Coastguard Worker 
strlcpy(char * dst,const char * src,size_t dst_size)1117*635a8641SAndroid Build Coastguard Worker size_t strlcpy(char* dst, const char* src, size_t dst_size) {
1118*635a8641SAndroid Build Coastguard Worker   return lcpyT<char>(dst, src, dst_size);
1119*635a8641SAndroid Build Coastguard Worker }
wcslcpy(wchar_t * dst,const wchar_t * src,size_t dst_size)1120*635a8641SAndroid Build Coastguard Worker size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) {
1121*635a8641SAndroid Build Coastguard Worker   return lcpyT<wchar_t>(dst, src, dst_size);
1122*635a8641SAndroid Build Coastguard Worker }
1123*635a8641SAndroid Build Coastguard Worker 
1124*635a8641SAndroid Build Coastguard Worker }  // namespace base
1125