LINUX.ORG.RU

Кто как получает на C / C++ utf8 (utf16) string из пользовательских данных?


1

1

Убогость стандартных библиотек C & C++ поражает воображение. Как можно нормально сконвертировать что-то, что передаётся в программу извне, в utf формат. iconv не очень вдохновляет громозкостью кода и неспособностью работать с отдельными символами многобайтных кодировок.

Хочу один раз написать фукнцию (утилиту) для конвертации строк, чтобы решить хотя бы эту каждодневную задачу.

Ответ на: комментарий от ziemin

wchar_t - это не utf. Это убогое нечто. К прімеру, под windows это UCS-2. Мне нужно знать что этот массів байт в конкретной кодіровке (utf-x).

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

попробую эту ICU.

А чего ему там быть тяжёлым?

создаёт такое впечатленіе кол-вом всего что там есть.

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

А что непонятного? Вот, например, у меня везде локаль — КОИ8-Р. И я совершенно не парюсь по поводу конвертации чего бы там ни было.

Кстати, если таки собираешься ССЗБ быть, то в GTK есть функции преобразования с использованием iconv на основе текущей локали.

Anon
()

я свой велосипед наворотил. но использую и iconv тоже. свой велик только там где iconv не работает, по той или иной причине.

а чем конкретно iconv не устраивает?

насчет ICU, по моим личным впечатлениям — оно намного хуже iconv, в плане тяжести особенно.

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

пример: мне нужно прочитать юзер инпут и записать его в файл в UTF16-LE (формат требует). А код хочется писать портабельный, а не который держится на честном слова. Da taho ž mne ciesna ŭ KOI-8 :)

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

Кстати, если таки собираешься ССЗБ быть, то в GTK есть функции преобразования с использованием iconv на основе текущей локали.

не в gtk, а в glib. который вообще вселенское зло. лучше голый iconv использовать. там нет ничего сложного.

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

Da taho ž mne ciesna ŭ

Жесть!

Ну, раз так, то только iconv/enca.

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

а чем конкретно iconv не устраивает?

код у меня получается примерно такой: https://github.com/dzidzitop/libafc/blob/master/src/afc/stringToUTF16.cpp

Что бесит - валится на невалидном инпуте, безопасная конвертация (с заменой неваліда '?') невозможна в POSIX iconv. Также невозможно выцепить следуюсчий символ в последовательности без «мат индукции» (+ 1 байт - новый вызов iconv).

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

Да ладно тебе, невозможна! А как тогда, по-твоему, работает сам iconv? Вот точно ключик не помню, а маны лень читать. Но помню, что отлично он пропускал невалидный вход.

А enca тебе чем не нравится?

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

пример: мне нужно прочитать юзер инпут и записать его в файл в UTF16-LE (формат требует).

если нужно что-то совсем легкое, и без депендов — глянь тут, вдруг подойдет (придется выдирать из моего проекта куски кода):

utf8.c библиотека для работы с utf8, с охрененно быстрыми tolower, strcasestr, strcasecmp.

junklib.c а тут есть функция ddb_iconv, которая (невзирая на название) iconv вовсе не использует, но умеет конвертировать между разными кодировками, такими как: cp1251, iso8859-1, utf16le/be, shift-jis.

это все работает без дополнительных библиотек (кроме libc), но потащит за собой еще несколько файлов из исходников.

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

Вселенское зло — говнокути. А говноTK — просто фигня.

я и не говорю что gtk зло. я говорю конкретно про использование glib за пределами gtk. а вам надо поменьше на говне зацикливаться. а то приснится еще.

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

Да ладно тебе, невозможна!

в gnu iconv есть //TRANSLIT (как-то так) - пользую как костыль. в POSIX тупо нет.

А enca тебе чем не нравится?

а можно ссылку? а то выдаётся в поіске левота какая-то.

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

спасибо, гляну. Но юзкейс такой: any encoding -> utf(-x) -> простая (портабельная) обработка известной мне кодировки -> any encoding.

any encoding тут не будет.

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

Что бесит - валится на невалидном инпуте, безопасная конвертация (с заменой неваліда '?') невозможна в POSIX iconv. Также невозможно выцепить следуюсчий символ в последовательности без «мат индукции» (+ 1 байт - новый вызов iconv).

ты бы написал, для начала, что у тебя на входе, и что ты хочешь получить на выходе.

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

спасибо, гляну. Но юзкейс такой: any encoding -> utf(-x) -> простая (портабельная) обработка известной мне кодировки -> any encoding.

т.е. нужно угадывать кодировки?

у меня такой код тоже есть, но он умеет определять только между iso8859-1/cp1251/utf8. строки на входе могут быть очень короткими, 3 символа например. или вообще 1. на таких вводных, угадать произвольную кодировку нереально.

а так вообще такие библиотеки есть, и тебе совсем не iconv нужен. смотри что браузеры используют.

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

т.е. нужно угадывать кодировки?

Нет. Мне нужно приблизительно:

std::u32string convertToUtf32(const char * src, const char * srcEncoding);

Т.е. чтобы из поизвольной кодировки получить UTF, работать с которым можно предсказуемо и просто.

Задача частично решена (кривым кодом что давал выше) - но есть проблемы когда передают кривой инпут - ничего вообсче не сконвертируется, и я даже не буду знать где именно проблемная последовательность.

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

ок. тогда я все же неправильно понял. входная кодировка известна, так? значит, если инпут кривой — входная кодировка неправильная. что предполагается делать с этим кривым вводом? зачем вообще с ним что-либо делать? выдать просто сообщение об ошибке нельзя?

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

зачем вообще с ним что-либо делать? выдать просто сообщение об ошибке нельзя?

хочется знать в каком месте произошла ошибка + опциональное recovery.

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

я уже пользую iconv - и очень не нравится то, что получилось.

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

опциональное recovery

об этом и вопрос. что такое recovery в данном случае?

ты не знаешь входную кодировку (она неправильная, по условию задачи).

не один ли хрен, будешь ли ты знать на каком байте она не совпала, или не будешь? все равно угадывать кодировку для всего инпута придется.

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

об этом и вопрос. что такое recovery в данном случае?

src -> utf - тут сложно сказать можно ли делать recovery.

utf -> dest - то, что не влазит в кодировку dest заменять на '?', чтобы пользователь с KOI-8 получил хоть какую-то информацию (с iconv можно, когда я знаю что src это конкретная кодировка)

не один ли хрен, будешь ли ты знать на каком байте она не совпала, или не будешь?

для отладки проблемы очень полезно.

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

Т.е. чтобы из поизвольной кодировки получить UTF, работать с которым можно предсказуемо и просто.

Простите, Вы уверены, что транспортная кодировка (буква T в названии) - это то, с чем следует работать ? Ну, то есть, конечно, если планируется со строками действительно работать (резать/склеивать/искать итп), а не просто зачитать в одном формате, выплюнуть наружу в другом.

Вообще, обычно для задач обработки строковых данных используют кодировку с предсказуемым размером символа (например, тот же UCS-2, если его хватает), а на входе и выходе ставят конвертеры из/в нужные форматы.

Отдельно, конечно, нужно решать вопрос, как обрабатывать в такой схеме потоковые данные, но, тут уже нужно предметнее смотреть, для каких-то случаев хватит и тоненькой прокладки на базе iconv.

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

транспортная кодировка (буква T в названии)

Подавился чаем и полез в Вики. Таки transformation - это не «транспортная».

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

Да, пожалуй, облажался. Но менее транспортной она от этого не становится :)

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

Т.е. чтобы из поизвольной кодировки получить UTF, работать с которым можно предсказуемо и просто.

Вот с UTF-8 работать как раз сложнее и непредсказумее чем с wchar_t. Непредсказуемый размер символов - это очень предсказуемо.

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

wchar_t - это не utf. Это убогое нечто.

может ты не умеешь его готовить?

К прімеру, под windows это UCS-2.

ну а тебе до того что? wchar_t это непереносимый _внутренний_ формат, который годен для того, что-бы пилить строчку на символы.

Мне нужно знать что этот массів байт в конкретной кодіровке (utf-x).

дык — знай. Кто тебе это запрещает-то?

Хочу один раз написать фукнцию (утилиту) для конвертации строк, чтобы решить хотя бы эту каждодневную задачу.

позволь поинтересоваться: с какой целью? Для того, что-бы вынести этот твой костыль в

#define MUSTDIE
так?

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

А что непонятного? Вот, например, у меня везде локаль — КОИ8-Р

а вот скажи-ка мне на милость, как в твоей кои будет «і»?

У меня это 0xD1 0x96

Эту каоничную рассовую букву я взял из поста ТСа. Пруф:

$ echo  "К прімеру" |hexdump -C
00000000  d0 9a 20 d0 bf d1 80 d1  96 d0 bc d0 b5 d1 80 d1  |.. .............|
00000010  83 0a                                             |..|
00000012
что скажешь?

Только не надо мне тут про KOI8-U! Ты там даже своё имя хрен запишешь!

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

мне нужно прочитать юзер инпут и записать его в файл в UTF16-LE (формат требует).

вот и напиши свой форматозависимый костыль из wchar_t на/в твою UTF16-LE.

хочется писать портабельный, а не который держится на честном слова.

за это не переживай: в маздае всё так плохо потому, что там как раз за совместимость радеют. Оно до сих пор с cp866 MS-DOS совместимо. Т.ч. ничего там не поменяется.

А в Linux всё и так хорошо, там уже utf-8. Не вижу проблемы.

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

Вселенское зло — говнокути. А говноTK — просто фигня.

говнолиб(glib) — унылое говно мамонта. Давно пора закапывать. А кути — свежее, только высранное говнецо. Есть ещё маздай, там просто срут уже 30 лет в одно и то же место (в периметр ОС), и никто ничего никогда не закапывает. А если кому покажется, что какая-то кучка плохо пахнет, то он сразу на эту кучку накладывает свою кучу дерьма, которая совсем не воняет.

Выбирай на вкус и цвет. Выбор всегда есть.

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

Да ладно тебе, невозможна! А как тогда, по-твоему, работает сам iconv? Вот точно ключик не помню, а маны лень читать. Но помню, что отлично он пропускал невалидный вход.

не.

1. An invalid multibyte sequence is encountered in the input. In this case it sets errno to EILSEQ and returns (size_t) -1. *inbuf is left pointing to the begin- ning of the invalid multibyte sequence.

т.е. нужно скормить строчку, и отловить EILSEQ. Как отловишь, пропустить кривой символ, и кормить дальше. Я так делал.

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

Выбирай на вкус и цвет.

Из перечисленного тобою я не буду ничего выбирать ☺

пользуюсь гнутыми coreutils + кое-какими GPLными библиотеками.

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

что скажешь?

chartable 

 32 -  	 64 - @	 96 - `	128 - ─	160 - ═	192 - ю	224 - Ю	
 33 - !	 65 - A	 97 - a	129 - │	161 - ║	193 - а	225 - А	
 34 - "	 66 - B	 98 - b	130 - ┌	162 - ╒	194 - б	226 - Б	
 35 - #	 67 - C	 99 - c	131 - ┐	163 - ё	195 - ц	227 - Ц	
 36 - $	 68 - D	100 - d	132 - └	164 - ╓	196 - д	228 - Д	
 37 - %	 69 - E	101 - e	133 - ┘	165 - ╔	197 - е	229 - Е	
 38 - &	 70 - F	102 - f	134 - ├	166 - ╕	198 - ф	230 - Ф	
 39 - '	 71 - G	103 - g	135 - ┤	167 - ╖	199 - г	231 - Г	
 40 - (	 72 - H	104 - h	136 - ┬	168 - ╗	200 - х	232 - Х	
 41 - )	 73 - I	105 - i	137 - ┴	169 - ╘	201 - и	233 - И	
 42 - *	 74 - J	106 - j	138 - ┼	170 - ╙	202 - й	234 - Й	
 43 - +	 75 - K	107 - k	139 - ▀	171 - ╚	203 - к	235 - К	
 44 - ,	 76 - L	108 - l	140 - ▄	172 - ╛	204 - л	236 - Л	
 45 - -	 77 - M	109 - m	141 - █	173 - ╜	205 - м	237 - М	
 46 - .	 78 - N	110 - n	142 - ▌	174 - ╝	206 - н	238 - Н	
 47 - /	 79 - O	111 - o	143 - ▐	175 - ╞	207 - о	239 - О	
 48 - 0	 80 - P	112 - p	144 - ░	176 - ╟	208 - п	240 - П	
 49 - 1	 81 - Q	113 - q	145 - ▒	177 - ╠	209 - я	241 - Я	
 50 - 2	 82 - R	114 - r	146 - ▓	178 - ╡	210 - р	242 - Р	
 51 - 3	 83 - S	115 - s	147 - ⌠	179 - Ё	211 - с	243 - С	
 52 - 4	 84 - T	116 - t	148 - ■	180 - ╢	212 - т	244 - Т	
 53 - 5	 85 - U	117 - u	149 - ∙	181 - ╣	213 - у	245 - У	
 54 - 6	 86 - V	118 - v	150 - √	182 - ╤	214 - ж	246 - Ж	
 55 - 7	 87 - W	119 - w	151 - ≈	183 - ╥	215 - в	247 - В	
 56 - 8	 88 - X	120 - x	152 - ≤	184 - ╦	216 - ь	248 - Ь	
 57 - 9	 89 - Y	121 - y	153 - ≥	185 - ╧	217 - ы	249 - Ы	
 58 - :	 90 - Z	122 - z	154 -  	186 - ╨	218 - з	250 - З	
 59 - ;	 91 - [	123 - {	155 - ⌡	187 - ╩	219 - ш	251 - Ш	
 60 - <	 92 - \	124 - |	156 - °	188 - ╪	220 - э	252 - Э	
 61 - =	 93 - ]	125 - }	157 - ²	189 - ╫	221 - щ	253 - Щ	
 62 - >	 94 - ^	126 - ~	158 - ·	190 - ╬	222 - ч	254 - Ч	
 63 - ?	 95 - _	127 - 	159 - ÷	191 - ©	223 - ъ	255 - Ъ	

В ASCII недостающие буквы есть. А если ему всякие Г с черточками нужны, пусть своей КОИ8-У пользуется. Мне нафиг эти буковки не нужны!

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

Из перечисленного тобою я не буду ничего выбирать

кто бы сомневался, что свои велосипеды из говна и палок совсем не воняют.

я уже описал твой путь:

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

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

В ASCII недостающие буквы есть. А если ему всякие Г с черточками нужны, пусть своей КОИ8-У пользуется. Мне нафиг эти буковки не нужны!

это ты, нацмен, не нужен. Смирись. Кроме русских, есть ещё и другие национальности, и их ЧСХ, намного больше. А в одиночку ты — ноль. Люди должны объединяться. Программисты — не исключение. А всякие сатанинские системы с одной кодировкой (e.g. только русская) людей разъединяют. Т.е. суть прямой путь в гиену огненную и погибель для человеков!

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

eb 20 d0 d2 69 cd c5 d2 d5 0a

0x69 это вообще-то такая позиция из камасутры.

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

Нас — рать! ☺

emulek

0x69 это вообще-то такая позиция из камасутры.

Не нравится — пользуйся чем-нибудь своим. Я вообще извращением считаю заменять букву "и" на "i"! А еще глаз режет, когда вместо "ы" пишут "ьi": ну неужто, если не в силах настроить 3 раскладки, нельзя писать "ьı"?

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

Я вообще извращением считаю заменять букву «и» на «i»!

это у них «исконно русское» блѧдѣ (:

Без своей i они себя чувствуют так, как будто-бы забыли лицо своего отца. Уж поверь мне, лучше дать им эту букву, чем что-то доказывать.

вместо «ы» пишут «ьi»

дык у них нет Ы.

ну неужто, если не в силах настроить 3 раскладки

1. рукожопие — вовсе не русская национальная черта.

2. как их настроить, если в КОИ8-Р нет укр. букв, а в КОИ8-У нет русских? Вот, общаешься с такими-же упоротыми как и сам. Что тебя бесит-то?

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

Что бесит - валится на невалидном инпуте, безопасная конвертация (с заменой неваліда '?') невозможна в POSIX iconv. Также невозможно выцепить следуюсчий символ в последовательности без «мат индукции» (+ 1 байт - новый вызов iconv).

Общая замена на ? невозможна. Откуда он знает в какой кодировке (т.е. какого размера) данный невалид у тебя присутствует. Поэтому iconv делает максиму чего он может(и должнен) делать:

1. An invalid multibyte sequence is encountered in the input. In this case it sets errno to EILSEQ and returns (size_t) -1. *inbuf is left pointing to the beginning of the invalid multibyte sequence.

3. An incomplete multibyte sequence is encountered in the input, and the input byte sequence terminates after it. In this case it sets errno to EINVAL and returns (size_t) -1. *inbuf is left pointing to the beginning of the incomplete multibyte sequence.

CONFORMING TO
POSIX.1-2001.

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