Мы в нашей компании планируем сделать наше приложение поддерживающим Юникод, и мы анализируем, какие проблемы нам предстоит встретить.
В частности, наше приложение будет, например, сильно полагаться на длины строк, и мы хотели бы использовать wchar_t
в качестве базового класса символов.
Проблема возникает при работе с символами, которые должны храниться в 2 единицах по 16 битов в UTF-16, а именно с символами выше U + 10000.
Простой пример:
У меня есть строка UTF-8 "蟂" (символ Unicode U + 87C2, в UTF-8: E8 9F 82)
Итак, я установил следующий код:
const unsigned char my_utf8_string[] = { 0xe8, 0x9f, 0x82, 0x00 };
// compute size of wchar_t buffer.
int nb_chars = ::MultiByteToWideChar(CP_UTF8, // input is UTF8
0, // no flags
reinterpret_cast<char *>(my_utf8_string), // input string (no worries about signedness)
-1, // input is zero-terminated
NULL, // no output this time
0); // need the necessary buffer size
// allocate
wchar_t *my_utf16_string = new wchar_t[nb_chars];
// convert
nb_chars = ::MultiByteToWideChar(CP_UTF8,
0,
reinterpret_cast<char *>(my_utf8_string),
-1,
my_widechar_string, // output buffer
nb_chars); // allocated size
Хорошо, это работает, он выделяет дважды 16 бит, и мой буфер wchar_t
содержит {0x87c2, 0x0000}. Если я храню его внутри std::wstring
и вычисляю размер, я получаю 1.
Теперь давайте возьмем символ ? (U + 104A2) в качестве ввода в UTF-8: F0 90 92 A2.
На этот раз он выделяет место для трех wchar_t и std :: wstring :: size возвращает 2 , хотя я считаю, что у меня только один символ .
Это проблематично. Предположим, что мы получаем данные в UTF-8. Мы можем считать символы Юникода просто не считая байтов, равных 10xxxxxx
. Мы хотели бы импортировать эти данные в массив wchar_t
для работы с ним. Если мы просто выделим количество символов плюс один, это может быть безопасно ... пока кто-нибудь не использует символ выше U + FFFF. И тогда наш буфер будет слишком коротким, и наше приложение вылетит.
Итак, с одной и той же строкой, кодированной по-разному, функции, считающие символы в строке, будут возвращать разные значения?
Как разрабатываются приложения, работающие со строками Unicode, чтобы избежать такого рода раздражений?
Спасибо за ваши ответы.