А как насчёт скрестить UTF-8 и Win32 API?
Пришла давеча в голову совсем неоригинальная мысль – а почему ещё никто не сделал надстройку над Win32 API, позволяющую использовать строки, закодированные в UTF-8? Ведь существует же масса причин, чтобы такая библиотека пользовалась бы спросом, особенно несколько лет назад – во время массовой миграции с 9x на NT.
- Такую библиотеку несложно написать. Базовая инфраструктура в виде ANSI и Unicode вариантов одних и тех же Win32 функций существует. C и C++ поддерживают многобайтные символы (MBCS), в том числе и UTF-8.
- Перекодирование из UTF-8 в UTF-16 и обратно может показаться затратным, однако, к примеру, Wow64 делает фактически то же самое, перекодируя 32-х битные параметры в 64-х битные при каждом системном вызове и никакой особенной деградации производительности не заметно.
- Опыт применения UTF-8 в Unix мире показывает, что большинство ANSI приложений может без особых проблем работать с UTF-8 строками. Конечно, есть и отличия, но они легко обходятся.
- Переделка большого ANSI приложения в Unicode вариант, работающий с двухбайтовыми строками, весьма сложная и затратная процедура, требующая времени и немалого опыта от разработчиков. Перевод приложения на UTF-8. по всей видимости, должен быть значительно проще.
Конечно же, есть случаи, когда переход на UTF-8 сам по себе ничего не даёт, однако в большинстве ситуаций это вполне оправдано. Так почему же никто таким не пользуется?
PS: Беглый поиск в Интернете дал ссылку только одну ссылку UTF-8 Cygwin. Однако не удалось найти ни одной реализации для чистого Windows окружения.
А как насчёт скрестить UTF-8 и Win32 API?…
Пришла давеча в голову совсем неоригинальная мысль – а почему ещё никто не сдела…
А я уже сделал.
Очень просто - создал клон класса CString (очень старый, от VC++ 4.0), выкинув из него двухбайтовость и левую многобайтность. Все хранение в однобайтном буфере (т.е. char *) строки UTF-8. Разумеется, конструкторы из CString и переопределенное присваивание.
Я не стал переделывать системные вызовы. Везде, где надо, я в мои классы добавляю временную переменную типа CString, а в вызове делаю SomeStr.ToStr(cstr).
Разумеется, это не так удобно, как обертывание всего API, но работает зашибись.
К примеру, я смог использовать xgettext для интернационализации своих программ, что на порядок круче отстоя с интернационализацией ресурсов.
Теперь языки у меня переключаются динамически прямо в запущенной программе, из меню.
Производительность не пострадала - т.е. я не заметил тормозов. Хотя специально не замерял.
Некоторые из стандартных Windows функций имеют UTF-8 overload-ы. Например - DNS функции. Загляните в список экспорта из DNSAPI.DLL и сможете увидеть например такое:
DnsValidateName_A
DnsValidateName_UTF8
DnsValidateName_W
Интересно, не знал об этом.
О поддержке UTF-8 в реальных проектах, которые рождались как ANSI великолепно написал Michael Caplan здесь http://blogs.msdn.com/michkap/archive/2007/05/11/2547703.aspx
Он описывает нюансы, приведшие к прекращению поддержки UTF-8 в VCRT 8.0, и, насколько я понимаю, все доводы применимы и к MSLU.
Цитата: But to be honest, given that every project I have ever seen that claimed to support UTF-8 failed in the 3/4 byte cases (some even failed in the 2-byte cases!)
А еще нужно учесть, что длина UTF-8 представления символа из UCS-4 может быть до 6 байт (для code points за пределами первых 17 плоскостей, rfc2279).
Не могу сказать что аргументы Майкла звучат убедительно. По моему, всё что он сказал это то, что проекты использующие UTF-16 поддерживают Unicode лучше чем UTF-8 аналоги только потому, что и там и там разработчики лажают с поддержкой многосимвольных последовательностей. Просто в один символ UTF-16 можно запихать гораздо больше разных кодировок, чем в в один символ UTF-8.
Сколько разных программистов, зная что в тексте ровно N байт выделяют для смены кодировки буфер размером 2*N , в неявном предположении, что при конвертации объем не может увеличиться больше чем в два раза? При этом число 2 скорее всего замаскировано чем-то вроде sizeof(wchar_t), если программист знает, что на Unix-ах wchar_t четырехбайтный. И большинство кодировок (все single-byte) вполне отвечают этому эмпирическому правилу, что позволяет таким ошибкам жить в коде, которому уже довольно много лет.
Так что мы имеем два отрицательных момента. Первый состоит в том, что программисту нужно быть много аккуратнее в управлении памятью при добавлении поддержки UTF-8, так как максимальный размер символа может достигать 6-ти байт для UCS-4, 4-х байт для UTF-16 и 3-х байт для Basic Multilingual Plane. В сравнении с этим правила UTF-16 просты до безобразия - 2 байта для Basic Multilingual Plane и 4 байта для азиатских языков.
Второй отрицательный момент в том, что для того, чтобы сделать что-либо полезное с текстом, будь то сортировка или отрисовка - внутри runtime (в широком смысле) все равно нужно будет получить code-point, что для UTF-8 более затратная операция.
Ну и в качестве курьеза, который показывает, что за аргументацией Майкла Каплана возможно стоит нечто большее, чем абстрактные рассуждения. Google для запроса “utf-16 problem” находит 380 000 ссылок, а для “utf-8 problem” - 5 900 000. Разница более чем в 15 раз
Да я согласная, согласная я.
За исключением ремарки про UCS-4. UTF-16 тоже не способна закодировать всё многообразие UCS-4.
Моя мысль состоит в том, что при переделки ANSI проекта в Unicode в случае UTF-16 делается двойная работа - сначала все переводится на UCS-2, а потом, когда обнаруживается, что UCS-2 и UTF-16 это не одно и тоже, начинаются заделываться дырки с surrogate characters. И это если не затрагивать символов вроде ударений и прочих, имеющих культурно/лингвистическое значение.
В случае же с UTF-8 массу усилий, которые в “нормальном” случае тратяться на героическую замену strlen на wstrlen (а по уму - сразу на StringCchLength), можно потратить на искоренение “лингвистисеких” проблем.
В общем, нехорошо маскировать проблему и говорить, что мы, мол, поддерживаем весь Unicode, хотя на самом деле поддерживаются дай бог только европейские языки.
[...] тут совсем недавно удивлялся почему нет библиотек, эмулирующих поддержку UTF-8 на [...]