1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/utf_string_conversions.h"
#include <stdint.h>
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "build/build_config.h"
namespace base {
namespace {
// Generalized Unicode converter -----------------------------------------------
// Converts the given source Unicode character type to the given destination
// Unicode character type as a STL string. The given input buffer and size
// determine the source, and the given output STL string will be replaced by
// the result.
template<typename SRC_CHAR, typename DEST_STRING>
bool ConvertUnicode(const SRC_CHAR* src,
size_t src_len,
DEST_STRING* output) {
// ICU requires 32-bit numbers.
bool success = true;
int32_t src_len32 = static_cast<int32_t>(src_len);
for (int32_t i = 0; i < src_len32; i++) {
uint32_t code_point;
if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
WriteUnicodeCharacter(code_point, output);
} else {
WriteUnicodeCharacter(0xFFFD, output);
success = false;
}
}
return success;
}
} // namespace
// UTF-8 <-> Wide --------------------------------------------------------------
bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) {
if (IsStringASCII(std::wstring(src, src_len))) {
output->assign(src, src + src_len);
return true;
} else {
PrepareForUTF8Output(src, src_len, output);
return ConvertUnicode(src, src_len, output);
}
}
std::string WideToUTF8(const std::wstring& wide) {
if (IsStringASCII(wide)) {
return std::string(wide.data(), wide.data() + wide.length());
}
std::string ret;
PrepareForUTF8Output(wide.data(), wide.length(), &ret);
ConvertUnicode(wide.data(), wide.length(), &ret);
return ret;
}
bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) {
if (IsStringASCII(StringPiece(src, src_len))) {
output->assign(src, src + src_len);
return true;
} else {
PrepareForUTF16Or32Output(src, src_len, output);
return ConvertUnicode(src, src_len, output);
}
}
std::wstring UTF8ToWide(StringPiece utf8) {
if (IsStringASCII(utf8)) {
return std::wstring(utf8.begin(), utf8.end());
}
std::wstring ret;
PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret);
ConvertUnicode(utf8.data(), utf8.length(), &ret);
return ret;
}
// UTF-16 <-> Wide -------------------------------------------------------------
#if defined(WCHAR_T_IS_UTF16)
// When wide == UTF-16, then conversions are a NOP.
bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output) {
output->assign(src, src_len);
return true;
}
string16 WideToUTF16(const std::wstring& wide) {
return wide;
}
bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output) {
output->assign(src, src_len);
return true;
}
std::wstring UTF16ToWide(const string16& utf16) {
return utf16;
}
#elif defined(WCHAR_T_IS_UTF32)
bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output) {
output->clear();
// Assume that normally we won't have any non-BMP characters so the counts
// will be the same.
output->reserve(src_len);
return ConvertUnicode(src, src_len, output);
}
string16 WideToUTF16(const std::wstring& wide) {
string16 ret;
WideToUTF16(wide.data(), wide.length(), &ret);
return ret;
}
bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output) {
output->clear();
// Assume that normally we won't have any non-BMP characters so the counts
// will be the same.
output->reserve(src_len);
return ConvertUnicode(src, src_len, output);
}
std::wstring UTF16ToWide(const string16& utf16) {
std::wstring ret;
UTF16ToWide(utf16.data(), utf16.length(), &ret);
return ret;
}
#endif // defined(WCHAR_T_IS_UTF32)
// UTF16 <-> UTF8 --------------------------------------------------------------
#if defined(WCHAR_T_IS_UTF32)
bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) {
if (IsStringASCII(StringPiece(src, src_len))) {
output->assign(src, src + src_len);
return true;
} else {
PrepareForUTF16Or32Output(src, src_len, output);
return ConvertUnicode(src, src_len, output);
}
}
string16 UTF8ToUTF16(StringPiece utf8) {
if (IsStringASCII(utf8)) {
return string16(utf8.begin(), utf8.end());
}
string16 ret;
PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret);
// Ignore the success flag of this call, it will do the best it can for
// invalid input, which is what we want here.
ConvertUnicode(utf8.data(), utf8.length(), &ret);
return ret;
}
bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) {
if (IsStringASCII(StringPiece16(src, src_len))) {
output->assign(src, src + src_len);
return true;
} else {
PrepareForUTF8Output(src, src_len, output);
return ConvertUnicode(src, src_len, output);
}
}
std::string UTF16ToUTF8(StringPiece16 utf16) {
std::string ret;
// Ignore the success flag of this call, it will do the best it can for
// invalid input, which is what we want here.
UTF16ToUTF8(utf16.data(), utf16.length(), &ret);
return ret;
}
#elif defined(WCHAR_T_IS_UTF16)
// Easy case since we can use the "wide" versions we already wrote above.
bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) {
return UTF8ToWide(src, src_len, output);
}
string16 UTF8ToUTF16(StringPiece utf8) {
return UTF8ToWide(utf8);
}
bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) {
return WideToUTF8(src, src_len, output);
}
std::string UTF16ToUTF8(StringPiece16 utf16) {
if (IsStringASCII(utf16))
return std::string(utf16.data(), utf16.data() + utf16.length());
std::string ret;
PrepareForUTF8Output(utf16.data(), utf16.length(), &ret);
ConvertUnicode(utf16.data(), utf16.length(), &ret);
return ret;
}
#endif
string16 ASCIIToUTF16(StringPiece ascii) {
DCHECK(IsStringASCII(ascii)) << ascii;
return string16(ascii.begin(), ascii.end());
}
std::string UTF16ToASCII(StringPiece16 utf16) {
DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16);
return std::string(utf16.begin(), utf16.end());
}
} // namespace base
|