LINUX.ORG.RU

sqlite3_exec и wchar_t


0

2

Сабж. Как добавить запись в sqlite3 базу из C/C++, при том, что данные в wchar_t?

UPD: с этим разобрался. Теперь другая проблема. В базу не записывается

sqlite3_stmt * stmt;
sqlite3_prepare16(db, sql.str().c_str(), -1, &stmt, NULL);
sqlite3_step(stmt);
sqlite3_finalize(stmt);

где sql типа wstringstream

Если же вручную ввести такой же запрос в клиенте sqlite3, то добавляется.

★★★★★

Последнее исправление: cvs-255 (всего исправлений: 2)
Ответ на: комментарий от const86

Не в utf16, а в wchar_t, который вообще говоря не обязан совпадать с utf16

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от mashina

в итоге ситуация такая:

если я делаю sqlite3_prepare с обычной строчкой, то он принимает. если sqlite3_prepare16 с строчкой в wchar_t, то он не принимает

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

где sql типа wstringstream

похоже, даёшь ему не utf-16 строчку.

mashina ★★★★★
()
Ответ на: комментарий от cvs-255

sqlite3_prepare16 с строчкой в wchar_t, то он не принимает

что вполне вполне логично, wchar_t это не utf16

mashina ★★★★★
()
Ответ на: комментарий от cvs-255

если sqlite3_prepare16 с строчкой в wchar_t, то он не принимает

а чего он должен ее принимать - wchar_t на линуксе это UTF32

wota ★★
()
Ответ на: комментарий от cvs-255

И как быть согласно стандарту (чтобы не было платформо-зависимого кода)?

char16_t

const86 ★★★★★
()
Ответ на: комментарий от cvs-255

Явно перекодировать wchar_t в нужную кодировку, или использовать char16_t из C++11. А откуда у тебя вообще появился wchar_t если ты пишешь под онтопик?

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

Так не рекомендуется, вообще говоря, использовать char для русских букв в utf8.

Или же все функции для работы со строками должны быть специальными, именно для utf8, а не обычные.

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 1)
Ответ на: комментарий от cvs-255

Так не рекомендуется, вообще говоря, использовать char для русских букв в utf8.

Не-не, для UTF-8 - именно char, даже функциями из стандартной библиотеки С или С++ можно использовать в ряде случаев (копирование, конкатенация). Другой вопрос, что там где нужно работать с количеством и индексами символов, сравнивать строки с учётом различным способов кодирования одного и того же символа нужны специальные функции. Но нужно учитывать, что такие же специальные функции нужны и для UTF-16 и UTF-32 (которые могут использоваться для wchar_t). Из трёх кодировок Unicode только одна (UTF-32) обладает фиксированной длиной code-point, но в самом Unicode символ может представляться несколькими code-point'ами (например, ä может быть записана двумя code-point'ами, а может и одним). Т.е. библиотеки нужны для правильной работы с Unicode'ом вне зависимости от кодировки. wchar_t на онтопике не нужен, нужен он на оффтопике по историческим причинам.

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

Ну так для wchar_t есть стандартные функции в языке. Для UTF8 я таких не нашел.

Даже strlen для utf8 не нашел, хотя куда уж проще функция.

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

strlen, toupper итд, без привлечения сторонних жирных библиотек?

Разве что strlen. Остальное все плохо работает. towupper:

This function is not very appropriate for dealing with Unicode characters, because Unicode knows about three cases: upper, lower and title case.

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

Ну так для wchar_t есть стандартные функции в языке

А они учитывают специфику Unicode? А ты сам используя wchar_t учитываешь специфику Unicode? В частности ту, что русская ё может кодироваться по-разному. Повторюсь использование Unicode == использование написанных под него библиотек (icu, например), wchar_t не предоставляет никаких гарантий.

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

towupper

Так это для wchar_t, а не для utf8

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Begemoth

А ты сам используя wchar_t учитываешь специфику Unicode?

wchar_t вообще говоря не обязан совпадать с юникодом.

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

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

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

Какие конкретно проблемы с переносимостью? Это же внутренняя реализация широких символов. Весь ввод-вывод в системной кодировке идет.

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 2)
Ответ на: комментарий от cvs-255

1. Кодировка wchar_t не определена, следовательно на разных платформах с одними и теми же данными программа может работать по разному.

2. wchar_t - это один символ расширенного набора (согласно стандарта), если для wchar_t используется UTF-16 или UTF-32 то возможны ситуации, когда один символ представлен wchar_t[2].

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

Кодировка wchar_t не определена, следовательно на разных платформах с одними и теми же данными программа может работать по разному.

Данные я откуда то беру?Я же не храню данные в wchar_t. Я их храню в utf8. А когда загружаю, перевожу в wchar_t.

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 1)
Ответ на: комментарий от cvs-255

Да пофигу откуда тебе пришел этот wchar_t и что там внутри. Твоя задача преобразовать его [нормально] в utf-8/16. Гуглится элементарно.

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

Ну так если я хочу перевести в utf8, то я выставлю локаль utf8.

setlocale никто не отменял

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

Давай один раз убьем все вопросы, пусть даже прикрепленный тред висит никто не замечает. Есть внешние данные, для них ты в общем виде должен знать кодировку. Но поскольку ты в душе не ведаешь, какова она, на помощь приходит LANG, который заюзан в stdlib'е. stdlib тебе выдает либо байты как есть (char *), либо «широкие буквы» (wchar_t). Как есть оно и есть как есть, а широкие это /хз какое-то/ внутреннее представление, которое совершенно случайно иногда может походить на UTF-16/32, но и то не полностью. То есть это черный ящик.

Далее рассуждения переходят в плоскость преобразования типов, где есть разные типы, в идеале отделенные тайпдефами, но в реальности это все может быть char *. Между ними есть функции преобразования. Тебе надо преобразовать wchar_t в utf-8/16. Что ты для этого выберешь — совершенно неважно, но а) нельзя «просто» кастануть, б) stdlib этого не умеет «просто».

arturpub ★★
()
Ответ на: комментарий от cvs-255

преобразование utf-8 -> wchar_t пройдёт везде нормально. Но результат будет _разный_.

1. wchar_t нужен тогда, когда тебе нужна «десятая буква с конца»

2. utf-8 нужен во всех остальных случаях.

Что такое wchar_t — никто не знает, и знать не может. Даже размер не определён. За то ясно, что str[17] это восемнадцатый _символ_, т.к. 1 _символ_ занимает по определению 1 wchar_t. Сколько «это» в байтах — зависит и от символа, и от реализации.

Потому wchar_t не нужны, если ты пишешь в файл и/или в СУБД.

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

stdlib этого не умеет «просто».

не благодари: wcstombs - convert a wide-character string to a multibyte string

size_t wcstombs(char *dest, const wchar_t *src, size_t n);

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

Но результат будет _разный_

Ну и пусть. Когда я буду выводить, я обратно wchar_t в utf8 преобразую.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от emulek

wchar_t не нужен вообще, док, поскольку он не выживает в пустошах, а преобразование наружу/внутрь для него в общем виде не является lossless. Если кто-то захочет соблюсти какие-то инварианты относительно хранилища текста, например любимую всеми (но на практике *никогда* не используемую) произвольную побуквенную индексируемость, то ему достаточно проверить, что в UTF-32 потоке после NFC-нормализации не осталось композитов. Правда этому балбесу будет не совсем ясно, что делать, если их таки внезапно осталось ;)

wchar_t это зло..учий анахронизм со времен, когда многа буков стало уже нужно, а стандарты еще не доварились.

Мы тут как-то тему прикрепляли по wchar_t и компания, но какой-то умник ее открепил. Видимо лишп и факториалы на шкалах ему показались важнее.

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

wchar_t нужен тогда, когда тебе нужна «десятая буква с конца»

И тут не всегда поможет Mac OS X кодирует (по-крайней мере раньше кодировал) букву ё двумя code-point'ами: умляут и е.

Begemoth ★★★★★
()
Ответ на: комментарий от cvs-255

Например, на Windows wchar_t - это UTF-16, а это либо кодировка с переменной длиной символа (как UTF-8), что не соответствует wchar_t, либо только часть символов юникода. Вообще строго говоря extended character set (wchar_t) не обязан отличаться от basic character set (char), это всё на усмотрение реализации. У wchar_t слишком много неопределённостей для его практического применения за пределами кода, напрямую работающего с Windows API.

Begemoth ★★★★★
()
Ответ на: комментарий от cvs-255

Ну и пусть. Когда я буду выводить, я обратно wchar_t в utf8 преобразую.

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

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

wchar_t не нужен вообще, док, поскольку он не выживает в пустошах

это как?

а преобразование наружу/внутрь для него в общем виде не является lossless.

а это вендопроблемы. УМВР.

Если кто-то захочет соблюсти какие-то инварианты относительно хранилища текста, например любимую всеми (но на практике *никогда* не используемую) произвольную побуквенную индексируемость

вот не нужно за всё и за всех отвечать. Иногда — нужно. Да, редко. Вот например. Давеча даже мегабаксу зачем-то надо было. А оно и по буквам тупит...

И да, ещё сортировка часто IRL нужна, причём регистронезависимая. Причём быстрая.

wchar_t это зло..учий анахронизм со времен, когда многа буков стало уже нужно, а стандарты еще не доварились.

32х битный wcahr_t вполне годен. Но да, признаю, что так только в GNU/Linux.

Мы тут как-то тему прикрепляли по wchar_t и компания, но какой-то умник ее открепил. Видимо лишп и факториалы на шкалах ему показались важнее.

увы.

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

И тут не всегда поможет Mac OS X кодирует (по-крайней мере раньше кодировал) букву ё двумя code-point'ами: умляут и е.

альтернативно мыслящие должны страдать.

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

не обязан отличаться от basic character set (char), это всё на усмотрение реализации.

Но он должен кодировать все встречающиеся в системе символы.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от emulek

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

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от emulek

Под пустошами имелось ввиду в файлах / сетевых пакетах.

а преобразование наружу/внутрь для него в общем виде не является lossless.

а это вендопроблемы. УМВР.

УТВР только потому, что ты не используешь локаль, где большая часть символов — странные композиты, а такие языки слышал бывают (хотя могу и ошибаться, краем глаза читал в каком-то ратионале по уникоду). Кроме того, можно вчарной проге в утф-локали скормить какой-нить совершенно-уникод-валидный синтетический композит, которым она тут же подавится.

То же самое о побуквенной индексации. Если она нужна — порежь поток на буквы и бегай по char **, кто мешает? Весь мир договорился, что есть символы и их допустимые композиты, и будем ими пользоваться. wchar_t же нам предлагает просто избегать проблемных мест и НЕ искать расстояние левенштейна для них. А если кому-то надо? Я считаю нет смысла работать только с частью общепризнанного набора, особенно когда сложность уже есть, а профитов все еще не очень.

.

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

arturpub ★★
()
Ответ на: комментарий от cvs-255

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

ты как в базу пишешь? Судя по первому посту, как раз в wchar_t. А надо в utf-8.

Да, wchar_t только внутри RAM, и только если нужен посимвольный разбор.

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

Под пустошами имелось ввиду в файлах / сетевых пакетах.

хрени wchar_t там нечего делать.

УТВР только потому, что ты не используешь локаль, где большая часть символов — странные композиты, а такие языки слышал бывают (хотя могу и ошибаться, краем глаза читал в каком-то ратионале по уникоду). Кроме того, можно вчарной проге в утф-локали скормить какой-нить совершенно-уникод-валидный синтетический композит, которым она тут же подавится.

не подавится. Просто результаты поиска/сортировки будут неточные. Заметь: именно неточные, а не неверные. Т.е. скажем буква «ё» будет стоять в конце алфавита, а не после «е». Если она через умляут записана почему-то.

То же самое о побуквенной индексации. Если она нужна — порежь поток на буквы и бегай по char **

ты никогда не задумывался, сколько занимает обратный индекс? Как минимум столько же, сколько вся твоя выборка текста. А если ты её на char** порежешь? А ведь не все грамотные, 95% идиоты, и пишут неграмотно. Потому чёткий поиск не катит, т.к. ничего не находит.

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

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

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

Не очень понял. С буквой ё все норм, потому что она может в рекомпозицию, а можно например скомбинировать ё еще и с нижним хвостиком, насколько я знаю, и у нее не будет собственой nfc-формы. Если без вот этого, то я с тобой полностью согласен — утф и хорошо реализованный вчар должны по идее быть идентичны по функциональности.

Если с этим, то у всех unicode-aware регулярок есть флаг «не учитывать безразмерные компоненты», так что и е, и ё, и ё с хвостиком будут равнозначны при поиске. Хотя с другой стороны, всякие расстояния левенштейна имеют смысл только для фонетических текстов, а они хорошо определены и ограничены алфавитами, поэтому моя теоретическая буква к практике отношения и правда не имеет.

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

ну на практике пока особых проблем у меня не было. Русский/англ/укр работают нормально, других не нужно. Да, с wchar_t. И да, win/mac у меня нет, и не нужно. Пусть страдают. Впрочем, в клиентских компьютерах и нет тонны текстов. Т.ч. там можно как ты говоришь и по char** порезать, не проблема. Или ещё лучше вообще так искать, без всяких индексов. Есть в glibc такая штука как regex(3), она сейчас отлично работает с utf-8. Т.ч. wchar_t действительно не нужны. Зачем ими обмазываются — не знаю.

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

А нет ли уже готовой реализации чего-нибудь вроде utfchar_t?

Чтобы при переводе из char* в него, все эти точки над ё итд группировались в одну переменную. И уже из этих переменных делать строку.

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