xref: /aosp_15_r20/external/cronet/base/strings/utf_string_conversions.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 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/utf_string_conversions.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <limits.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <concepts>
11*6777b538SAndroid Build Coastguard Worker #include <ostream>
12*6777b538SAndroid Build Coastguard Worker #include <string_view>
13*6777b538SAndroid Build Coastguard Worker #include <type_traits>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_ostream_operators.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversion_utils.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/third_party/icu/icu_utf.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace base {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker constexpr base_icu::UChar32 kErrorCodePoint = 0xFFFD;
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker // Size coefficient ----------------------------------------------------------
29*6777b538SAndroid Build Coastguard Worker // The maximum number of codeunits in the destination encoding corresponding to
30*6777b538SAndroid Build Coastguard Worker // one codeunit in the source encoding.
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker template <typename SrcChar, typename DestChar>
33*6777b538SAndroid Build Coastguard Worker struct SizeCoefficient {
34*6777b538SAndroid Build Coastguard Worker   static_assert(sizeof(SrcChar) < sizeof(DestChar),
35*6777b538SAndroid Build Coastguard Worker                 "Default case: from a smaller encoding to the bigger one");
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   // ASCII symbols are encoded by one codeunit in all encodings.
38*6777b538SAndroid Build Coastguard Worker   static constexpr int value = 1;
39*6777b538SAndroid Build Coastguard Worker };
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker template <>
42*6777b538SAndroid Build Coastguard Worker struct SizeCoefficient<char16_t, char> {
43*6777b538SAndroid Build Coastguard Worker   // One UTF-16 codeunit corresponds to at most 3 codeunits in UTF-8.
44*6777b538SAndroid Build Coastguard Worker   static constexpr int value = 3;
45*6777b538SAndroid Build Coastguard Worker };
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_32_BIT)
48*6777b538SAndroid Build Coastguard Worker template <>
49*6777b538SAndroid Build Coastguard Worker struct SizeCoefficient<wchar_t, char> {
50*6777b538SAndroid Build Coastguard Worker   // UTF-8 uses at most 4 codeunits per character.
51*6777b538SAndroid Build Coastguard Worker   static constexpr int value = 4;
52*6777b538SAndroid Build Coastguard Worker };
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker template <>
55*6777b538SAndroid Build Coastguard Worker struct SizeCoefficient<wchar_t, char16_t> {
56*6777b538SAndroid Build Coastguard Worker   // UTF-16 uses at most 2 codeunits per character.
57*6777b538SAndroid Build Coastguard Worker   static constexpr int value = 2;
58*6777b538SAndroid Build Coastguard Worker };
59*6777b538SAndroid Build Coastguard Worker #endif  // defined(WCHAR_T_IS_32_BIT)
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker template <typename SrcChar, typename DestChar>
62*6777b538SAndroid Build Coastguard Worker constexpr int size_coefficient_v =
63*6777b538SAndroid Build Coastguard Worker     SizeCoefficient<std::decay_t<SrcChar>, std::decay_t<DestChar>>::value;
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker // UnicodeAppendUnsafe --------------------------------------------------------
66*6777b538SAndroid Build Coastguard Worker // Function overloads that write code_point to the output string. Output string
67*6777b538SAndroid Build Coastguard Worker // has to have enough space for the codepoint.
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker // Convenience typedef that checks whether the passed in type is integral (i.e.
70*6777b538SAndroid Build Coastguard Worker // bool, char, int or their extended versions) and is of the correct size.
71*6777b538SAndroid Build Coastguard Worker template <typename Char, size_t N>
72*6777b538SAndroid Build Coastguard Worker concept BitsAre = std::integral<Char> && CHAR_BIT * sizeof(Char) == N;
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker template <typename Char>
75*6777b538SAndroid Build Coastguard Worker   requires(BitsAre<Char, 8>)
UnicodeAppendUnsafe(Char * out,size_t * size,base_icu::UChar32 code_point)76*6777b538SAndroid Build Coastguard Worker void UnicodeAppendUnsafe(Char* out,
77*6777b538SAndroid Build Coastguard Worker                          size_t* size,
78*6777b538SAndroid Build Coastguard Worker                          base_icu::UChar32 code_point) {
79*6777b538SAndroid Build Coastguard Worker   CBU8_APPEND_UNSAFE(reinterpret_cast<uint8_t*>(out), *size, code_point);
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker template <typename Char>
83*6777b538SAndroid Build Coastguard Worker   requires(BitsAre<Char, 16>)
UnicodeAppendUnsafe(Char * out,size_t * size,base_icu::UChar32 code_point)84*6777b538SAndroid Build Coastguard Worker void UnicodeAppendUnsafe(Char* out,
85*6777b538SAndroid Build Coastguard Worker                          size_t* size,
86*6777b538SAndroid Build Coastguard Worker                          base_icu::UChar32 code_point) {
87*6777b538SAndroid Build Coastguard Worker   CBU16_APPEND_UNSAFE(out, *size, code_point);
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker template <typename Char>
91*6777b538SAndroid Build Coastguard Worker   requires(BitsAre<Char, 32>)
UnicodeAppendUnsafe(Char * out,size_t * size,base_icu::UChar32 code_point)92*6777b538SAndroid Build Coastguard Worker void UnicodeAppendUnsafe(Char* out,
93*6777b538SAndroid Build Coastguard Worker                          size_t* size,
94*6777b538SAndroid Build Coastguard Worker                          base_icu::UChar32 code_point) {
95*6777b538SAndroid Build Coastguard Worker   out[(*size)++] = static_cast<Char>(code_point);
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker // DoUTFConversion ------------------------------------------------------------
99*6777b538SAndroid Build Coastguard Worker // Main driver of UTFConversion specialized for different Src encodings.
100*6777b538SAndroid Build Coastguard Worker // dest has to have enough room for the converted text.
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker template <typename DestChar>
DoUTFConversion(const char * src,size_t src_len,DestChar * dest,size_t * dest_len)103*6777b538SAndroid Build Coastguard Worker bool DoUTFConversion(const char* src,
104*6777b538SAndroid Build Coastguard Worker                      size_t src_len,
105*6777b538SAndroid Build Coastguard Worker                      DestChar* dest,
106*6777b538SAndroid Build Coastguard Worker                      size_t* dest_len) {
107*6777b538SAndroid Build Coastguard Worker   bool success = true;
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < src_len;) {
110*6777b538SAndroid Build Coastguard Worker     base_icu::UChar32 code_point;
111*6777b538SAndroid Build Coastguard Worker     CBU8_NEXT(reinterpret_cast<const uint8_t*>(src), i, src_len, code_point);
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker     if (!IsValidCodepoint(code_point)) {
114*6777b538SAndroid Build Coastguard Worker       success = false;
115*6777b538SAndroid Build Coastguard Worker       code_point = kErrorCodePoint;
116*6777b538SAndroid Build Coastguard Worker     }
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker     UnicodeAppendUnsafe(dest, dest_len, code_point);
119*6777b538SAndroid Build Coastguard Worker   }
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   return success;
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker template <typename DestChar>
DoUTFConversion(const char16_t * src,size_t src_len,DestChar * dest,size_t * dest_len)125*6777b538SAndroid Build Coastguard Worker bool DoUTFConversion(const char16_t* src,
126*6777b538SAndroid Build Coastguard Worker                      size_t src_len,
127*6777b538SAndroid Build Coastguard Worker                      DestChar* dest,
128*6777b538SAndroid Build Coastguard Worker                      size_t* dest_len) {
129*6777b538SAndroid Build Coastguard Worker   bool success = true;
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   auto ConvertSingleChar = [&success](char16_t in) -> base_icu::UChar32 {
132*6777b538SAndroid Build Coastguard Worker     if (!CBU16_IS_SINGLE(in) || !IsValidCodepoint(in)) {
133*6777b538SAndroid Build Coastguard Worker       success = false;
134*6777b538SAndroid Build Coastguard Worker       return kErrorCodePoint;
135*6777b538SAndroid Build Coastguard Worker     }
136*6777b538SAndroid Build Coastguard Worker     return in;
137*6777b538SAndroid Build Coastguard Worker   };
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   size_t i = 0;
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   // Always have another symbol in order to avoid checking boundaries in the
142*6777b538SAndroid Build Coastguard Worker   // middle of the surrogate pair.
143*6777b538SAndroid Build Coastguard Worker   while (i + 1 < src_len) {
144*6777b538SAndroid Build Coastguard Worker     base_icu::UChar32 code_point;
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker     if (CBU16_IS_LEAD(src[i]) && CBU16_IS_TRAIL(src[i + 1])) {
147*6777b538SAndroid Build Coastguard Worker       code_point = CBU16_GET_SUPPLEMENTARY(src[i], src[i + 1]);
148*6777b538SAndroid Build Coastguard Worker       if (!IsValidCodepoint(code_point)) {
149*6777b538SAndroid Build Coastguard Worker         code_point = kErrorCodePoint;
150*6777b538SAndroid Build Coastguard Worker         success = false;
151*6777b538SAndroid Build Coastguard Worker       }
152*6777b538SAndroid Build Coastguard Worker       i += 2;
153*6777b538SAndroid Build Coastguard Worker     } else {
154*6777b538SAndroid Build Coastguard Worker       code_point = ConvertSingleChar(src[i]);
155*6777b538SAndroid Build Coastguard Worker       ++i;
156*6777b538SAndroid Build Coastguard Worker     }
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker     UnicodeAppendUnsafe(dest, dest_len, code_point);
159*6777b538SAndroid Build Coastguard Worker   }
160*6777b538SAndroid Build Coastguard Worker 
161*6777b538SAndroid Build Coastguard Worker   if (i < src_len) {
162*6777b538SAndroid Build Coastguard Worker     UnicodeAppendUnsafe(dest, dest_len, ConvertSingleChar(src[i]));
163*6777b538SAndroid Build Coastguard Worker   }
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   return success;
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_32_BIT)
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker template <typename DestChar>
DoUTFConversion(const wchar_t * src,size_t src_len,DestChar * dest,size_t * dest_len)171*6777b538SAndroid Build Coastguard Worker bool DoUTFConversion(const wchar_t* src,
172*6777b538SAndroid Build Coastguard Worker                      size_t src_len,
173*6777b538SAndroid Build Coastguard Worker                      DestChar* dest,
174*6777b538SAndroid Build Coastguard Worker                      size_t* dest_len) {
175*6777b538SAndroid Build Coastguard Worker   bool success = true;
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < src_len; ++i) {
178*6777b538SAndroid Build Coastguard Worker     auto code_point = static_cast<base_icu::UChar32>(src[i]);
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker     if (!IsValidCodepoint(code_point)) {
181*6777b538SAndroid Build Coastguard Worker       success = false;
182*6777b538SAndroid Build Coastguard Worker       code_point = kErrorCodePoint;
183*6777b538SAndroid Build Coastguard Worker     }
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker     UnicodeAppendUnsafe(dest, dest_len, code_point);
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   return success;
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker 
191*6777b538SAndroid Build Coastguard Worker #endif  // defined(WCHAR_T_IS_32_BIT)
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker // UTFConversion --------------------------------------------------------------
194*6777b538SAndroid Build Coastguard Worker // Function template for generating all UTF conversions.
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker template <typename InputString, typename DestString>
UTFConversion(const InputString & src_str,DestString * dest_str)197*6777b538SAndroid Build Coastguard Worker bool UTFConversion(const InputString& src_str, DestString* dest_str) {
198*6777b538SAndroid Build Coastguard Worker   if (IsStringASCII(src_str)) {
199*6777b538SAndroid Build Coastguard Worker     dest_str->assign(src_str.begin(), src_str.end());
200*6777b538SAndroid Build Coastguard Worker     return true;
201*6777b538SAndroid Build Coastguard Worker   }
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   dest_str->resize(src_str.length() *
204*6777b538SAndroid Build Coastguard Worker                    size_coefficient_v<typename InputString::value_type,
205*6777b538SAndroid Build Coastguard Worker                                       typename DestString::value_type>);
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker   // Empty string is ASCII => it OK to call operator[].
208*6777b538SAndroid Build Coastguard Worker   auto* dest = &(*dest_str)[0];
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker   // ICU requires 32 bit numbers.
211*6777b538SAndroid Build Coastguard Worker   size_t src_len = src_str.length();
212*6777b538SAndroid Build Coastguard Worker   size_t dest_len = 0;
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker   bool res = DoUTFConversion(src_str.data(), src_len, dest, &dest_len);
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker   dest_str->resize(dest_len);
217*6777b538SAndroid Build Coastguard Worker   dest_str->shrink_to_fit();
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   return res;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker }  // namespace
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker // UTF16 <-> UTF8 --------------------------------------------------------------
225*6777b538SAndroid Build Coastguard Worker 
UTF8ToUTF16(const char * src,size_t src_len,std::u16string * output)226*6777b538SAndroid Build Coastguard Worker bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output) {
227*6777b538SAndroid Build Coastguard Worker   return UTFConversion(StringPiece(src, src_len), output);
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker 
UTF8ToUTF16(StringPiece utf8)230*6777b538SAndroid Build Coastguard Worker std::u16string UTF8ToUTF16(StringPiece utf8) {
231*6777b538SAndroid Build Coastguard Worker   std::u16string ret;
232*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
233*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
234*6777b538SAndroid Build Coastguard Worker   UTF8ToUTF16(utf8.data(), utf8.size(), &ret);
235*6777b538SAndroid Build Coastguard Worker   return ret;
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker 
UTF16ToUTF8(const char16_t * src,size_t src_len,std::string * output)238*6777b538SAndroid Build Coastguard Worker bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output) {
239*6777b538SAndroid Build Coastguard Worker   return UTFConversion(StringPiece16(src, src_len), output);
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker 
UTF16ToUTF8(StringPiece16 utf16)242*6777b538SAndroid Build Coastguard Worker std::string UTF16ToUTF8(StringPiece16 utf16) {
243*6777b538SAndroid Build Coastguard Worker   std::string ret;
244*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
245*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
246*6777b538SAndroid Build Coastguard Worker   UTF16ToUTF8(utf16.data(), utf16.length(), &ret);
247*6777b538SAndroid Build Coastguard Worker   return ret;
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker // UTF-16 <-> Wide -------------------------------------------------------------
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_16_BIT)
253*6777b538SAndroid Build Coastguard Worker // When wide == UTF-16 the conversions are a NOP.
254*6777b538SAndroid Build Coastguard Worker 
WideToUTF16(const wchar_t * src,size_t src_len,std::u16string * output)255*6777b538SAndroid Build Coastguard Worker bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) {
256*6777b538SAndroid Build Coastguard Worker   output->assign(src, src + src_len);
257*6777b538SAndroid Build Coastguard Worker   return true;
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker 
WideToUTF16(std::wstring_view wide)260*6777b538SAndroid Build Coastguard Worker std::u16string WideToUTF16(std::wstring_view wide) {
261*6777b538SAndroid Build Coastguard Worker   return std::u16string(wide.begin(), wide.end());
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker 
UTF16ToWide(const char16_t * src,size_t src_len,std::wstring * output)264*6777b538SAndroid Build Coastguard Worker bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) {
265*6777b538SAndroid Build Coastguard Worker   output->assign(src, src + src_len);
266*6777b538SAndroid Build Coastguard Worker   return true;
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker 
UTF16ToWide(StringPiece16 utf16)269*6777b538SAndroid Build Coastguard Worker std::wstring UTF16ToWide(StringPiece16 utf16) {
270*6777b538SAndroid Build Coastguard Worker   return std::wstring(utf16.begin(), utf16.end());
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker 
273*6777b538SAndroid Build Coastguard Worker #elif defined(WCHAR_T_IS_32_BIT)
274*6777b538SAndroid Build Coastguard Worker 
WideToUTF16(const wchar_t * src,size_t src_len,std::u16string * output)275*6777b538SAndroid Build Coastguard Worker bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) {
276*6777b538SAndroid Build Coastguard Worker   return UTFConversion(std::wstring_view(src, src_len), output);
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker 
WideToUTF16(std::wstring_view wide)279*6777b538SAndroid Build Coastguard Worker std::u16string WideToUTF16(std::wstring_view wide) {
280*6777b538SAndroid Build Coastguard Worker   std::u16string ret;
281*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
282*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
283*6777b538SAndroid Build Coastguard Worker   WideToUTF16(wide.data(), wide.length(), &ret);
284*6777b538SAndroid Build Coastguard Worker   return ret;
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker 
UTF16ToWide(const char16_t * src,size_t src_len,std::wstring * output)287*6777b538SAndroid Build Coastguard Worker bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) {
288*6777b538SAndroid Build Coastguard Worker   return UTFConversion(StringPiece16(src, src_len), output);
289*6777b538SAndroid Build Coastguard Worker }
290*6777b538SAndroid Build Coastguard Worker 
UTF16ToWide(StringPiece16 utf16)291*6777b538SAndroid Build Coastguard Worker std::wstring UTF16ToWide(StringPiece16 utf16) {
292*6777b538SAndroid Build Coastguard Worker   std::wstring ret;
293*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
294*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
295*6777b538SAndroid Build Coastguard Worker   UTF16ToWide(utf16.data(), utf16.length(), &ret);
296*6777b538SAndroid Build Coastguard Worker   return ret;
297*6777b538SAndroid Build Coastguard Worker }
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker #endif  // defined(WCHAR_T_IS_32_BIT)
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker // UTF-8 <-> Wide --------------------------------------------------------------
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker // UTF8ToWide is the same code, regardless of whether wide is 16 or 32 bits
304*6777b538SAndroid Build Coastguard Worker 
UTF8ToWide(const char * src,size_t src_len,std::wstring * output)305*6777b538SAndroid Build Coastguard Worker bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) {
306*6777b538SAndroid Build Coastguard Worker   return UTFConversion(StringPiece(src, src_len), output);
307*6777b538SAndroid Build Coastguard Worker }
308*6777b538SAndroid Build Coastguard Worker 
UTF8ToWide(StringPiece utf8)309*6777b538SAndroid Build Coastguard Worker std::wstring UTF8ToWide(StringPiece utf8) {
310*6777b538SAndroid Build Coastguard Worker   std::wstring ret;
311*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
312*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
313*6777b538SAndroid Build Coastguard Worker   UTF8ToWide(utf8.data(), utf8.length(), &ret);
314*6777b538SAndroid Build Coastguard Worker   return ret;
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_16_BIT)
318*6777b538SAndroid Build Coastguard Worker // Easy case since we can use the "utf" versions we already wrote above.
319*6777b538SAndroid Build Coastguard Worker 
WideToUTF8(const wchar_t * src,size_t src_len,std::string * output)320*6777b538SAndroid Build Coastguard Worker bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) {
321*6777b538SAndroid Build Coastguard Worker   return UTF16ToUTF8(as_u16cstr(src), src_len, output);
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker 
WideToUTF8(std::wstring_view wide)324*6777b538SAndroid Build Coastguard Worker std::string WideToUTF8(std::wstring_view wide) {
325*6777b538SAndroid Build Coastguard Worker   return UTF16ToUTF8(StringPiece16(as_u16cstr(wide), wide.size()));
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker #elif defined(WCHAR_T_IS_32_BIT)
329*6777b538SAndroid Build Coastguard Worker 
WideToUTF8(const wchar_t * src,size_t src_len,std::string * output)330*6777b538SAndroid Build Coastguard Worker bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) {
331*6777b538SAndroid Build Coastguard Worker   return UTFConversion(std::wstring_view(src, src_len), output);
332*6777b538SAndroid Build Coastguard Worker }
333*6777b538SAndroid Build Coastguard Worker 
WideToUTF8(std::wstring_view wide)334*6777b538SAndroid Build Coastguard Worker std::string WideToUTF8(std::wstring_view wide) {
335*6777b538SAndroid Build Coastguard Worker   std::string ret;
336*6777b538SAndroid Build Coastguard Worker   // Ignore the success flag of this call, it will do the best it can for
337*6777b538SAndroid Build Coastguard Worker   // invalid input, which is what we want here.
338*6777b538SAndroid Build Coastguard Worker   WideToUTF8(wide.data(), wide.length(), &ret);
339*6777b538SAndroid Build Coastguard Worker   return ret;
340*6777b538SAndroid Build Coastguard Worker }
341*6777b538SAndroid Build Coastguard Worker 
342*6777b538SAndroid Build Coastguard Worker #endif  // defined(WCHAR_T_IS_32_BIT)
343*6777b538SAndroid Build Coastguard Worker 
ASCIIToUTF16(StringPiece ascii)344*6777b538SAndroid Build Coastguard Worker std::u16string ASCIIToUTF16(StringPiece ascii) {
345*6777b538SAndroid Build Coastguard Worker   DCHECK(IsStringASCII(ascii)) << ascii;
346*6777b538SAndroid Build Coastguard Worker   return std::u16string(ascii.begin(), ascii.end());
347*6777b538SAndroid Build Coastguard Worker }
348*6777b538SAndroid Build Coastguard Worker 
UTF16ToASCII(StringPiece16 utf16)349*6777b538SAndroid Build Coastguard Worker std::string UTF16ToASCII(StringPiece16 utf16) {
350*6777b538SAndroid Build Coastguard Worker   DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16);
351*6777b538SAndroid Build Coastguard Worker   return std::string(utf16.begin(), utf16.end());
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker #if defined(WCHAR_T_IS_16_BIT)
ASCIIToWide(StringPiece ascii)355*6777b538SAndroid Build Coastguard Worker std::wstring ASCIIToWide(StringPiece ascii) {
356*6777b538SAndroid Build Coastguard Worker   DCHECK(IsStringASCII(ascii)) << ascii;
357*6777b538SAndroid Build Coastguard Worker   return std::wstring(ascii.begin(), ascii.end());
358*6777b538SAndroid Build Coastguard Worker }
359*6777b538SAndroid Build Coastguard Worker 
WideToASCII(std::wstring_view wide)360*6777b538SAndroid Build Coastguard Worker std::string WideToASCII(std::wstring_view wide) {
361*6777b538SAndroid Build Coastguard Worker   DCHECK(IsStringASCII(wide)) << wide;
362*6777b538SAndroid Build Coastguard Worker   return std::string(wide.begin(), wide.end());
363*6777b538SAndroid Build Coastguard Worker }
364*6777b538SAndroid Build Coastguard Worker #endif  // defined(WCHAR_T_IS_16_BIT)
365*6777b538SAndroid Build Coastguard Worker 
366*6777b538SAndroid Build Coastguard Worker }  // namespace base
367