1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/strings/utf_string_conversions.h"
7 #include "base/strings/string_piece.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversion_utils.h"
15 // Generalized Unicode converter -----------------------------------------------
17 // Converts the given source Unicode character type to the given destination
18 // Unicode character type as a STL string. The given input buffer and size
19 // determine the source, and the given output STL string will be replaced by
21 template<typename SRC_CHAR
, typename DEST_STRING
>
22 bool ConvertUnicode(const SRC_CHAR
* src
,
24 DEST_STRING
* output
) {
25 // ICU requires 32-bit numbers.
27 int32 src_len32
= static_cast<int32
>(src_len
);
28 for (int32 i
= 0; i
< src_len32
; i
++) {
30 if (ReadUnicodeCharacter(src
, src_len32
, &i
, &code_point
)) {
31 WriteUnicodeCharacter(code_point
, output
);
33 WriteUnicodeCharacter(0xFFFD, output
);
43 // UTF-8 <-> Wide --------------------------------------------------------------
45 bool WideToUTF8(const wchar_t* src
, size_t src_len
, std::string
* output
) {
46 if (IsStringASCII(std::wstring(src
, src_len
))) {
47 output
->assign(src
, src
+ src_len
);
50 PrepareForUTF8Output(src
, src_len
, output
);
51 return ConvertUnicode(src
, src_len
, output
);
55 std::string
WideToUTF8(const std::wstring
& wide
) {
56 if (IsStringASCII(wide
)) {
57 return std::string(wide
.data(), wide
.data() + wide
.length());
61 PrepareForUTF8Output(wide
.data(), wide
.length(), &ret
);
62 ConvertUnicode(wide
.data(), wide
.length(), &ret
);
66 bool UTF8ToWide(const char* src
, size_t src_len
, std::wstring
* output
) {
67 if (IsStringASCII(StringPiece(src
, src_len
))) {
68 output
->assign(src
, src
+ src_len
);
71 PrepareForUTF16Or32Output(src
, src_len
, output
);
72 return ConvertUnicode(src
, src_len
, output
);
76 std::wstring
UTF8ToWide(const StringPiece
& utf8
) {
77 if (IsStringASCII(utf8
)) {
78 return std::wstring(utf8
.begin(), utf8
.end());
82 PrepareForUTF16Or32Output(utf8
.data(), utf8
.length(), &ret
);
83 ConvertUnicode(utf8
.data(), utf8
.length(), &ret
);
87 // UTF-16 <-> Wide -------------------------------------------------------------
89 #if defined(WCHAR_T_IS_UTF16)
91 // When wide == UTF-16, then conversions are a NOP.
92 bool WideToUTF16(const wchar_t* src
, size_t src_len
, string16
* output
) {
93 output
->assign(src
, src_len
);
97 string16
WideToUTF16(const std::wstring
& wide
) {
101 bool UTF16ToWide(const char16
* src
, size_t src_len
, std::wstring
* output
) {
102 output
->assign(src
, src_len
);
106 std::wstring
UTF16ToWide(const string16
& utf16
) {
110 #elif defined(WCHAR_T_IS_UTF32)
112 bool WideToUTF16(const wchar_t* src
, size_t src_len
, string16
* output
) {
114 // Assume that normally we won't have any non-BMP characters so the counts
116 output
->reserve(src_len
);
117 return ConvertUnicode(src
, src_len
, output
);
120 string16
WideToUTF16(const std::wstring
& wide
) {
122 WideToUTF16(wide
.data(), wide
.length(), &ret
);
126 bool UTF16ToWide(const char16
* src
, size_t src_len
, std::wstring
* output
) {
128 // Assume that normally we won't have any non-BMP characters so the counts
130 output
->reserve(src_len
);
131 return ConvertUnicode(src
, src_len
, output
);
134 std::wstring
UTF16ToWide(const string16
& utf16
) {
136 UTF16ToWide(utf16
.data(), utf16
.length(), &ret
);
140 #endif // defined(WCHAR_T_IS_UTF32)
142 // UTF16 <-> UTF8 --------------------------------------------------------------
144 #if defined(WCHAR_T_IS_UTF32)
146 bool UTF8ToUTF16(const char* src
, size_t src_len
, string16
* output
) {
147 if (IsStringASCII(StringPiece(src
, src_len
))) {
148 output
->assign(src
, src
+ src_len
);
151 PrepareForUTF16Or32Output(src
, src_len
, output
);
152 return ConvertUnicode(src
, src_len
, output
);
156 string16
UTF8ToUTF16(const StringPiece
& utf8
) {
157 if (IsStringASCII(utf8
)) {
158 return string16(utf8
.begin(), utf8
.end());
162 PrepareForUTF16Or32Output(utf8
.data(), utf8
.length(), &ret
);
163 // Ignore the success flag of this call, it will do the best it can for
164 // invalid input, which is what we want here.
165 ConvertUnicode(utf8
.data(), utf8
.length(), &ret
);
169 bool UTF16ToUTF8(const char16
* src
, size_t src_len
, std::string
* output
) {
170 if (IsStringASCII(StringPiece16(src
, src_len
))) {
171 output
->assign(src
, src
+ src_len
);
174 PrepareForUTF8Output(src
, src_len
, output
);
175 return ConvertUnicode(src
, src_len
, output
);
179 std::string
UTF16ToUTF8(const string16
& utf16
) {
180 if (IsStringASCII(utf16
)) {
181 return std::string(utf16
.begin(), utf16
.end());
185 // Ignore the success flag of this call, it will do the best it can for
186 // invalid input, which is what we want here.
187 UTF16ToUTF8(utf16
.data(), utf16
.length(), &ret
);
191 #elif defined(WCHAR_T_IS_UTF16)
192 // Easy case since we can use the "wide" versions we already wrote above.
194 bool UTF8ToUTF16(const char* src
, size_t src_len
, string16
* output
) {
195 return UTF8ToWide(src
, src_len
, output
);
198 string16
UTF8ToUTF16(const StringPiece
& utf8
) {
199 return UTF8ToWide(utf8
);
202 bool UTF16ToUTF8(const char16
* src
, size_t src_len
, std::string
* output
) {
203 return WideToUTF8(src
, src_len
, output
);
206 std::string
UTF16ToUTF8(const string16
& utf16
) {
207 return WideToUTF8(utf16
);
212 string16
ASCIIToUTF16(const StringPiece
& ascii
) {
213 DCHECK(IsStringASCII(ascii
)) << ascii
;
214 return string16(ascii
.begin(), ascii
.end());
217 std::string
UTF16ToASCII(const string16
& utf16
) {
218 DCHECK(IsStringASCII(utf16
)) << UTF16ToUTF8(utf16
);
219 return std::string(utf16
.begin(), utf16
.end());