xref: /aosp_15_r20/external/cronet/base/strings/string_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <errno.h>
8*6777b538SAndroid Build Coastguard Worker #include <math.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdarg.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
12*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
13*6777b538SAndroid Build Coastguard Worker #include <string.h>
14*6777b538SAndroid Build Coastguard Worker #include <time.h>
15*6777b538SAndroid Build Coastguard Worker #include <wchar.h>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include <limits>
18*6777b538SAndroid Build Coastguard Worker #include <optional>
19*6777b538SAndroid Build Coastguard Worker #include <string_view>
20*6777b538SAndroid Build Coastguard Worker #include <type_traits>
21*6777b538SAndroid Build Coastguard Worker #include <vector>
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util_impl_helpers.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util_internal.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversion_utils.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/third_party/icu/icu_utf.h"
31*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker namespace base {
34*6777b538SAndroid Build Coastguard Worker 
IsWprintfFormatPortable(const wchar_t * format)35*6777b538SAndroid Build Coastguard Worker bool IsWprintfFormatPortable(const wchar_t* format) {
36*6777b538SAndroid Build Coastguard Worker   for (const wchar_t* position = format; *position != '\0'; ++position) {
37*6777b538SAndroid Build Coastguard Worker     if (*position == '%') {
38*6777b538SAndroid Build Coastguard Worker       bool in_specification = true;
39*6777b538SAndroid Build Coastguard Worker       bool modifier_l = false;
40*6777b538SAndroid Build Coastguard Worker       while (in_specification) {
41*6777b538SAndroid Build Coastguard Worker         // Eat up characters until reaching a known specifier.
42*6777b538SAndroid Build Coastguard Worker         if (*++position == '\0') {
43*6777b538SAndroid Build Coastguard Worker           // The format string ended in the middle of a specification.  Call
44*6777b538SAndroid Build Coastguard Worker           // it portable because no unportable specifications were found.  The
45*6777b538SAndroid Build Coastguard Worker           // string is equally broken on all platforms.
46*6777b538SAndroid Build Coastguard Worker           return true;
47*6777b538SAndroid Build Coastguard Worker         }
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker         if (*position == 'l') {
50*6777b538SAndroid Build Coastguard Worker           // 'l' is the only thing that can save the 's' and 'c' specifiers.
51*6777b538SAndroid Build Coastguard Worker           modifier_l = true;
52*6777b538SAndroid Build Coastguard Worker         } else if (((*position == 's' || *position == 'c') && !modifier_l) ||
53*6777b538SAndroid Build Coastguard Worker                    *position == 'S' || *position == 'C' || *position == 'F' ||
54*6777b538SAndroid Build Coastguard Worker                    *position == 'D' || *position == 'O' || *position == 'U') {
55*6777b538SAndroid Build Coastguard Worker           // Not portable.
56*6777b538SAndroid Build Coastguard Worker           return false;
57*6777b538SAndroid Build Coastguard Worker         }
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker         if (wcschr(L"diouxXeEfgGaAcspn%", *position)) {
60*6777b538SAndroid Build Coastguard Worker           // Portable, keep scanning the rest of the format string.
61*6777b538SAndroid Build Coastguard Worker           in_specification = false;
62*6777b538SAndroid Build Coastguard Worker         }
63*6777b538SAndroid Build Coastguard Worker       }
64*6777b538SAndroid Build Coastguard Worker     }
65*6777b538SAndroid Build Coastguard Worker   }
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker   return true;
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker 
ToLowerASCII(StringPiece str)70*6777b538SAndroid Build Coastguard Worker std::string ToLowerASCII(StringPiece str) {
71*6777b538SAndroid Build Coastguard Worker   return internal::ToLowerASCIIImpl(str);
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker 
ToLowerASCII(StringPiece16 str)74*6777b538SAndroid Build Coastguard Worker std::u16string ToLowerASCII(StringPiece16 str) {
75*6777b538SAndroid Build Coastguard Worker   return internal::ToLowerASCIIImpl(str);
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker 
ToUpperASCII(StringPiece str)78*6777b538SAndroid Build Coastguard Worker std::string ToUpperASCII(StringPiece str) {
79*6777b538SAndroid Build Coastguard Worker   return internal::ToUpperASCIIImpl(str);
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
ToUpperASCII(StringPiece16 str)82*6777b538SAndroid Build Coastguard Worker std::u16string ToUpperASCII(StringPiece16 str) {
83*6777b538SAndroid Build Coastguard Worker   return internal::ToUpperASCIIImpl(str);
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
EmptyString()86*6777b538SAndroid Build Coastguard Worker const std::string& EmptyString() {
87*6777b538SAndroid Build Coastguard Worker   static const base::NoDestructor<std::string> s;
88*6777b538SAndroid Build Coastguard Worker   return *s;
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker 
EmptyString16()91*6777b538SAndroid Build Coastguard Worker const std::u16string& EmptyString16() {
92*6777b538SAndroid Build Coastguard Worker   static const base::NoDestructor<std::u16string> s16;
93*6777b538SAndroid Build Coastguard Worker   return *s16;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
ReplaceChars(StringPiece16 input,StringPiece16 replace_chars,StringPiece16 replace_with,std::u16string * output)96*6777b538SAndroid Build Coastguard Worker bool ReplaceChars(StringPiece16 input,
97*6777b538SAndroid Build Coastguard Worker                   StringPiece16 replace_chars,
98*6777b538SAndroid Build Coastguard Worker                   StringPiece16 replace_with,
99*6777b538SAndroid Build Coastguard Worker                   std::u16string* output) {
100*6777b538SAndroid Build Coastguard Worker   return internal::ReplaceCharsT(input, replace_chars, replace_with, output);
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
ReplaceChars(StringPiece input,StringPiece replace_chars,StringPiece replace_with,std::string * output)103*6777b538SAndroid Build Coastguard Worker bool ReplaceChars(StringPiece input,
104*6777b538SAndroid Build Coastguard Worker                   StringPiece replace_chars,
105*6777b538SAndroid Build Coastguard Worker                   StringPiece replace_with,
106*6777b538SAndroid Build Coastguard Worker                   std::string* output) {
107*6777b538SAndroid Build Coastguard Worker   return internal::ReplaceCharsT(input, replace_chars, replace_with, output);
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker 
RemoveChars(StringPiece16 input,StringPiece16 remove_chars,std::u16string * output)110*6777b538SAndroid Build Coastguard Worker bool RemoveChars(StringPiece16 input,
111*6777b538SAndroid Build Coastguard Worker                  StringPiece16 remove_chars,
112*6777b538SAndroid Build Coastguard Worker                  std::u16string* output) {
113*6777b538SAndroid Build Coastguard Worker   return internal::ReplaceCharsT(input, remove_chars, StringPiece16(), output);
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker 
RemoveChars(StringPiece input,StringPiece remove_chars,std::string * output)116*6777b538SAndroid Build Coastguard Worker bool RemoveChars(StringPiece input,
117*6777b538SAndroid Build Coastguard Worker                  StringPiece remove_chars,
118*6777b538SAndroid Build Coastguard Worker                  std::string* output) {
119*6777b538SAndroid Build Coastguard Worker   return internal::ReplaceCharsT(input, remove_chars, StringPiece(), output);
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
TrimString(StringPiece16 input,StringPiece16 trim_chars,std::u16string * output)122*6777b538SAndroid Build Coastguard Worker bool TrimString(StringPiece16 input,
123*6777b538SAndroid Build Coastguard Worker                 StringPiece16 trim_chars,
124*6777b538SAndroid Build Coastguard Worker                 std::u16string* output) {
125*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringT(input, trim_chars, TRIM_ALL, output) !=
126*6777b538SAndroid Build Coastguard Worker          TRIM_NONE;
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker 
TrimString(StringPiece input,StringPiece trim_chars,std::string * output)129*6777b538SAndroid Build Coastguard Worker bool TrimString(StringPiece input,
130*6777b538SAndroid Build Coastguard Worker                 StringPiece trim_chars,
131*6777b538SAndroid Build Coastguard Worker                 std::string* output) {
132*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringT(input, trim_chars, TRIM_ALL, output) !=
133*6777b538SAndroid Build Coastguard Worker          TRIM_NONE;
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker 
TrimString(StringPiece16 input,StringPiece16 trim_chars,TrimPositions positions)136*6777b538SAndroid Build Coastguard Worker StringPiece16 TrimString(StringPiece16 input,
137*6777b538SAndroid Build Coastguard Worker                          StringPiece16 trim_chars,
138*6777b538SAndroid Build Coastguard Worker                          TrimPositions positions) {
139*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringPieceT(input, trim_chars, positions);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker 
TrimString(StringPiece input,StringPiece trim_chars,TrimPositions positions)142*6777b538SAndroid Build Coastguard Worker StringPiece TrimString(StringPiece input,
143*6777b538SAndroid Build Coastguard Worker                        StringPiece trim_chars,
144*6777b538SAndroid Build Coastguard Worker                        TrimPositions positions) {
145*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringPieceT(input, trim_chars, positions);
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker 
TruncateUTF8ToByteSize(const std::string & input,const size_t byte_size,std::string * output)148*6777b538SAndroid Build Coastguard Worker void TruncateUTF8ToByteSize(const std::string& input,
149*6777b538SAndroid Build Coastguard Worker                             const size_t byte_size,
150*6777b538SAndroid Build Coastguard Worker                             std::string* output) {
151*6777b538SAndroid Build Coastguard Worker   DCHECK(output);
152*6777b538SAndroid Build Coastguard Worker   if (byte_size > input.length()) {
153*6777b538SAndroid Build Coastguard Worker     *output = input;
154*6777b538SAndroid Build Coastguard Worker     return;
155*6777b538SAndroid Build Coastguard Worker   }
156*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(byte_size,
157*6777b538SAndroid Build Coastguard Worker             static_cast<uint32_t>(std::numeric_limits<int32_t>::max()));
158*6777b538SAndroid Build Coastguard Worker   // Note: This cast is necessary because CBU8_NEXT uses int32_ts.
159*6777b538SAndroid Build Coastguard Worker   int32_t truncation_length = static_cast<int32_t>(byte_size);
160*6777b538SAndroid Build Coastguard Worker   int32_t char_index = truncation_length - 1;
161*6777b538SAndroid Build Coastguard Worker   const char* data = input.data();
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // Using CBU8, we will move backwards from the truncation point
164*6777b538SAndroid Build Coastguard Worker   // to the beginning of the string looking for a valid UTF8
165*6777b538SAndroid Build Coastguard Worker   // character.  Once a full UTF8 character is found, we will
166*6777b538SAndroid Build Coastguard Worker   // truncate the string to the end of that character.
167*6777b538SAndroid Build Coastguard Worker   while (char_index >= 0) {
168*6777b538SAndroid Build Coastguard Worker     int32_t prev = char_index;
169*6777b538SAndroid Build Coastguard Worker     base_icu::UChar32 code_point = 0;
170*6777b538SAndroid Build Coastguard Worker     CBU8_NEXT(reinterpret_cast<const uint8_t*>(data), char_index,
171*6777b538SAndroid Build Coastguard Worker               truncation_length, code_point);
172*6777b538SAndroid Build Coastguard Worker     if (!IsValidCharacter(code_point)) {
173*6777b538SAndroid Build Coastguard Worker       char_index = prev - 1;
174*6777b538SAndroid Build Coastguard Worker     } else {
175*6777b538SAndroid Build Coastguard Worker       break;
176*6777b538SAndroid Build Coastguard Worker     }
177*6777b538SAndroid Build Coastguard Worker   }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker   if (char_index >= 0 )
180*6777b538SAndroid Build Coastguard Worker     *output = input.substr(0, static_cast<size_t>(char_index));
181*6777b538SAndroid Build Coastguard Worker   else
182*6777b538SAndroid Build Coastguard Worker     output->clear();
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker 
TrimWhitespace(StringPiece16 input,TrimPositions positions,std::u16string * output)185*6777b538SAndroid Build Coastguard Worker TrimPositions TrimWhitespace(StringPiece16 input,
186*6777b538SAndroid Build Coastguard Worker                              TrimPositions positions,
187*6777b538SAndroid Build Coastguard Worker                              std::u16string* output) {
188*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringT(input, StringPiece16(kWhitespaceUTF16),
189*6777b538SAndroid Build Coastguard Worker                                positions, output);
190*6777b538SAndroid Build Coastguard Worker }
191*6777b538SAndroid Build Coastguard Worker 
TrimWhitespace(StringPiece16 input,TrimPositions positions)192*6777b538SAndroid Build Coastguard Worker StringPiece16 TrimWhitespace(StringPiece16 input,
193*6777b538SAndroid Build Coastguard Worker                              TrimPositions positions) {
194*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16),
195*6777b538SAndroid Build Coastguard Worker                                     positions);
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker 
TrimWhitespaceASCII(StringPiece input,TrimPositions positions,std::string * output)198*6777b538SAndroid Build Coastguard Worker TrimPositions TrimWhitespaceASCII(StringPiece input,
199*6777b538SAndroid Build Coastguard Worker                                   TrimPositions positions,
200*6777b538SAndroid Build Coastguard Worker                                   std::string* output) {
201*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringT(input, StringPiece(kWhitespaceASCII), positions,
202*6777b538SAndroid Build Coastguard Worker                                output);
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker 
TrimWhitespaceASCII(StringPiece input,TrimPositions positions)205*6777b538SAndroid Build Coastguard Worker StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions) {
206*6777b538SAndroid Build Coastguard Worker   return internal::TrimStringPieceT(input, StringPiece(kWhitespaceASCII),
207*6777b538SAndroid Build Coastguard Worker                                     positions);
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker 
CollapseWhitespace(StringPiece16 text,bool trim_sequences_with_line_breaks)210*6777b538SAndroid Build Coastguard Worker std::u16string CollapseWhitespace(StringPiece16 text,
211*6777b538SAndroid Build Coastguard Worker                                   bool trim_sequences_with_line_breaks) {
212*6777b538SAndroid Build Coastguard Worker   return internal::CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
CollapseWhitespaceASCII(StringPiece text,bool trim_sequences_with_line_breaks)215*6777b538SAndroid Build Coastguard Worker std::string CollapseWhitespaceASCII(StringPiece text,
216*6777b538SAndroid Build Coastguard Worker                                     bool trim_sequences_with_line_breaks) {
217*6777b538SAndroid Build Coastguard Worker   return internal::CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
ContainsOnlyChars(StringPiece input,StringPiece characters)220*6777b538SAndroid Build Coastguard Worker bool ContainsOnlyChars(StringPiece input, StringPiece characters) {
221*6777b538SAndroid Build Coastguard Worker   return input.find_first_not_of(characters) == StringPiece::npos;
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker 
ContainsOnlyChars(StringPiece16 input,StringPiece16 characters)224*6777b538SAndroid Build Coastguard Worker bool ContainsOnlyChars(StringPiece16 input, StringPiece16 characters) {
225*6777b538SAndroid Build Coastguard Worker   return input.find_first_not_of(characters) == StringPiece16::npos;
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker 
IsStringASCII(StringPiece str)229*6777b538SAndroid Build Coastguard Worker bool IsStringASCII(StringPiece str) {
230*6777b538SAndroid Build Coastguard Worker   return internal::DoIsStringASCII(str.data(), str.length());
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker 
IsStringASCII(StringPiece16 str)233*6777b538SAndroid Build Coastguard Worker bool IsStringASCII(StringPiece16 str) {
234*6777b538SAndroid Build Coastguard Worker   return internal::DoIsStringASCII(str.data(), str.length());
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_32_BIT)
IsStringASCII(std::wstring_view str)238*6777b538SAndroid Build Coastguard Worker bool IsStringASCII(std::wstring_view str) {
239*6777b538SAndroid Build Coastguard Worker   return internal::DoIsStringASCII(str.data(), str.length());
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker #endif
242*6777b538SAndroid Build Coastguard Worker 
IsStringUTF8(StringPiece str)243*6777b538SAndroid Build Coastguard Worker bool IsStringUTF8(StringPiece str) {
244*6777b538SAndroid Build Coastguard Worker   return internal::DoIsStringUTF8<IsValidCharacter>(str);
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker 
IsStringUTF8AllowingNoncharacters(StringPiece str)247*6777b538SAndroid Build Coastguard Worker bool IsStringUTF8AllowingNoncharacters(StringPiece str) {
248*6777b538SAndroid Build Coastguard Worker   return internal::DoIsStringUTF8<IsValidCodepoint>(str);
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker 
EqualsASCII(StringPiece16 str,StringPiece ascii)251*6777b538SAndroid Build Coastguard Worker bool EqualsASCII(StringPiece16 str, StringPiece ascii) {
252*6777b538SAndroid Build Coastguard Worker   return ranges::equal(ascii, str);
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker 
StartsWith(StringPiece str,StringPiece search_for,CompareCase case_sensitivity)255*6777b538SAndroid Build Coastguard Worker bool StartsWith(StringPiece str,
256*6777b538SAndroid Build Coastguard Worker                 StringPiece search_for,
257*6777b538SAndroid Build Coastguard Worker                 CompareCase case_sensitivity) {
258*6777b538SAndroid Build Coastguard Worker   return internal::StartsWithT(str, search_for, case_sensitivity);
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker 
StartsWith(StringPiece16 str,StringPiece16 search_for,CompareCase case_sensitivity)261*6777b538SAndroid Build Coastguard Worker bool StartsWith(StringPiece16 str,
262*6777b538SAndroid Build Coastguard Worker                 StringPiece16 search_for,
263*6777b538SAndroid Build Coastguard Worker                 CompareCase case_sensitivity) {
264*6777b538SAndroid Build Coastguard Worker   return internal::StartsWithT(str, search_for, case_sensitivity);
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker 
EndsWith(StringPiece str,StringPiece search_for,CompareCase case_sensitivity)267*6777b538SAndroid Build Coastguard Worker bool EndsWith(StringPiece str,
268*6777b538SAndroid Build Coastguard Worker               StringPiece search_for,
269*6777b538SAndroid Build Coastguard Worker               CompareCase case_sensitivity) {
270*6777b538SAndroid Build Coastguard Worker   return internal::EndsWithT(str, search_for, case_sensitivity);
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker 
EndsWith(StringPiece16 str,StringPiece16 search_for,CompareCase case_sensitivity)273*6777b538SAndroid Build Coastguard Worker bool EndsWith(StringPiece16 str,
274*6777b538SAndroid Build Coastguard Worker               StringPiece16 search_for,
275*6777b538SAndroid Build Coastguard Worker               CompareCase case_sensitivity) {
276*6777b538SAndroid Build Coastguard Worker   return internal::EndsWithT(str, search_for, case_sensitivity);
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker 
HexDigitToInt(char c)279*6777b538SAndroid Build Coastguard Worker char HexDigitToInt(char c) {
280*6777b538SAndroid Build Coastguard Worker   DCHECK(IsHexDigit(c));
281*6777b538SAndroid Build Coastguard Worker   if (c >= '0' && c <= '9')
282*6777b538SAndroid Build Coastguard Worker     return static_cast<char>(c - '0');
283*6777b538SAndroid Build Coastguard Worker   return (c >= 'A' && c <= 'F') ? static_cast<char>(c - 'A' + 10)
284*6777b538SAndroid Build Coastguard Worker                                 : static_cast<char>(c - 'a' + 10);
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker static const char* const kByteStringsUnlocalized[] = {
288*6777b538SAndroid Build Coastguard Worker   " B",
289*6777b538SAndroid Build Coastguard Worker   " kB",
290*6777b538SAndroid Build Coastguard Worker   " MB",
291*6777b538SAndroid Build Coastguard Worker   " GB",
292*6777b538SAndroid Build Coastguard Worker   " TB",
293*6777b538SAndroid Build Coastguard Worker   " PB"
294*6777b538SAndroid Build Coastguard Worker };
295*6777b538SAndroid Build Coastguard Worker 
FormatBytesUnlocalized(int64_t bytes)296*6777b538SAndroid Build Coastguard Worker std::u16string FormatBytesUnlocalized(int64_t bytes) {
297*6777b538SAndroid Build Coastguard Worker   double unit_amount = static_cast<double>(bytes);
298*6777b538SAndroid Build Coastguard Worker   size_t dimension = 0;
299*6777b538SAndroid Build Coastguard Worker   const int kKilo = 1024;
300*6777b538SAndroid Build Coastguard Worker   while (unit_amount >= kKilo &&
301*6777b538SAndroid Build Coastguard Worker          dimension < std::size(kByteStringsUnlocalized) - 1) {
302*6777b538SAndroid Build Coastguard Worker     unit_amount /= kKilo;
303*6777b538SAndroid Build Coastguard Worker     dimension++;
304*6777b538SAndroid Build Coastguard Worker   }
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   char buf[64];
307*6777b538SAndroid Build Coastguard Worker   if (bytes != 0 && dimension > 0 && unit_amount < 100) {
308*6777b538SAndroid Build Coastguard Worker     base::snprintf(buf, std::size(buf), "%.1lf%s", unit_amount,
309*6777b538SAndroid Build Coastguard Worker                    kByteStringsUnlocalized[dimension]);
310*6777b538SAndroid Build Coastguard Worker   } else {
311*6777b538SAndroid Build Coastguard Worker     base::snprintf(buf, std::size(buf), "%.0lf%s", unit_amount,
312*6777b538SAndroid Build Coastguard Worker                    kByteStringsUnlocalized[dimension]);
313*6777b538SAndroid Build Coastguard Worker   }
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker   return ASCIIToUTF16(buf);
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker 
ReplaceFirstSubstringAfterOffset(std::u16string * str,size_t start_offset,StringPiece16 find_this,StringPiece16 replace_with)318*6777b538SAndroid Build Coastguard Worker void ReplaceFirstSubstringAfterOffset(std::u16string* str,
319*6777b538SAndroid Build Coastguard Worker                                       size_t start_offset,
320*6777b538SAndroid Build Coastguard Worker                                       StringPiece16 find_this,
321*6777b538SAndroid Build Coastguard Worker                                       StringPiece16 replace_with) {
322*6777b538SAndroid Build Coastguard Worker   internal::DoReplaceMatchesAfterOffset(
323*6777b538SAndroid Build Coastguard Worker       str, start_offset, internal::MakeSubstringMatcher(find_this),
324*6777b538SAndroid Build Coastguard Worker       replace_with, internal::ReplaceType::REPLACE_FIRST);
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker 
ReplaceFirstSubstringAfterOffset(std::string * str,size_t start_offset,StringPiece find_this,StringPiece replace_with)327*6777b538SAndroid Build Coastguard Worker void ReplaceFirstSubstringAfterOffset(std::string* str,
328*6777b538SAndroid Build Coastguard Worker                                       size_t start_offset,
329*6777b538SAndroid Build Coastguard Worker                                       StringPiece find_this,
330*6777b538SAndroid Build Coastguard Worker                                       StringPiece replace_with) {
331*6777b538SAndroid Build Coastguard Worker   internal::DoReplaceMatchesAfterOffset(
332*6777b538SAndroid Build Coastguard Worker       str, start_offset, internal::MakeSubstringMatcher(find_this),
333*6777b538SAndroid Build Coastguard Worker       replace_with, internal::ReplaceType::REPLACE_FIRST);
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker 
ReplaceSubstringsAfterOffset(std::u16string * str,size_t start_offset,StringPiece16 find_this,StringPiece16 replace_with)336*6777b538SAndroid Build Coastguard Worker void ReplaceSubstringsAfterOffset(std::u16string* str,
337*6777b538SAndroid Build Coastguard Worker                                   size_t start_offset,
338*6777b538SAndroid Build Coastguard Worker                                   StringPiece16 find_this,
339*6777b538SAndroid Build Coastguard Worker                                   StringPiece16 replace_with) {
340*6777b538SAndroid Build Coastguard Worker   internal::DoReplaceMatchesAfterOffset(
341*6777b538SAndroid Build Coastguard Worker       str, start_offset, internal::MakeSubstringMatcher(find_this),
342*6777b538SAndroid Build Coastguard Worker       replace_with, internal::ReplaceType::REPLACE_ALL);
343*6777b538SAndroid Build Coastguard Worker }
344*6777b538SAndroid Build Coastguard Worker 
ReplaceSubstringsAfterOffset(std::string * str,size_t start_offset,StringPiece find_this,StringPiece replace_with)345*6777b538SAndroid Build Coastguard Worker void ReplaceSubstringsAfterOffset(std::string* str,
346*6777b538SAndroid Build Coastguard Worker                                   size_t start_offset,
347*6777b538SAndroid Build Coastguard Worker                                   StringPiece find_this,
348*6777b538SAndroid Build Coastguard Worker                                   StringPiece replace_with) {
349*6777b538SAndroid Build Coastguard Worker   internal::DoReplaceMatchesAfterOffset(
350*6777b538SAndroid Build Coastguard Worker       str, start_offset, internal::MakeSubstringMatcher(find_this),
351*6777b538SAndroid Build Coastguard Worker       replace_with, internal::ReplaceType::REPLACE_ALL);
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker 
WriteInto(std::string * str,size_t length_with_null)354*6777b538SAndroid Build Coastguard Worker char* WriteInto(std::string* str, size_t length_with_null) {
355*6777b538SAndroid Build Coastguard Worker   return internal::WriteIntoT(str, length_with_null);
356*6777b538SAndroid Build Coastguard Worker }
357*6777b538SAndroid Build Coastguard Worker 
WriteInto(std::u16string * str,size_t length_with_null)358*6777b538SAndroid Build Coastguard Worker char16_t* WriteInto(std::u16string* str, size_t length_with_null) {
359*6777b538SAndroid Build Coastguard Worker   return internal::WriteIntoT(str, length_with_null);
360*6777b538SAndroid Build Coastguard Worker }
361*6777b538SAndroid Build Coastguard Worker 
JoinString(span<const std::string> parts,StringPiece separator)362*6777b538SAndroid Build Coastguard Worker std::string JoinString(span<const std::string> parts, StringPiece separator) {
363*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker 
JoinString(span<const std::u16string> parts,StringPiece16 separator)366*6777b538SAndroid Build Coastguard Worker std::u16string JoinString(span<const std::u16string> parts,
367*6777b538SAndroid Build Coastguard Worker                           StringPiece16 separator) {
368*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker 
JoinString(span<const StringPiece> parts,StringPiece separator)371*6777b538SAndroid Build Coastguard Worker std::string JoinString(span<const StringPiece> parts, StringPiece separator) {
372*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
373*6777b538SAndroid Build Coastguard Worker }
374*6777b538SAndroid Build Coastguard Worker 
JoinString(span<const StringPiece16> parts,StringPiece16 separator)375*6777b538SAndroid Build Coastguard Worker std::u16string JoinString(span<const StringPiece16> parts,
376*6777b538SAndroid Build Coastguard Worker                           StringPiece16 separator) {
377*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker 
JoinString(std::initializer_list<StringPiece> parts,StringPiece separator)380*6777b538SAndroid Build Coastguard Worker std::string JoinString(std::initializer_list<StringPiece> parts,
381*6777b538SAndroid Build Coastguard Worker                        StringPiece separator) {
382*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
383*6777b538SAndroid Build Coastguard Worker }
384*6777b538SAndroid Build Coastguard Worker 
JoinString(std::initializer_list<StringPiece16> parts,StringPiece16 separator)385*6777b538SAndroid Build Coastguard Worker std::u16string JoinString(std::initializer_list<StringPiece16> parts,
386*6777b538SAndroid Build Coastguard Worker                           StringPiece16 separator) {
387*6777b538SAndroid Build Coastguard Worker   return internal::JoinStringT(parts, separator);
388*6777b538SAndroid Build Coastguard Worker }
389*6777b538SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(StringPiece16 format_string,const std::vector<std::u16string> & subst,std::vector<size_t> * offsets)390*6777b538SAndroid Build Coastguard Worker std::u16string ReplaceStringPlaceholders(
391*6777b538SAndroid Build Coastguard Worker     StringPiece16 format_string,
392*6777b538SAndroid Build Coastguard Worker     const std::vector<std::u16string>& subst,
393*6777b538SAndroid Build Coastguard Worker     std::vector<size_t>* offsets) {
394*6777b538SAndroid Build Coastguard Worker   std::optional<std::u16string> replacement =
395*6777b538SAndroid Build Coastguard Worker       internal::DoReplaceStringPlaceholders(
396*6777b538SAndroid Build Coastguard Worker           format_string, subst,
397*6777b538SAndroid Build Coastguard Worker           /*placeholder_prefix*/ u'$',
398*6777b538SAndroid Build Coastguard Worker           /*should_escape_multiple_placeholder_prefixes*/ true,
399*6777b538SAndroid Build Coastguard Worker           /*is_strict_mode*/ false, offsets);
400*6777b538SAndroid Build Coastguard Worker 
401*6777b538SAndroid Build Coastguard Worker   DCHECK(replacement);
402*6777b538SAndroid Build Coastguard Worker   return replacement.value();
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(StringPiece format_string,const std::vector<std::string> & subst,std::vector<size_t> * offsets)405*6777b538SAndroid Build Coastguard Worker std::string ReplaceStringPlaceholders(StringPiece format_string,
406*6777b538SAndroid Build Coastguard Worker                                       const std::vector<std::string>& subst,
407*6777b538SAndroid Build Coastguard Worker                                       std::vector<size_t>* offsets) {
408*6777b538SAndroid Build Coastguard Worker   std::optional<std::string> replacement =
409*6777b538SAndroid Build Coastguard Worker       internal::DoReplaceStringPlaceholders(
410*6777b538SAndroid Build Coastguard Worker           format_string, subst,
411*6777b538SAndroid Build Coastguard Worker           /*placeholder_prefix*/ '$',
412*6777b538SAndroid Build Coastguard Worker           /*should_escape_multiple_placeholder_prefixes*/ true,
413*6777b538SAndroid Build Coastguard Worker           /*is_strict_mode*/ false, offsets);
414*6777b538SAndroid Build Coastguard Worker 
415*6777b538SAndroid Build Coastguard Worker   DCHECK(replacement);
416*6777b538SAndroid Build Coastguard Worker   return replacement.value();
417*6777b538SAndroid Build Coastguard Worker }
418*6777b538SAndroid Build Coastguard Worker 
ReplaceStringPlaceholders(const std::u16string & format_string,const std::u16string & a,size_t * offset)419*6777b538SAndroid Build Coastguard Worker std::u16string ReplaceStringPlaceholders(const std::u16string& format_string,
420*6777b538SAndroid Build Coastguard Worker                                          const std::u16string& a,
421*6777b538SAndroid Build Coastguard Worker                                          size_t* offset) {
422*6777b538SAndroid Build Coastguard Worker   std::vector<size_t> offsets;
423*6777b538SAndroid Build Coastguard Worker   std::u16string result =
424*6777b538SAndroid Build Coastguard Worker       ReplaceStringPlaceholders(format_string, {a}, &offsets);
425*6777b538SAndroid Build Coastguard Worker 
426*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(1U, offsets.size());
427*6777b538SAndroid Build Coastguard Worker   if (offset)
428*6777b538SAndroid Build Coastguard Worker     *offset = offsets[0];
429*6777b538SAndroid Build Coastguard Worker   return result;
430*6777b538SAndroid Build Coastguard Worker }
431*6777b538SAndroid Build Coastguard Worker 
strlcpy(char * dst,const char * src,size_t dst_size)432*6777b538SAndroid Build Coastguard Worker size_t strlcpy(char* dst, const char* src, size_t dst_size) {
433*6777b538SAndroid Build Coastguard Worker   return internal::lcpyT(dst, src, dst_size);
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker 
u16cstrlcpy(char16_t * dst,const char16_t * src,size_t dst_size)436*6777b538SAndroid Build Coastguard Worker size_t u16cstrlcpy(char16_t* dst, const char16_t* src, size_t dst_size) {
437*6777b538SAndroid Build Coastguard Worker   return internal::lcpyT(dst, src, dst_size);
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker 
wcslcpy(wchar_t * dst,const wchar_t * src,size_t dst_size)440*6777b538SAndroid Build Coastguard Worker size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) {
441*6777b538SAndroid Build Coastguard Worker   return internal::lcpyT(dst, src, dst_size);
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker 
444*6777b538SAndroid Build Coastguard Worker }  // namespace base
445