LINUX.ORG.RU

Unicode в С++


0

3

Понадобился мне тут сабж, и после дня ковыряний появился вопрос - это вообще возможно? Ситуация такая: CLI приложение, у него есть файл данных жёстко в UTF-8, также оно должно читать/писать пользовательские данные (думается, в его локали), а внутри работать со строками посимвольно + tolower/toupper + какая-никакая сортировка.

Как я понял, «C++» way - использовать эти locale и facets, только нигде по ним нет нормальной документации. Во всех примерах конвертят (через facet шототам .wider) ASCII из char* в wchar_t* - замечательно но только если в char* UTF8 то конвертит оно по байтам а не по символам. Это во-первых. Во-вторых, оно зависит от этого долбаного setlocale, а мне нахрен не упёрлось чтобы конвертация между utf8 и широким форматом как-то зависела от локали. C++'ного преобразования регистра нет, конвертим строки через towlower/towupper, что тоже с какого-то хрена зависит от локали. Сишный way с mbstowcs завист от локали аналогично. Кое-где советуют писать свою utf8 локаль или брать из буста с хитрыми хаками по переопределению namespace'ов.

Порыскал по интернету, нашёл замечательную библиотечку http://slonik-v-domene.livejournal.com/17731.html?thread=93507 как я понял utf8<->wide + lower/upper, безо всяких идиотских локалей. Там, правда, уродский сишный интерфейс с кучей аллокаций, но это не проблема переписать. Также для широких символов там используется не wchar_t, а unsigned int, а это уже не попихаешь в в wcout.

Ещё есть ICU (с совершенно ублюдской документацией) и, в конце концов iconv (хотя я бы предпочёл отказаться от внешних библиотек вообще).

Ещё есть новые литералы и char16_t/char32_t в C++11.

Итого - всего много, но ничего нормально не работает. Как быть?

Предполагаю что правильнее всего было бы разобраться с C++ локалями/фасетами и написать свои классы для utf8 и возможно utf32 с возможностью конвертации между ними, а для последнего case и сортировку. Однако нужна вменяемая документация на то как оно работает и вообще что эти фасеты значат. Другой вариант - сделать basic_string<int32_t> и написать для него функции конвертации в/из string (с utf8) и tolower/toupper и забыть про этот ад. Общение с пользователем оставить только в utf8.

★★★★★

>Предполагаю что правильнее всего было бы написать свой велосипед

Истину глаголешь! Сделай это, Томми!

yyk ★★★★★
()

enjoy your C++

anonymous
()

>Во-вторых, оно зависит от этого долбаного setlocale, а мне нахрен не упёрлось чтобы конвертация между utf8 и широким форматом как-то зависела от локали.

char *setlocale(int category, const char *locale); ← обратить внимание на второй аргумент.

Будешь зависеть только от наличия локали же. Хочешь не зависеть даже от этого — только iconv.

x3al ★★★★★
()
Ответ на: комментарий от x3al

> Хочешь не зависеть даже от этого

Разумеется, не хочу. У меня в голове даже не укладывается кто придумал от этого зависеть.

только iconv.

iconv не умеет upper/lower, поэтому его в любом случае не хватит. Если остановиться на utf-8 снаружи и utf-32 внутри легче действительно написать велосипед, ибо и utf8<->utf-32 и uc/lc по таблице делаются тривиально. Можно прилепить iconv исключительно для поддержки локалей, но на это можно забить.

Меня, тем не менее, интересует как можно велосипеда избежать или сделать его максимально незаметным. А это нормальная документация с примерами по ICU и C++'ным локалям-фасетам.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от slovazap

> Подробнее.

А в прочем, не надо. То что там есть полностью эквивалентно chacu, не канает. Аллокации на каждый чих, удодливый сишный интерфейс и полный glib.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от slovazap

Что тут непонятного? Использовать байтовые строки, а по символам utf-8 итерировать с помощью итераторов из glib.

Reset ★★★★★
()

wchar_t <-> utf8, на всех ОС wchar_t хранит UTF32, на виндовс - UTF16, преобразования тривиальны и легко нунлятся

aho
()
Ответ на: комментарий от Reset

> Что тут непонятного? Использовать байтовые строки, а по символам utf-8 итерировать с помощью итераторов из glib

Спасибо, нет.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от aho

> wchar_t <-> utf8, на всех ОС wchar_t хранит UTF32, на виндовс - UTF16, преобразования тривиальны и легко нунлятся

Во-первых, все утверждения здесь ложны, во-вторых - способ преобразования utf8<->wchar без локалей в студию.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от slovazap

> Во-первых, все утверждения здесь ложны, во-вторых - способ преобразования utf8<->wchar без локалей в студию.

ну раз ложны - ищи сам

aho
()
Ответ на: комментарий от m0rph

> Посмотри, как это в Qt реализовано.

Посмотри как это сделано в QString.

Да, QString посмотрю, спасибо за подсказку.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от slovazap

Думаю что в QString свой велосипед. Они скорее всего создают кучу меппингов toupper/tolower для символов поддерживаемых языков.

m0rph ★★★★★
()

ICU, эталон, но жирноват

shty ★★★★★
()
Ответ на: комментарий от Reset

строго говоря, нет. Но, в принципе, UTF-16 это расширение UCS-2, так что можно в некоторых случаях «делать вид» что у нас на самом деле UCS-2. Хотя это и неправильно, но многие сишные и плюсовые программы так и делают.

anonymous
()
Ответ на: комментарий от anonymous

> в винде для юникодных функций нет локалей.

имелся в виду используемый набор символов

aho
()
Ответ на: комментарий от slovazap

Не в wchar надо преобразовывать, а в uint32_t. Делается это тривиально - в википедии описано как.

Reset ★★★★★
()
Ответ на: комментарий от anonymous

>icu4c

Не годится. ТС надо потрахаться, а не результат.

yyk ★★★★★
()

А почему нельзя взять QtCore и юзать оттуда QString?

DELIRIUM ☆☆☆☆☆
()

locale и facets, только нигде по ним нет нормальной документации

Посмотри тут, например. Ну по ссылкам из оттуда тоже.

one_more_hokum ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.