Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2014.09.14;
Скачать: [xml.tar.bz2];

Вниз

Разбираемся в кодировках   Найти похожие ветки 

 
DevilDevil ©   (2014-01-24 16:16) [0]

Совсем скоро понадобится писать потоковый конвертатор кодировок в довесок к функционалу библиотеки CachedBuffers. Это нужно для парсинга и генерации большого объёма текстовых файлов. К примеру если ваш парсер рассчитан на кодировку utf16, а ему подают 2Гб текста в кодировке utf8 - то стандартными средствами Delphi типа TEncoding или UTF8Decode данную задачу не решить. Не говоря уже о том, что будет отожрано немеряно оперативной памяти и работать жутко медленно.

Мне уже довелось иметь дело с конвертацией кодировок. Я подсматривал исходники функций в System.pas, часть кода смотрел в Wine. И добился хороших результатов, но в итоге пришёл к выводу, что мой подход непрофессиональный. К примеру я полагал, что размер символа в кодировке utf16 равен 2м байтам, а оказалось - от 2х до 4х. Я думал, что символ в кодировке utf8 может занимать максимум 3 байта, а оказалось 5. Я думал, что utf16 и UCS2 - это одно и то же.

Конкретно мне такой функционал нужен для быстрого парсинга огромных XML-файлов, где, как известно, должна быть поддержка не только множества Unicode-кодировок, но и множества Ansi-кодировок. И я хочу окончательно в этом разобраться, чтобы последний раз написать, отладить - и больше к этому не возвращаться.

В связи с этим мне хотелось бы получить помощь от форумчан:
1) качественно разжёванная информация
2) конкретный рабочий корректный код конвертации
3) платформозависимые особенности API (Win, Mac, iOs, And, Lin)
4) моральная поддержка
5) помощь в тестировании

Меня часто обвиняют в том, что я слишком далеко отхожу от стандартных простых проверенных решений. И подобная критика была бы очень уместна, если бы передо мной стояли типичные задачи - разработать быстро, без ошибок, с перспективами лёгкой модификации. Но передо мной стоят задачи другого плана - обрабатывать огромные объёмы данных с максимальной скоростью. Поэтому и решения выбираются такие, чтобы добиться максимальной производительности. В частности это означает, что и конвертация будет организована нестандартным некрасивым образом, с чтением например сразу по 4-8 байт за итерацию. Хочется надеяться, что мои навыки и мои бесплатные библиотеки полезны сейчас или будут полезны в будущем вам.

Вот к примеру стал я копать текущие решения TEncoding внутри XE5. И с ужасом обнаружил, что исходники вообще не рассчитаны на 4х байтные кодировки: utf32le и utf32be. Notepad++ тоже не работает с этими кодировками и с utf16 (только ucs2). Поэтому к примеру один из первых моментов, которые хочется уточнить - с помощью какого текстового редактора можно создавать и модифицировать текстовые файлы в настоящих utf16/32 кодировках.


 
Kerk ©   (2014-01-24 16:32) [1]

Ну если ты сам говоришь, что делаешь не нечто универсальное, а что-то делающее хорошо одну конкретную работу, то нет ли смысла отказаться от поддержки разных кодировок? Часто ли попадаются тексты в странных кодировках? Нужно ли тебе поддерживать "настоящие" utf16/32, если на данный момент ты даже не знаешь чем такие файлы создать?

Кодировки - штука неисчерпаемая, оттуда живым не вылезешь. Я какое-то время уже занимался проблемами вроде "а почему наше приложение на корейской винде неправильно отображает китайские символы". Никому не пожелаю.

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


 
DVM ©   (2014-01-24 16:36) [2]


> Конкретно мне такой функционал нужен для быстрого парсинга
> огромных XML-файлов, где, как известно, должна быть поддержка
> не только множества Unicode-кодировок, но и множества Ansi-
> кодировок.

SAX парсер ты уже написал? Самая, имхо, актуальная кодировка для XML - UTF-8.


> Вот к примеру стал я копать текущие решения TEncoding внутри
> XE5. И с ужасом обнаружил, что исходники вообще не рассчитаны
> на 4х байтные кодировки: utf32le и utf32be. Notepad++ тоже
> не работает с этими кодировками и с utf16 (только ucs2).
>  Поэтому к примеру один из первых моментов, которые хочется
> уточнить - с помощью какого текстового редактора можно создавать
> и модифицировать текстовые файлы в настоящих utf16/32 кодировках.
>

Ты хоть раз встречал текст/документ/веб страницу в кодировках utf32le и utf32be? Я - нет. Теоретически, они могут встретиться, но на практике никто даже с реализацией особенно как видишь не заморачивается ибо не целесообразно. Даже UTF-16 редкость. Самые ходовые кодировки - UTF-8, Unicode (два варианта с разным порядком байт) и однобайтовые.


 
DevilDevil ©   (2014-01-24 16:51) [3]

> Kerk ©   (24.01.14 16:32) [1]
> DVM ©   (24.01.14 16:36) [2]

Вы конечно многое что правильно говорите. Только я предпочитаю прорабатывать конкретный блок прежде, чем переходить на следующий. SAX-парсер это замечательно, но что будет если ему подсунуть другую кодировку? Т.е. в итоге как минимум надо затачиваться на 3 ходовые кодировки: ansi, utf8, utf16. А раз уж подход с переконвертацией одинаковый - почему бы не поднатужиться и не дописать вариации utf32.

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

Ну и третья причина - я периодически сталкиваюсь с задачами парсинга (из разных кодировок). Хочется уже наконец дописать этот момент и забыть как страшный сон :)))


 
DVM ©   (2014-01-24 17:37) [4]


> Т.е. в итоге как минимум надо затачиваться на 3 ходовые
> кодировки: ansi, utf8,

Для парсера это практически одно и то же.


> Ну и третья причина - я периодически сталкиваюсь с задачами
> парсинга (из разных кодировок). Хочется уже наконец дописать
> этот момент и забыть как страшный сон :)))

Разные это Utf-8, Unicode и однобайтовые опять же :)


 
DevilDevil ©   (2014-01-24 17:42) [5]

> Для парсера это практически одно и то же.

да если название аттрибутов и узлов на латиннице
но к сожалению это бывает не всегда :)

> Разные это Utf-8, Unicode и однобайтовые опять же :)

Да, Ansi, Utf8 и Unicode
Но надоело каждый раз писать велосипед :)


 
DevilDevil ©   (2014-01-24 17:42) [6]

* и Utf16


 
Pavia ©   (2014-01-24 18:33) [7]

По моему самая распространённая кодировка это GB2312 странно что вы её не поддерживаете.


>  Я какое-то время уже занимался проблемами вроде "а почему
> наше приложение на корейской винде неправильно отображает
> китайские символы". Никому не пожелаю.

А вот МС считает что Big5 лучше чем GB2312.

UTF16 по моему никто не поддерживает.
Жил да был UNICODE 2-х байтовый потом консорциум сказал 2-байта мало, что и породило UTF16(новый UNICODE) и UCS16(старый UNICODE)
А так как в программах он обозначался UNICODE то и получилась путаница.


> что размер символа в кодировке utf16 равен 2м байтам, а
> оказалось - от 2х до 4х.

А разве не до 6?


> Самая, имхо, актуальная кодировка для XML - UTF-8.

А по стандарту UNICODE.


 
Pavia ©   (2014-01-24 18:34) [8]

По моему самая распространённая кодировка это GB2312 странно что вы её не поддерживаете.


>  Я какое-то время уже занимался проблемами вроде "а почему
> наше приложение на корейской винде неправильно отображает
> китайские символы". Никому не пожелаю.

А вот МС считает что Big5 лучше чем GB2312.

UTF16 по моему никто не поддерживает.
Жил да был UNICODE 2-х байтовый потом консорциум сказал 2-байта мало, что и породило UTF16(новый UNICODE) и UCS16(старый UNICODE)
А так как в программах он обозначался UNICODE то и получилась путаница.


> что размер символа в кодировке utf16 равен 2м байтам, а
> оказалось - от 2х до 4х.

А разве не до 6?


> Самая, имхо, актуальная кодировка для XML - UTF-8.

А по стандарту UNICODE.


 
BSD_Daemon   (2014-01-24 20:35) [9]

Потерпи чуть-чуть.
Все проблемы с кодировками исчезнут при выходе Delphi XE12...


 
Anatoly Podgoretsky ©   (2014-01-24 21:27) [10]


> UTF16 по моему никто не поддерживает.Жил да был UNICODE
> 2-х байтовый потом консорциум сказал 2-байта мало, что и
> породило UTF16(новый UNICODE) и UCS16(старый UNICODE)А так
> как в программах он обозначался UNICODE то и получилась
> путаница.

UTF-16 = UCS-2 для первых 64К символов, в больше этого ычтречается только в экзотических случаев, типа иероглифов. Не знаю как сейчас в Дельфи, но ранее была только декларация. Насчет UTF-32 тут вообще смех, Микрософт изначально разрабатывал именно 32 бита, но Юникод корсоциум их обсмеял, он в то время поддерживал 16 бит, когда же Микрософт перешел на 16 бит, то снова подвергся остракизму. Но тут уж Микрософт отыгрался и придумал UTF-16 с поддержкой до 1 миллиона символов. А консорциум остался с 32 битами, но только на Линуксе.


 
DVM ©   (2014-01-24 22:07) [11]


> Pavia ©   (24.01.14 18:34) [8]


> А по стандарту UNICODE

Ни в спецификации XML1.0 ни в XML1.1 не указано, что использовать надо какую либо определенную кодировку. Зато там указано, что все парсеры ДОЛЖНЫ поддерживать UTF-8 и UTF-16.

XML - в первую очередь формат для обмена данными и логичнее всего использовать транспортные кодировки, данные в которых представлены наиболее компактно.
9 из 10 XML файлов используют UTF-8.


 
DVM ©   (2014-01-24 22:33) [12]


>
> DevilDevil ©   (24.01.14 16:16) 

http://www.gnu.org/software/libiconv/

Тут смотри реализацию готовую. В принципе можно сделать обертку для этой dll и все. Она почти на всех платформах работает. Ну или портировать, но это долго и муторно.


 
Rouse_ ©   (2014-01-24 22:34) [13]


> Вот к примеру стал я копать текущие решения TEncoding внутри
> XE5. И с ужасом обнаружил, что исходники вообще не рассчитаны
> на 4х байтные кодировки: utf32le и utf32be. Notepad++ тоже
> не работает с этими кодировками и с utf16 (только ucs2).
>  Поэтому к примеру один из первых моментов, которые хочется
> уточнить - с помощью какого текстового редактора можно создавать
> и модифицировать текстовые файлы в настоящих utf16/32 кодировках.

К вопросу про: "а нафига?"
Ты хоть раз в жизни видел файлы в этих кодировках?
Вот и я нет :)


 
Rouse_ ©   (2014-01-24 22:35) [14]


> 9 из 10 XML файлов используют UTF-8.

+1
Причем последний из десяти используется Win1251


 
Rouse_ ©   (2014-01-24 22:42) [15]

ЗЫ: ну и к вопросу о спецификациях, откуда ты эти все кодировки вычитал. В свое время я занимался реализацией ZIP в виде набора классов FWZip и конечно хотел реализовать спецуху по полной, но вот проблема... А ее никто не поддерживает на все 100, даже сама PKWARE, у них там даже камент есть, мол это все будет юзаться только тогда когда появится реальная необходимость. Нет ни одного архиватора в мире поддерживающего полный функционал по самой последней спецификации ZIP (да даже по пятой) - это наверное тоже звоночек? :)


 
картман ©   (2014-01-25 00:34) [16]

ща договоритесь - через триста постов ветку закроют))


 
DevilDevil ©   (2014-01-25 02:18) [17]

Такой вопрос, на засыпку
В начале файла стоит FF первый байт и FE второй байт
Файл представлен в кодировке utf-16 или ucs2 ?

> Rouse_ ©   (24.01.14 22:42) [15]
> это наверное тоже звоночек? :)

Розыч, я предлагаю сначала разобраться что можно сделать, а потом думать, чем можно пренебречь


 
Германн ©   (2014-01-25 02:21) [18]


> я предлагаю сначала разобраться что можно сделать

Во многих случаях для этого приходится сначала сделать, а уж потом разбираться.


 
DevilDevil ©   (2014-01-25 02:37) [19]

> DVM ©   (24.01.14 22:33) [12]
> http://www.gnu.org/software/libiconv/

ты сам оттуда что-нибудь пробовал?


 
DVM ©   (2014-01-25 10:38) [20]


> DevilDevil ©   (25.01.14 02:37) [19]


> ты сам оттуда что-нибудь пробовал?

Конечно, под системами отличными от Windows это практически единственный вариант для работы с различными кодировками с минимумом усилий. В том же FreePascal она используется. Вот обертка например под FreePascal
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/iconvenc/src/


 
DVM ©   (2014-01-25 10:48) [21]


> DevilDevil ©   (25.01.14 02:18) [17]
> Такой вопрос, на засыпку
> В начале файла стоит FF первый байт и FE второй байт
> Файл представлен в кодировке utf-16 или ucs2 ?

Это одно и то же практически.

http://www.unicode.org/faq/basic_q.html#14


Q: What is the difference between UCS-2 and UTF-16?

A: UCS-2 is obsolete terminology which refers to a Unicode implementation up to Unicode 1.1, before surrogate code points and UTF-16 were added to Version 2.0 of the standard. This term should now be avoided.

UCS-2 does not define a distinct data format, because UTF-16 and UCS-2 are identical for purposes of data exchange. Both are 16-bit, and have exactly the same code unit representation.

Sometimes in the past an implementation has been labeled "UCS-2" to indicate that it does not support supplementary characters and doesn"t interpret pairs of surrogate code points as characters. Such an implementation would not handle processing of character properties, code point boundaries, collation, etc. for supplementary characters. [AF]


 
DVM ©   (2014-01-25 10:57) [22]


> DevilDevil ©

Касательно SAX XML парсера. Я делал такой для одной своей задачи (разумеется частичную реализацию), где надо было обрабатывать поток XML тегов неопределенного размера с максимальной скоростью. В результате пришел к выводу, что SAX XML парсер НЕ ДОЛЖЕН заниматься каким либо перекодированием поступащих данных. Его задача определить кодировку и правильно читать данные. Далее он просто должен выплевывать элементы как RawByteString ничего не трогая. Иначе будет потеря скорости. Кто захочет сам перекодирует.


 
DevilDevil ©   (2014-01-25 13:25) [23]

> DVM ©   (25.01.14 10:57) [22]

> В результате пришел к выводу, что SAX XML парсер НЕ ДОЛЖЕН
> заниматься каким либо перекодированием поступащих данных.
>  Его задача определить кодировку и правильно читать данные.


Скажешь тоже
Допустим парсер ориентирован на кодировку Utf-8
Но пользователь получил XML в формате Utf-16 размером 3Гб

CachedBuffers спроектирована таким образом, чтобы подтягивать новые куски данных по мере надобности. В эту концепцию прекрасно ложатся "промежуточные буферы" или "конверторы". Собственно библиотека на то и рассчитана. В случае если поступающие данные не соответствуют нужной кодировке - просто инициализируем требуемый "конвертор".

Мой SAX-парсер будет принимать Utf8 и Ansi (если все узлы и аттрибуты на латиннице). Но и Utf32be он не должен бояться :)


 
DevilDevil ©   (2014-01-25 14:21) [24]

>> В начале файла стоит FF первый байт и FE второй байт
>> Файл представлен в кодировке utf-16 или ucs2 ?


> Это одно и то же практически.

В том то и дело. Что в случае Utf16 символ может быть представлен 4 байтами, а в Ucs2 только 2мя. Поэтому например код преобразования в Utf8 для каждой из этих кодировок должен отличаться. Вот я и спрашиваю. Если BOM равно FF FE - то это Utf16 или UCS2 ?


 
й   (2014-01-25 14:54) [25]


> UCS-2 is obsolete terminology which refers to a Unicode implementation up to Unicode 1.1


 
clickmaker ©   (2014-01-25 15:21) [26]

> Если BOM равно FF FE - то это

UTF16 LE


 
DVM ©   (2014-01-25 15:59) [27]


> Скажешь тоже
> Допустим парсер ориентирован на кодировку Utf-8
> Но пользователь получил XML в формате Utf-16 размером 3Гб

Я не вижу тут никаких проблем ни с какой кодировкой с хоть 100 тыщ мильонов гигабайт размером файла.


> CachedBuffers спроектирована таким образом, чтобы подтягивать
> новые куски данных по мере надобности. В эту концепцию прекрасно
> ложатся "промежуточные буферы" или "конверторы". Собственно
> библиотека на то и рассчитана. В случае если поступающие
> данные не соответствуют нужной кодировке - просто инициализируем
> требуемый "конвертор".

Фильтры это по умному называется обычно.  Ну флаг тебе в руки.


>  Если BOM равно FF FE - то это Utf16 или UCS2 ?

если bom не указана вообще что думаешь делать? плюс для некоторых кодировок bom совпадает.


 
DevilDevil ©   (2014-01-25 16:53) [28]

> DVM ©   (25.01.14 15:59) [27]
> Я не вижу тут никаких проблем ни с какой кодировкой с хоть
> 100 тыщ мильонов гигабайт размером файла.


Нет, я тоже не вижу проблем. Просто не понимаю, почему ты советуешь отказаться от подхода переконвертации в случае если кодировка отличается от ожидаемой

> Фильтры это по умному называется обычно.  Ну флаг тебе в руки.

фильтры...
может быть
я ещё не придумал итоговое название

> если bom не указана вообще что думаешь делать? плюс для
> некоторых кодировок bom совпадает.


Я тут смотрю как принято устанавливать кодировку. Если BOM нет то смотрится символ "<"... уже на этом этапе теоретически можно понять, какая кодировка.

Если кодировка однобайтовая и не Utf-8 - тогда уже нужно смотреть encoding :)

Оффтоп:
Смотрю исходники NativeXml и хочется плакать. 32битные кодировки не поддерживаются, хоть и определяется BOM на перспективу... но не это самое страшное. Оптимизации... там поле непаханое для оптимизаций....


 
DVM ©   (2014-01-25 17:46) [29]


> DevilDevil ©   (25.01.14 16:53) [28]


> Просто не понимаю, почему ты советуешь отказаться от подхода
> переконвертации в случае если кодировка отличается от ожидаемой

Скорость обработки выше будет и SAX парсер будет более универсальным. Иногда перекодировка не только не требуется, но и вредна. Перекодировать то всегда можно по месту, если известно какая кодировка и дан буфер с данными. Ну вот, например, SAX парсер генерирует события для тегов и аттрибутов, нам нужны только теги, их мы и будем перекодировать по месту, аттрибуты нам не нужны и перекодировать их не надо - не тратим на них ресурсы.


 
DevilDevil ©   (2014-01-25 18:47) [30]

> Скорость обработки выше будет и SAX парсер будет более универсальным.

Дак а за счёт чего?
Я это и пытаюсь понять :)

Исходя из того, что я вижу - парсер в любом случае получает CachedBuffer в нужной кодировке
Какой там путь преобразований проделает буфер - парсеру всё равно


 
DVM ©   (2014-01-25 19:32) [31]


> Какой там путь преобразований проделает буфер - парсеру
> всё равно
Ну при таком подходе, да, все равно. Грузить преобразованиями процессор будет буфер.

Ты реши, что для тебя важнее - универсальность и красота использования или скорость. Универсальный подход при котором строится некий граф фильтров, выдающий на выходе на блюдечке обработанные и преобразованные данные (все без разбору, нужные и ненужные) будет уступать коду, который необходимые преобразования делает по месту и только при необходимости.
Я уж не знаю как еще объяснить. Первый подход хорош в обычных приложениях, второй в highload и big data приложениях. Все это имхо, из опыта моего.


 
DevilDevil ©   (2014-01-25 20:50) [32]

> DVM ©   (25.01.14 19:32) [31]

При всём уважении - не понял :)
Парсер понимает кодировки Utf8 и Ansi. Т.е. самые распространённые
Парсинг осуществляется путём просматривания буфера и тестированием, сколько байт в буфере осталось. Когда буфер заканчивается - вызывается "виртуальная" функция докачки следующего куска памяти в буфер.

Давай задам тогда вопрос по другому. Как модель парсинга спроектировать ещё эффективнее?


 
DevilDevil ©   (2014-01-25 21:29) [33]

А пока актуален следующий вопрос
На данный момент я копаю iconv и пока честно говоря не очень разобрался :)
Но каким образом я выполнял преобразования кодировок раньше.

Я вызывал MultiByteToWideChar для символов от 128 до 255 - таким образом получал таблицу Ansi-->UCS-2. А как такого же результата я могу достичь на других ОС?


 
DevilDevil ©   (2014-01-25 21:32) [34]

Хм...
Смотрю в Delphi7 функцию в модуле Systems
function WCharFromChar(WCharDest: PWideChar; DestChars: Integer; const CharSource: PChar; SrcBytes: Integer): Integer;
{$IFDEF LINUX}
var
 IconvContext: Integer;
{$ENDIF}
begin
{$IFDEF LINUX}
 if (DestChars <> 0) and (SrcBytes <> 0) then
 begin
   IconvContext := iconv_open("UNICODELITTLE", nl_langinfo(_NL_CTYPE_CODESET_NAME));
   if IconvContext = -1 then
     LocaleConversionError;
   try
     Result := BufConvert(WCharDest, DestChars * SizeOf(WideChar), CharSource, SrcBytes,
       IconvContext, 2, CharacterSizeLocaleChar);
   finally
     iconv_close(IconvContext);
   end;
   if Result <> -1 then
     Result := Result div SizeOf(WideChar);
 end
 else
   Result := 0;
{$ENDIF}
{$IFDEF MSWINDOWS}
 Result := MultiByteToWideChar(DefaultUserCodePage, 0, CharSource, SrcBytes,
     WCharDest, DestChars);
{$ENDIF}
end;


Как так? )))


 
Kerk ©   (2014-01-25 22:19) [35]

А что удивляет? Линукс? Так то во время Кайликса было. Первый заход на кроссплатформенность.


 
DVM ©   (2014-01-25 22:32) [36]


> DevilDevil ©   (25.01.14 20:50) [32]
> > DVM ©   (25.01.14 19:32) [31]
>
> При всём уважении - не понял :)
> Парсер понимает кодировки Utf8 и Ansi. Т.е. самые распространённые

Фактически парсеру в таком случае надо понимать только где начинаются и где заканчиваются теги XML, а они как правило содержат символы которые что в UTF-8, что в Ansi имеют одни и те же коды и эти символы однобайтные. Т.е для простоты можно полагать, что парсер работает с текстом в котором все символы - однобайтные. Двух и более байтными могут быть только значения узлов или аттрибутов, разные там CDATA и пр, но их парсеру вовсе не надо перекодировать, он их может выдавать в том виде, в котором они были в исходных данных, если это были данные в UTF-8 значит выдает UTF-8. Кому надо прекодирует значения нужных ему узлов и аттрибутов в ту кодировку, которая ему нужна. Исходная ведь известна.

Другое дело, если кодировка исходного документа, например, Unicode и все символы имеют размер по 2 байта. Я так понимаю, что ты собираешься перекодировать такие данные перед тем как передавать их парсеру? Так?


 
DevilDevil ©   (2014-01-25 22:40) [37]

> Kerk ©   (25.01.14 22:19) [35]
> А что удивляет? Линукс? Так то во время Кайликса было. Первый
> заход на кроссплатформенность.


А там какого-нибудь АПИ из юникода в анси разве нет?
И это... как дело обстоит в маке, иос и ведроде ?

У меня сейчас под рукой только Delphi7


 
DVM ©   (2014-01-25 22:44) [38]


> DevilDevil ©   (25.01.14 21:29) [33]
> А пока актуален следующий вопрос
> На данный момент я копаю iconv и пока честно говоря не очень
> разобрался :)
> Но каким образом я выполнял преобразования кодировок раньше.
>
>
> Я вызывал MultiByteToWideChar для символов от 128 до 255
> - таким образом получал таблицу Ansi-->UCS-2. А как такого
> же результата я могу достичь на других ОС?

Точно так же, можно сэмулировать функцию MultiByteToWideChar как в том же NativeXML сделано, через ICONV или через вот это, например:

https://code.google.com/p/notepas/source/browse/components/tslib/core/CodecUtilsWin32.pas?spec=svn141&r=141


 
DVM ©   (2014-01-25 22:45) [39]


> DevilDevil ©   (25.01.14 22:40) [37]


> А там какого-нибудь АПИ из юникода в анси разве нет?
> И это... как дело обстоит в маке, иос и ведроде ?

Есть там соответствующие функции, но в каждом разные и проще использовать ICONV которая работает везде. Или свой вариант писать нативный.


 
Kerk ©   (2014-01-25 22:48) [40]


> И это... как дело обстоит в маке, иос и ведроде ?

Если верить моему беглому взгляду (мог что-то упустить), то на винде все по-старому, на андроиде используется библиотека ICU (поиск по имени функции ucnv_open вывел на http://site.icu-project.org/), на маке и айосе - iconv.


 
DevilDevil ©   (2014-01-25 23:00) [41]

> DVM ©   (25.01.14 22:32) [36]

> Фактически парсеру в таком случае надо понимать только где
> начинаются и где заканчиваются теги XML, а они как правило
> содержат символы которые что в UTF-8, что в Ansi имеют одни
> и те же коды и эти символы однобайтные. Т.е для простоты
> можно полагать, что парсер работает с текстом в котором
> все символы - однобайтные. Двух и более байтными могут быть
> только значения узлов или аттрибутов, разные там CDATA и
> пр, но их парсеру вовсе не надо перекодировать, он их может
> выдавать в том виде, в котором они были в исходных данных,
>  если это были данные в UTF-8 значит выдает UTF-8. Кому
> надо прекодирует значения нужных ему узлов и аттрибутов
> в ту кодировку, которая ему нужна. Исходная ведь известна.


Примерно так в конечном счёте и будет
Данные парсеру (и соответственно пользователю) поступают данные в кодировке Utf8 или Ansi (если все аттрибуты/узлы/etc) на латиннице.

А тип строки будет определён примерно так:
type
 XmlStringMode = (xsmDecoded, xsmUniversal, xsmEncoded);

 XmlString = packed record
   Data: pointer;
   Size: integer;

   case Integer of
     0: (Flags: integer);
     1: (CodePage: word; Mode: XmlStringMode; __: byte);
 end;


> Другое дело, если кодировка исходного документа, например,
>  Unicode и все символы имеют размер по 2 байта. Я так понимаю,
>  что ты собираешься перекодировать такие данные перед тем
> как передавать их парсеру? Так?


Сам парсер не будет знать, какой была исходная кодировка. Он лишь будет знать, в какой однобайтовой кодировке ему подают данные: в Utf8 или Ansi(CodePage)


 
DVM ©   (2014-01-25 23:10) [42]


> Данные парсеру (и соответственно пользователю) поступают
> данные в кодировке Utf8 или Ansi (если все аттрибуты/узлы/etc)
> на латиннице.

Ну так я об этом и говорил. Просто большинство парсеров что я видел, принудительно перекодируют все значения узлов, что для SAX не очень хорошо.


> Сам парсер не будет знать, какой была исходная кодировка.
>  Он лишь будет знать, в какой однобайтовой кодировке ему
> подают данные: в Utf8 или Ansi(CodePage)
>
>

Т.е где то будет перекодирование.


> А тип строки будет определён примерно так:

FreePascal будешь поддерживать? Там внимательнее с перечислениями надо, они там имеют не такой размер по умолчанию как в делфи.


 
DevilDevil ©   (2014-01-25 23:39) [43]

Офтоп:
Страшно читать чужие исходники где понаписали тысячу файлов :)


> ICONV

Насколько я понял, iconv тем плохо, что поддерживает значительно меньшее количество кодировок, чем виндусовый MultiByteToWideChar. Отсюда надо плясать. Получается количество поддерживаемых страниц ограничивается возможностями iconv. Или нет? ICU кстати всё поддерживает, что есть в iconv?

> Ну так я об этом и говорил. Просто большинство парсеров
> что я видел, принудительно перекодируют все значения узлов,
>  что для SAX не очень хорошо.


Ну они типа делают для удобства. Что конечно отрицательно сказывается на производительности.
Но меня больше веселит другое. Большинство парсингов, которые я видел, принимают на вход кодировку utf16. На мой взгляд абсолютно нелогичное решение. Во-первых, в большинстве случаев придётся весь файл перекодировать (в utf16), во-вторых, распознание символов происходит значительно медленнее. Вон в PugiXml используются компактные таблички на 256 элементов.


 
DevilDevil ©   (2014-01-25 23:40) [44]

> FreePascal будешь поддерживать? Там внимательнее с перечислениями
> надо, они там имеют не такой размер по умолчанию как в делфи.


Да, я с этим уже сталкивался
У меня уже есть шаблон, который я смело ставлю на каждый создаваемый юнит
// compiler options
{$ifdef fpc}
 {$mode delphi}
 {$asmmode intel}
{$endif}
{$V+}{$B-}{$X+}{$T+}{$P+}{$H+}{$J-}{$MINENUMSIZE 1}{$A4}
{$if CompilerVersion >= 15}
 {$WARN UNSAFE_CODE OFF}
 {$WARN UNSAFE_TYPE OFF}
 {$WARN UNSAFE_CAST OFF}
{$ifend}
{$O+}{$R-}{$I-}{$Q-}


 
DevilDevil ©   (2014-01-25 23:49) [45]

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

Вот допустим мы ставим перед собой задачу переконвертировать символ utf16 в символ ansi (windows-1251). И встречается нам какой нибудь французский "a" с загогулькой или немецкие амляуты. Непосредственно этого символа в windows-1251 нет. Но WideCharToMultiByte по идее найдёт "наиболее близкий символ".

Как выглядит этот алгоритм поиска "близкого символа" ?


 
clickmaker ©   (2014-01-25 23:55) [46]

> Как выглядит этот алгоритм поиска "близкого символа" ?

хэш-таблица?
символ с загогулькой -> символ без загогульки


 
DVM ©   (2014-01-26 00:12) [47]


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

Это еще от системы зависит.


> Получается количество поддерживаемых страниц ограничивается
> возможностями iconv. Или нет? ICU кстати всё поддерживает,
>  что есть в iconv?

Недостающее всегда дописать можно.
А вот ICU многие не довольны. Много с ней нюансов говорят. Не java вариант, а тот который сишный.


 
DevilDevil ©   (2014-01-26 00:39) [48]

> хэш-таблица?
> символ с загогулькой -> символ без загогульки


хочешь сказать существует одна хеш-таблица по всем "загогулечным символам" utf16?


 
DevilDevil ©   (2014-01-26 16:35) [49]

Вобщем пока всё сводится к тому, чтобы писать отдельный модуль по конвертациям
Хочется подойти универсально, разбавив функционалом кодирования данных в формате XML (&amp; и т.д.)


 
clickmaker ©   (2014-01-26 17:10) [50]

> одна хеш-таблица по всем "загогулечным символам" utf16?

не по всем. Для несуществующих юзается "default character"


 
DevilDevil ©   (2014-01-26 17:15) [51]

Покажи кодом


 
clickmaker ©   (2014-01-26 17:20) [52]

исходник WideCharToMultiByte?


 
DevilDevil ©   (2014-01-26 20:50) [53]

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

Смотрю исходники iconv - там подход другой
Для каждой кодировки свой функция кодирования и декодирования символа
Со своими персональными таблицами, никаких хешей


 
clickmaker ©   (2014-01-26 21:20) [54]

> Со своими персональными таблицами

ну а кто ж спорит. Для каждой кодировки - своя таблица. Как именно в WideCharToMultiByte организован и оптимизирован поиск соответствий - это уж я не знаю, могу только предполагать


 
DevilDevil ©   (2014-01-29 00:23) [55]

Идём дальше

1) символы за диапазоном $ffff могут быть в верхнем/нижнем регистре или нет?
2) где в стандарте прописан полный список возможных XML-кодировок в атрибуте "encoding"?
3) такое понятие как кодовая страница(номер)... оно уникально для всех платформ или имеются различия?
4) какие ещё классификации кодировок существуют кроме Ansi и Unicode? Как например классифицировать китайский Big5 и прочие непонятности где размер символа не равен 1 байту

Все эти многочисленные непонятности порядком раздражают. Надеюсь хотя бы часть из них вы проясните


 
DevilDevil ©   (2014-01-29 11:07) [56]

Равнодушие хуже ненависти
Ребят, без вашей помощи мне не справиться никак :)


 
й   (2014-01-29 11:46) [57]

> Равнодушие хуже ненависти

ждешь "волшебного пенделя"? ок
взялся за гуж - не говори, что не дюж
назвался груздем (программистом) - полезай в кузов (рфтм спеки, рфц и прочее - всё открыто)
понятно, что чтива много и не особо завлекательного
но реальное программирование - это всегда двухэтапный перевод: человеческий язык -> идея в голове -> код программы
и не всегда первый этап проще, скорее наоборот


 
clickmaker ©   (2014-01-29 12:03) [58]

> какие ещё классификации кодировок существуют кроме Ansi
> и Unicode?

их 3 всего. SBCS, DBCS и MBCS


 
DevilDevil ©   (2014-01-29 12:12) [59]

Я не жду волшебного пенделя
Я жду консультативной помощи того, кто с этими форматами и кодировками уже разбирался
Это минимум, который я ожидаю

Вариант, который бы меня устроил на 4 - это энтузиазм в поиске информации. Ибо цель благая, а задачи поиска информации и проектирования/реализации просто рвут меня на части. В идеале хочется заниматься только вторым.

Я вообще думаю у библиотеки неплохие перспективы войти в недра Delphi, как в свою очередь FastMM и прочие FastCode плюшки. Ибо в кодировках сейчас у них просто полный ахтунг, а особенно в классе TEncoding. Производительность - просто хочется плакать. Функционал тоже скудный. В итоге если твой софт должен работать с текстом - перспективы твои незавидные


 
DevilDevil ©   (2014-01-29 12:20) [60]

> clickmaker ©   (29.01.14 12:03) [58]
> их 3 всего. SBCS, DBCS и MBCS

Какие из представленных кодировок являются DBCS и MBCS?
http://www.gnu.org/software/libiconv/


 
clickmaker ©   (2014-01-29 12:30) [61]

> [60] DevilDevil ©   (29.01.14 12:20)

а сам-то как думаешь? Из буковок DB и MB не понятно?


 
DevilDevil ©   (2014-01-29 12:33) [62]

Я думаю ты не понял вопрос
Про размер примерно понятно
И я не спрашиваю про Unicode-кодировки

я спрашиваю про иные кодировки, обозначенные здесь
http://www.gnu.org/software/libiconv/


 
DVM ©   (2014-01-29 12:44) [63]


> DevilDevil ©   (29.01.14 12:33) [62]


> я спрашиваю про иные кодировки, обозначенные здесь

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


 
DVM ©   (2014-01-29 12:46) [64]


> DevilDevil ©   (29.01.14 12:12) [59]


> Я вообще думаю у библиотеки неплохие перспективы войти в
> недра Delphi, как в свою очередь FastMM и прочие FastCode
> плюшки. Ибо в кодировках сейчас у них просто полный ахтунг,
>  а особенно в классе TEncoding. Производительность - просто
> хочется плакать. Функционал тоже скудный. В итоге если твой
> софт должен работать с текстом - перспективы твои незавидные

Состояние класса TEncoding нормальное и соответствующее нынешним реалиям. Если ты возьмешь аналогичный класс из NET то там функционал примерно такой же и список поддерживаемых кодировок тоже. Реализованы популярные кодировки.


 
DevilDevil ©   (2014-01-29 13:05) [65]

> Гуглишь название каждой, читаешь описание. Мне не понятен
> вопрос. Там сотня кодировок, по каждой надо написать сюда
> какие из них мультибайтный, какие однобайтные и т.д.?


Во-первых, не сотня
Во-вторых, большинство однобайтные
В-третьих, юникодовые не касаемся

Получается под категорию DBCS и MBCS попадает всего несколько (классов) кодировок. Я хочу знать какие
Кроме того по идее кто сталкивался с DBCS и MBCS - может прояснить ситуацию.

> Состояние класса TEncoding нормальное и соответствующее
> нынешним реалиям. Если ты возьмешь аналогичный класс из
> NET то там функционал примерно такой же и список поддерживаемых
> кодировок тоже. Реализованы популярные кодировки.


А я и не сказал, что отвратительное. Если ты работаешь только с UnicodeString и файлами до 1Мб - то функционала вполне может хватить. Но копни глубже, до уровня например UTF32 - и всё. Увеличь размер до 100Мб Utf8 - и всё. Поставь задачу реализовать частично функционал Notepad++ - и всё. Захотел распознать encoding в XML-документе - и всё.

Я не говорю, что отвратительно. Я говорю, что можно и нужно значительно лучше


 
DVM ©   (2014-01-29 13:27) [66]


> DevilDevil ©   (29.01.14 13:05) [65]


> Во-первых, не сотня

Даже больше, посчитай сам.


> В-третьих, юникодовые не касаемся

А юникодная не может быть DBCS ?


> Получается под категорию DBCS и MBCS попадает всего несколько
> (классов) кодировок. Я хочу знать какие
> Кроме того по идее кто сталкивался с DBCS и MBCS - может
> прояснить ситуацию.

Да все сталкивались, но сталкивались с конкретными, а не со всеми сразу.


> Если ты работаешь только с UnicodeString и файлами до 1Мб
> - то функционала вполне может хватить. Но копни глубже,
> до уровня например UTF32 - и всё. Увеличь размер до 100Мб
> Utf8 - и всё.

Опять ты хочешь сделать серебрянную пулю на все случаи жизни. Тебе дан механизм, делай расширение по образцу, используй готовые примитивы.
Сделать свои классы кодировок по аналогии с TEncoding и зарегистрировать - не проблема, размер файла - читай поблочно и декодируй  - тоже не проблема. Notepad++ тоже ведь сделан не на базе какого то супер-пупер готового и волшебного компонента, кто-то же это запрограммировал. Кому надо запрограммирует и в своем коде.


 
DevilDevil ©   (2014-01-29 14:27) [67]

124 :)

> А юникодная не может быть DBCS ?
может
просто с ними всё понятно

> Опять ты хочешь сделать серебрянную пулю на все случаи жизни.
>  Тебе дан механизм, делай расширение по образцу, используй
> готовые примитивы.
> Сделать свои классы кодировок по аналогии с TEncoding и
> зарегистрировать - не проблема, размер файла - читай поблочно
> и декодируй  - тоже не проблема. Notepad++ тоже ведь сделан
> не на базе какого то супер-пупер готового и волшебного компонента,
>  кто-то же это запрограммировал. Кому надо запрограммирует
> и в своем коде.


Программист тем хорош, что может спроектировать и реализовать быстрое удобное универсальное решение
Конечно нужно прикидывать какую ценность будет иметь то или иное вложение. Но это не значит, что данное направление нет необходимости проработать.

На данном этапе я собираю информацию. И я прошу помочь хотя бы с ней
В [55] я же не только про SBCS/DBCS/MBCS спросил. Но это тоже информация и я за неё благодарен


 
clickmaker ©   (2014-01-29 14:47) [68]

> быстрое удобное универсальное

выберите любые 2


 
DevilDevil ©   (2014-01-29 15:06) [69]

я выжму 2.5
вопрос только от чего эти 0.5 отнимутся
я думаю 0.05 от "быстрое", 0.05 от "удобное" и 0.4 от "универсальное"


 
DevilDevil ©   (2014-01-30 15:54) [70]

Не могу понять, где под не-Windows заполняется DefaultSystemCodePage
В Windows понятно - GetACP()
А как в других ОС?


 
DevilDevil ©   (2014-01-30 16:30) [71]

И ещё вопрос по class helper
Вот есть класс TEncoding
У него есть метод:
class function GetBufferEncoding(const Buffer: TBytes; var AEncoding: TEncoding;
     ADefaultEncoding: TEncoding): Integer; overload; static;


Средствами class helper я могу "перехватить" (переопределить) эту функцию или нет?


 
Kerk ©   (2014-01-30 16:35) [72]

С помощью RTTI можешь


 
DevilDevil ©   (2014-01-30 16:39) [73]

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


 
Kerk ©   (2014-01-30 16:43) [74]


> Слушаю как

http://docwiki.embarcadero.com/Libraries/XE5/en/System.Rtti.TVirtualMethodInterceptor
Появилось в Delphi XE


 
DevilDevil ©   (2014-01-30 16:45) [75]

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


 
Kerk ©   (2014-01-30 16:50) [76]


> Во-первых, ты не сказал, как пользовать

Я могу конечно текст справки и код примера сюда скопировать, но смысл?

> Во-вторых, метод то не виртуальный

Это я проглядел, да. Не тот случай. Тогда без грязных хаков никак, думаю.


 
DevilDevil ©   (2014-01-30 16:53) [77]

я жмакаю по "Code Examples" - чёт он меня никуда не перенаправляет
офтоп: мда, первый раз когда я пользуюсь хелпером - заставляет меня чуть-чуть в нём разочароваться :)

Ok.
Возвращаемся к другому вопросу
Как определяется DefaultSystemCodePage в не-Windows системах?


 
Kerk ©   (2014-01-30 16:57) [78]


> я жмакаю по "Code Examples" - чёт он меня никуда не перенаправляет

Вот тут примерно то же самое
http://blog.barrkel.com/2010/09/virtual-method-interception.html


 
DevilDevil ©   (2014-01-30 17:02) [79]

> DVM ©   (29.01.14 13:27) [66]
> Сделать свои классы кодировок по аналогии с TEncoding и
> зарегистрировать - не проблема


Кстати забавный этот TEncoding
С одной стороны действительно много вещей продумали. И SingleByte, и MBCS, а в strict private уже объявлены:
   class var
     FANSIEncoding: TEncoding;
     FASCIIEncoding: TEncoding;
     FBigEndianUnicodeEncoding: TEncoding;
     FUnicodeEncoding: TEncoding;
     FUTF7Encoding: TEncoding;
     FUTF8Encoding: TEncoding;
   class function GetANSI: TEncoding; static;
   class function GetASCII: TEncoding; static;
   class function GetBigEndianUnicode: TEncoding; static;
   class function GetDefault: TEncoding; static; inline;
   class function GetUnicode: TEncoding; static;
   class function GetUTF7: TEncoding; static;
   class function GetUTF8: TEncoding; static;


Но вот беда
Код GetBufferEncoding заточен только на UTF8, UCS2 и UCSbe
И функционала как "зарегистрировать" кодировку - просто нет


 
DevilDevil ©   (2014-01-30 17:03) [80]

> Вот тут примерно то же самое
> http://blog.barrkel.com/2010/09/virtual-method-interception.html


понятно


 
DevilDevil ©   (2014-01-30 17:18) [81]

Ребят, это полный ахтунг!!!!!!!!!!!

Под ведроидом не то что Utf8String нет, там ни AnsiString нет, ни даже AnsiChar
как так?
что за фигня?


 
Kerk ©   (2014-01-30 17:20) [82]

Доброе утро. Ты в спячке чтоль был? Там один тип строк - string, он же UnicodeString.

Для всего остального есть TBytes.


 
Kerk ©   (2014-01-30 17:22) [83]

Предупреждая следующий шок - строки на андроиде и ios индексируются не с единицы, а с нуля.


 
Kerk ©   (2014-01-30 17:22) [84]

Короче вот тебе слайды (минутка самопиара:)
http://www.slideshare.net/VLDCORP/ios-android-delphi


 
DVM ©   (2014-01-30 17:36) [85]


> DevilDevil ©   (30.01.14 17:02) [79]


> И функционала как "зарегистрировать" кодировку - просто
> нет

Достаточно наследников насоздавать от TEncoding и все. В принципе даже и в TEncoding можно добавить недостающие поля - class helper можно сделать.


> Код GetBufferEncoding заточен только на UTF8, UCS2 и UCSbe

Метод виртуальный же


 
DVM ©   (2014-01-30 17:39) [86]


> Kerk ©   (30.01.14 17:20) [82]

А указатели там есть, надеюсь?


 
Kerk ©   (2014-01-30 17:46) [87]

Есть указатели, куда они денутся.


 
DevilDevil ©   (2014-01-30 17:50) [88]

Я в шоке по нескольким причинам
Настолько подавлен, что не могу структурированно изложить мысли
Но сейчас постараюсь

1) Кроссплатформ RAD Studio - гуд
2) Мобильное направление RAD Studio - вэри гуд
3) Slow compile and big binary size - вэри бэд
4) Кинул на форму Memo и пару кнопок. По нажатию одной кнопки сделал Memo1.Lines.Text := "Тестовая строка". Запустил, поиграл пару секунд, получил Exception. Это полный п.
5) Рассогласованность компиляторов на уровне типов и доступа к строкам - это полное зло
6) Полный отказ от поддержки не-UCS2 строк бессмыслен
7) Подсчёт ссылок - подход привлекательный, но надеюсь его уберут
8) Мне на 55% нравится, куда идёт Эмбар. Но есть вещи, которые бьют меня прямо в сердце

P.S. я думал в RTL всё сводится к UnicodeString, но поддержка сохраняется. Оказалось нет. Про остальное знал. А презентация действительно хорошая!


 
DevilDevil ©   (2014-01-30 17:52) [89]

> Метод виртуальный же

class function static

> Достаточно наследников насоздавать от TEncoding и все. В
> принципе даже и в TEncoding можно добавить недостающие поля
> - class helper можно сделать.


Memo1.Lines.LoadFromFile() в конечном счёте вызывает TEncoding.GetBufferEncoding, с которым ты уже ничего не сделаешь


 
DVM ©   (2014-01-30 18:01) [90]


> DevilDevil ©   (30.01.14 17:52) [89]


> class function static

посмотрел, да, точно не виртуальный.


 
Kerk ©   (2014-01-30 18:03) [91]


> Рассогласованность компиляторов на уровне типов и доступа
> к строкам - это полное зло

Пошли по пути Python"а. Там тоже 5 лет назад произошло то же самое. Ничем хорошим не закончилось, правда. До сих пор большинство на полностью юникодную версию не перешло. Посмотрим как это получится в Embarcadero.

Мне по большому счету пофиг, но не вижу причин почему было не оставить AnsiString, кому оно мешала-то.

> P.S. я думал в RTL всё сводится к UnicodeString, но поддержка
> сохраняется. Оказалось нет.

Юмор в том, что все наоборот. Глубоко внутри RTL есть разные типы строк, а снаружи только UnicodeString. В сети описывали хаки, позволяющие получить доступ к разным типам строк и из обычного кода.


 
DVM ©   (2014-01-30 18:10) [92]


> DevilDevil ©   (30.01.14 17:52) [89]


> Memo1.Lines.LoadFromFile() в конечном счёте вызывает TEncoding.
> GetBufferEncoding, с которым ты уже ничего не сделаешь

GetBufferEncoding будет же вызываться только тогда, когда явно не указана кодировка, и он будет искать преамбулы для нескольких известных ему кодировок, пытаясь определить какая. Но если кодировка указана, то он будет использовать ее метод GetPreamble, который у каждой кодировки может быть свой. По-моему все нормально.


 
DevilDevil ©   (2014-01-30 18:15) [93]

посмотрел чем инициализируется DefaultSystemCodePage в ведроиде
1251 :)
блин, а где он инициализируется?


 
vuk ©   (2014-01-30 18:54) [94]

to Kerk ©   (30.01.14 18:03) [91]:

> Юмор в том, что все наоборот. Глубоко внутри RTL есть разные
> типы строк, а снаружи только UnicodeString. В сети описывали
> хаки, позволяющие получить доступ к разным типам строк и
> из обычного кода.

Напомнило старые добрые времена. Компилятор Delphi 1 умел собирать exe-шники под DOS, у Borland был RTL, но они его никому не давали, хотя сами пользовались. Но путем срещивания RTL от BP, Delphi 1 и некоторого ручного кодинга можно было получать вполне живущие приложения под DOS.


 
ТНЕ картман   (2014-01-30 19:52) [95]


> DevilDevil ©   (30.01.14 17:02) [79]


> Но вот беда
> Код GetBufferEncoding заточен только на UTF8, UCS2 и UCSbe
> И функционала как "зарегистрировать" кодировку - просто
> нет

предположу, что это сделано исключительно в целях уменьшения размера экзешника))

ЗЫ. если не затруднит, приведи пример чего-нибудь идеального.


 
DevilDevil ©   (2014-01-30 21:21) [96]

> DVM ©   (30.01.14 18:10) [92]

> GetBufferEncoding будет же вызываться только тогда, когда
> явно не указана кодировка, и он будет искать преамбулы для
> нескольких известных ему кодировок, пытаясь определить какая.
>  Но если кодировка указана, то он будет использовать ее
> метод GetPreamble, который у каждой кодировки может быть
> свой. По-моему все нормально.


При всём уважении, не могу понять, зачем ты споришь. Этого функционала нет. Универсального подбора преамбулы для TEncoding нет. Базовые кодировки объявлены, но GetBufferEncoding их не проверяет. К тому же объявлены они как strict private и доступа к ним тоже нет. Складывается впечатление, что этот класс разрабатывал ты - и сейчас защищаешь свой труд от моих нападок. Слишком забавно :)


 
DevilDevil ©   (2014-01-30 21:23) [97]

> ТНЕ картман   (30.01.14 19:52) [95]

Текущий вопрос - каким именно способом и где Delphi определяет DefaultSystemCodePage в не-Windows ОС.
Философствовать могут все, но это сейчас нужно меньше всего. Давай придерживаться объявленных вопросов. Если конечно тема кодировок тебе интересна


 
ТНЕ картман   (2014-01-30 21:48) [98]


>  DevilDevil ©   (30.01.14 21:23) [97]
>
> > ТНЕ картман   (30.01.14 19:52) [95]
>
> Текущий вопрос - каким именно способом и где Delphi определяет
> DefaultSystemCodePage в не-Windows ОС.


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


 
DevilDevil ©   (2014-01-30 21:56) [99]

Тогда создай другую ветку и не гадь в мою


 
DVM ©   (2014-01-30 22:05) [100]


> DevilDevil ©   (30.01.14 21:21) [96]


> При всём уважении, не могу понять, зачем ты споришь. Этого
> функционала нет. Универсального подбора преамбулы для TEncoding
> нет. Базовые кодировки объявлены, но GetBufferEncoding их
> не проверяет.

Я тут не вижу предмета для спора. Я не понимаю о чем ты говоришь. Да, базовые кодировки объявлены. И GetBufferEncoding вызывает поочередно их метод GetPreamble, получая их преамбулу и сравнивает с тем что есть. Вот же. Проверяет все кодировки которые реализованы и которые имеют преамблу в принципе. Их всего 3 там таких:


if AEncoding = nil then
 begin
   // Find the appropraite encoding
   if ContainsPreamble(Buffer, TEncoding.UTF8.GetPreamble) then
     AEncoding := TEncoding.UTF8
   else if ContainsPreamble(Buffer, TEncoding.Unicode.GetPreamble) then
     AEncoding := TEncoding.Unicode
   else if ContainsPreamble(Buffer, TEncoding.BigEndianUnicode.GetPreamble) then
     AEncoding := TEncoding.BigEndianUnicode
   else
   begin
     AEncoding := ADefaultEncoding;
     Exit; // Don"t proceed just in case ADefaultEncoding has a Preamble
   end;
   Result := Length(AEncoding.GetPreamble);
 end


Единственное, что плохо, так это то, что просто так не добавить в список кодировок, преамбула которых сравнивается с текущей еще свою собственную. Про преамбулу UTF-7 (которая тоже реализована) не забыли, а намеренно не стали делать, т.к. она не одна,  а их четыре.


 
DVM ©   (2014-01-30 22:25) [101]


> DevilDevil ©   (30.01.14 21:23) [97]
> > ТНЕ картман   (30.01.14 19:52) [95]
>
> Текущий вопрос - каким именно способом и где Delphi определяет
> DefaultSystemCodePage в не-Windows ОС.

В модуле System.pas определена же функция

function GetACP: Cardinal;

Для Posix систем.

И соответственно DefaultSystemCodePage := GetACP;


 
DevilDevil ©   (2014-01-30 22:44) [102]

> DVM ©   (30.01.14 22:05) [100]

Давай рассуждать последовательно

1) TEncoding - неплохо спроектированный класс, предназначенный для разруливания ситуаций, связанных с переконвертированием кодировок, коих очень много
2) Теоретически поддерживаются чуть ли не все кодировки. И юникодовые, и Ansi, и OEM, и Маковские, и однобайтовые, и мультибайтовые... Причём поддерживать эти кодировки не сложно. TEncoding лишь является враппером над WideCharToMultibyte/libiconv/ICU.
3) Создание кодировок потокобезопасно и без блокировок (lock-free), что разумеется плюс
4) Для определения(создания) кодировки существует классовая функция GetBufferEncoding, которая анализирует BOM
5) Идентификация BOM происходит универсальным способом - путём вызова виртуальной функции GetPreamble() по каждой кодировке и её сравнения с буфером
6) Текстовые классы типа TStrings при загрузке из Stream/Файла вызывают универсальную TEncoding.GetBufferEncoding() - что правильно
7) Внутри класса уже объявлены ANSIEncoding, ASCIIEncoding, BigEndianUnicodeEncoding, UnicodeEncoding, UTF7Encoding, UTF8Encoding
8) BOM проверяется только по 3м из них. В то время как BOM может указывать и на ряд других кодировок:
http://ru.wikipedia.org/wiki/Маркер_последовательности_байтов
http://www.w3.org/TR/REC-xml/#sec-guessing
9) UTF-32, как и UTF-8, если не ошибаюсь, является стандартной кодировкой в POSIX. Но в классе TEncoding он не отражён
10) Не существует практической возможности "научить" TEncoding понимать другие BOM-ы

Bonus:
Я конечно не профи по UTF-7, но по моему его можно определить по последовательности 2B 2F 76


 
DevilDevil ©   (2014-01-30 22:46) [103]

> DVM ©   (30.01.14 22:25) [101]

> В модуле System.pas определена же функция
> function GetACP: Cardinal;
> Для Posix систем.
> И соответственно DefaultSystemCodePage := GetACP;


Хорошо если так
Меня сегодня по этой функции перенаправляли в Windows :)
Завтра посмотрю
Спасибо :)


 
ТНЕ картман   (2014-01-30 23:03) [104]


> 10) Не существует практической возможности "научить" TEncoding
> понимать другие BOM-ы

как это не существует?


 
DVM ©   (2014-01-30 23:12) [105]


> DevilDevil ©

Ты я смотрю по всем фронтам атакуешь:
http://www.sql.ru/forum/1072968/razbiraemsya-v-kodirovkah

Кстати, вот может пригодится (TUTF32Encoding):
https://code.google.com/p/delphi-foundations/source/browse/trunk/Book/05.+String+handling/TEncoding/CCR.Encodings.pas?r=32


 
DevilDevil ©   (2014-01-30 23:22) [106]

> Ты я смотрю по всем фронтам атакуешь:
> http://www.sql.ru/forum/1072968/razbiraemsya-v-kodirovkah


Ну да :)
А что ещё остаётся :)

> Кстати, вот может пригодится (TUTF32Encoding):https://code.
> google.com/p/delphi-foundations/source/browse/trunk/Book/05.
> +String+handling/TEncoding/CCR.Encodings.pas?r=32


Неплохое решение
Но то, что там есть мне уже известно
Завтра по плану мучать ведроид и разбираться с UTF-7
Смысла его поддерживать особого нет. Но каприз у меня такой. Пока хочется


 
DevilDevil ©   (2014-01-31 11:46) [107]

Кстати про лок-фри
Как дифайнами определить, поддерживаются ли атомики типа AtomicCmpExchange?


 
Kerk ©   (2014-01-31 12:33) [108]

Что конкретно определять-то?

Версию компилятора?
{$IF CompilerVersion >= XXX}

{$IFEND}


Винду?
{$IFDEF MSWINDOWS}

{$ENDIF}


 
DevilDevil ©   (2014-01-31 12:42) [109]

А винда то здесь причём?
AtomicCmpExchange это интринсинк
По идее можно отталкиваться от версии компилятора, но какой?
Кроме того... в FPC есть этот интринсинк?


 
DVM ©   (2014-01-31 13:21) [110]


> Кроме того... в FPC есть этот интринсинк?

есть, под всеми платформами есть.


 
DevilDevil ©   (2014-01-31 14:13) [111]

Круто
Осталось понять, с какой версии CompilerVersion они появились в Delphi :)

> DVM ©   (31.01.14 13:21) [110]
> есть, под всеми платформами есть.

Получается Emba спёрла из FPC?
Круто чё :)
А синтаксис то такой же?


 
DVM ©   (2014-01-31 14:52) [112]


> DevilDevil ©   (31.01.14 14:13) [111]


> Получается Emba спёрла из FPC?
> Круто чё :)

Чего сперла? InterlockedXXX функции? Они там давным давно есть. Причем они есть как в Windows (в kernel32), так и самописные (TInterlocked).

Из FPC:

function InterLockedIncrement (var Target: longint) : longint; public name "FPC_INTERLOCKEDINCREMENT";
function InterLockedDecrement (var Target: longint) : longint; public name "FPC_INTERLOCKEDDECREMENT";
function InterLockedExchange (var Target: longint;Source : longint) : longint; public name "FPC_INTERLOCKEDEXCHANGE";
function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; public name "FPC_INTERLOCKEDEXCHANGEADD";
function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; public name "FPC_INTERLOCKEDCOMPAREEXCHANGE";
{$ifdef cpu64}
function InterLockedIncrement64 (var Target: int64) : int64; public name "FPC_INTERLOCKEDINCREMENT64";
function InterLockedDecrement64 (var Target: int64) : int64; public name "FPC_INTERLOCKEDDECREMENT64";
function InterLockedExchange64 (var Target: int64;Source : int64) : int64; public name "FPC_INTERLOCKEDEXCHANGE64";
function InterLockedExchangeAdd64 (var Target: int64;Source : int64) : int64; public name "FPC_INTERLOCKEDEXCHANGEADD64";
function InterlockedCompareExchange64(var Target: int64; NewValue: int64; Comperand: int64): int64; public name "FPC_INTERLOCKEDCOMPAREEXCHANGE64";
{$endif cpu64}
{ Pointer overloads }
{$ifdef cpu64}
function InterLockedIncrement (var Target: Pointer) : Pointer; external name "FPC_INTERLOCKEDINCREMENT64";
function InterLockedDecrement (var Target: Pointer) : Pointer; external name "FPC_INTERLOCKEDDECREMENT64";
function InterLockedExchange (var Target: Pointer;Source : Pointer) : Pointer; external name "FPC_INTERLOCKEDEXCHANGE64";
function InterLockedExchangeAdd (var Target: Pointer;Source : Pointer) : Pointer; external name "FPC_INTERLOCKEDEXCHANGEADD64";
function InterlockedCompareExchange(var Target: Pointer; NewValue: Pointer; Comperand: Pointer): Pointer; external name "FPC_INTERLOCKEDCOMPAREEXCHANGE64";
{$else cpu64}
function InterLockedIncrement (var Target: Pointer) : Pointer; external name "FPC_INTERLOCKEDINCREMENT";
function InterLockedDecrement (var Target: Pointer) : Pointer; external name "FPC_INTERLOCKEDDECREMENT";
function InterLockedExchange (var Target: Pointer;Source : Pointer) : Pointer; external name "FPC_INTERLOCKEDEXCHANGE";
function InterLockedExchangeAdd (var Target: Pointer;Source : Pointer) : Pointer; external name "FPC_INTERLOCKEDEXCHANGEADD";
function InterlockedCompareExchange(var Target: Pointer; NewValue: Pointer; Comperand: Pointer): Pointer; external name "FPC_INTERLOCKEDCOMPAREEXCHANGE";
{$endif cpu64}
{ unsigned overloads }
function InterLockedIncrement (var Target: cardinal) : cardinal; external name "FPC_INTERLOCKEDINCREMENT";
function InterLockedDecrement (var Target: cardinal) : cardinal; external name "FPC_INTERLOCKEDDECREMENT";
function InterLockedExchange (var Target: cardinal;Source : cardinal) : cardinal; external name "FPC_INTERLOCKEDEXCHANGE";
function InterLockedExchangeAdd (var Target: cardinal;Source : cardinal) : cardinal; external name "FPC_INTERLOCKEDEXCHANGEADD";
function InterlockedCompareExchange(var Target: cardinal; NewValue: cardinal; Comperand: cardinal): cardinal; external name "FPC_INTERLOCKEDCOMPAREEXCHANGE";
{$ifdef cpu64}
function InterLockedIncrement64 (var Target: qword) : qword; external name "FPC_INTERLOCKEDINCREMENT64";
function InterLockedDecrement64 (var Target: qword) : qword; external name "FPC_INTERLOCKEDDECREMENT64";
function InterLockedExchange64 (var Target: qword;Source : qword) : qword; external name "FPC_INTERLOCKEDEXCHANGE64";
function InterLockedExchangeAdd64 (var Target: qword;Source : qword) : qword; external name "FPC_INTERLOCKEDEXCHANGEADD64";
function InterlockedCompareExchange64(var Target: qword; NewValue: qword; Comperand: qword): int64; external name "FPC_INTERLOCKEDCOMPAREEXCHANGE64";
{$endif cpu64}  


 
DevilDevil ©   (2014-01-31 14:59) [113]

> DVM ©   (31.01.14 14:52) [112]

Не Interlocked, а Atomic
Это inline-функция (интринсинк), который на x86/x64 выдаёт lock cmpxchg


 
DVM ©   (2014-01-31 15:07) [114]


> DevilDevil ©   (31.01.14 14:59) [113]


> Не Interlocked, а Atomic

А есть разница?

class function TInterlocked.CompareExchange(var Target: Pointer; Value: Pointer; Comparand: Pointer): Pointer;
{$IFDEF X64ASM}
asm
 .NOFRAME
 MOV  RAX,R8
 LOCK CMPXCHG [RCX],RDX
end;
{$ELSE !X64ASM}
{$IFDEF X86ASM}
asm
 XCHG EAX,EDX
 XCHG EAX,ECX
 LOCK CMPXCHG [EDX],ECX
end;
{$ENDIF X86ASM}
{$ENDIF !X64ASM}


 
DevilDevil ©   (2014-01-31 15:46) [115]

> DVM ©   (31.01.14 15:07) [114]

Конечно есть разница
Atomic это инлайн, а в FPC обычная функция :)

Ну а если серьёзно - в коде я буду вызывать функцию AtomicCmpExchange
Следовательно если ещё в ЯП нет - то её нужно эмулировать
Вот я и думаю, через какие опции компилятора это делается

Раз ты говоришь про Interlocked - делаю предположение, что Atomic в FPC тоже нет


 
DVM ©   (2014-01-31 15:53) [116]


> DevilDevil ©   (31.01.14 15:46) [115]
> > DVM ©   (31.01.14 15:07) [114]
>
> Конечно есть разница
> Atomic это инлайн, а в FPC обычная функция :)

В твоем случае какая разница? И то и другое позволит создать класс кодировки потокобезопасно и без блокировок.
Тебе ж ее один раз вызвать и забыть, какая разница инлайн - не инлайн?
В делфи кстати некоторые Interlocked тоже инлайн. Правда в делфи иногда такой инлайн получается - лучше бы его не было.


 
DVM ©   (2014-01-31 15:57) [117]


> Раз ты говоришь про Interlocked - делаю предположение, что
> Atomic в FPC тоже нет

Я не нашел, я Interlocked имел в виду


 
DevilDevil ©   (2014-01-31 16:00) [118]

Ну там типа смайл был потому, что это шутка
Но не без доли правды :)

Разницы конечно нет
Разница лишь в том, что Atomic под FPC не скомпилируется. Как и под старыми версиями Delphi. И с этим надо что-то делать

Я спросил, на какой дифайн заложиться
Кто знает, в какой версии Delphi они появились?


 
DVM ©   (2014-01-31 16:03) [119]


> Кто знает, в какой версии Delphi они появились?

AtomicCmpExchange? В XE3 по всей видимости, так там она есть, а в XE2 нету.
Но я не исключаю, что и раньше была, просто название другое было.


 
DevilDevil ©   (2014-01-31 17:09) [120]

Вот что получилось :)
(кому надо)

{$if Defined(FPC) or (CompilerVersion < 24)}
function AtomicCmpExchange(var Target: Pointer; NewValue: Pointer; Comparand: Pointer): Pointer;
{$if (not Defined(CPUX86)) and (not Defined(CPUX64))}
begin
 {$if Defined(FPC) or Defined(MSWINDOWS)}
   Result := InterlockedCompareExchange(Target, NewValue, Comparand);
 {$else}
   {$message warn "not thread safety"}
   Result := Target;
   if (Result = Comparand) then Target := NewValue;
 {$ifend}
end;
{$ifend}
{$ifdef CPUX86}
asm
 xchg eax, ecx
 lock cmpxchg [ecx], edx
end;
{$endif}
{$ifdef CPUX64}
asm
 mov rax, r8
 lock cmpxchg [rcx], rdx
end;
{$endif}
{$ifend}


 
DevilDevil ©   (2014-02-02 04:01) [121]

Определён список кодировок, которые надо бы поддерживать
Надеюсь получится
В английском я не асс, поэтому если что - корректируйте. Но не увлекайтесь

type
 // unicode mode
 TUniConvUnicode = (// most used
                    ucuNone{SBCS/MBCS: AnsiChar, AnsiString},
                    ucuUCS2{WideChar, WideString, UnicodeString},
                    ucuUtf8{Utf8Char, Utf8String},
                    // another supported unicode
                    ucuUtf7,ucuUtf16,ucuUtf16be,ucuUtf32,ucuUtf32be,ucuUCS_2143,ucuUCS_3412);

{  ------------------- SUPPORTED NON-UNICODE ENCODINGS ----------------------  }
(*
    ANSI Code Pages(may be returned by Windows.GetACP):
        874 – Thai
        1250 – Central and East European Latin
        1251 – Cyrillic
        1252 – West European Latin
        1253 – Greek
        1254 – Turkish
        1255 – Hebrew
        1256 – Arabic
        1257 – Baltic
        1258 – Vietnamese

    Another (multy-byte) encodings, that may be specified as default in POSIX systems:
        932 - Japanese (shift_jis)
        936 - Simplified Chinese (gb2312)
        949 - Korean (ks_c_5601-1987)
        950 - Traditional Chinese (big5)

    Single-byte encodings, that also can be defined as "encoding" in XML/HTML:
        866 - Cyrillic (OEM)
        28592 - Central European (iso-8859-2)
        28593 - Latin 3 (iso-8859-3)
        28594 - Baltic (iso-8859-4)
        28595 - Cyrillic (iso-8859-5)
        28596 - Arabic (iso-8859-6)
        28597 - Greek (iso-8859-7)
        28598 - Hebrew (iso-8859-8)
        28599 - Turkish (iso-8859-9)
        28600 - Nordic (iso-8859-10)
        28603 - Estonian (iso-8859-13)
        28604 - Celtic (iso-8859-14)
        28605 - Latin-9 (iso-8859-15)
        28606 - South-Eastern European (iso-8859-16)
        20866 - Cyrillic (koi8-r)
        21866 - Ukrainian (koi8-u)
        10000 - Western European (Mac)
        10007 - Cyrillic (Mac)

    Multy-byte encodings, that also can be defined as "encoding" in XML/HTML:
        54936 - Simplified Chinese (gb18030)
        52936 - Simplified Chinese (hz-gb-2312)
        20932 - Japanese (euc-jp)
        50220 - Japanese with no halfwidth Katakana (iso-2022-jp)
        51949 - EUC Korean (euc-kr)
*)


 
DVM ©   (2014-02-02 10:20) [122]


> DevilDevil ©   (31.01.14 17:09) [120]

ты начиная с какой Delphi будешь поддерживать? Мне кажется вот такие:
{$if Defined(FPC) or Defined(MSWINDOWS)} появились не так уж и давно.

Defined() имеется в виду и OR / AND в дефайнах.


 
DevilDevil ©   (2014-02-02 12:28) [123]

> DVM ©   (02.02.14 10:20) [122]

С 6й версии
Вроде там нормально поддерживается Defined


 
Незнакомец   (2014-02-06 12:51) [124]

Исходя из моего опыта использования iconv - могу сказать, что это лажа
Для той же самой кодировки 1252 например iconv лагает на символах #129,#141,#143,#144,#157
Ожидал лучшего качества


 
Незнакомец   (2014-02-06 16:15) [125]

хотя... в вики вот что пишут:

According to the information on Microsoft"s and the Unicode Consortium"s websites, positions 81, 8D, 8F, 90, and 9D are
unused; however, the Windows API MultiByteToWideChar maps these to the corresponding C1 control codes.



Страницы: 1 2 3 4 вся ветка

Форум: "Прочее";
Текущий архив: 2014.09.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.89 MB
Время: 0.006 c
15-1390470681
ВладОшин
2014-01-23 13:51
2014.09.14
WebSocket/ Хочу перепилить idHttpServer или что другое


2-1381834603
v1.0
2013-10-15 14:56
2014.09.14
множество


15-1391718602
Юрий
2014-02-07 00:30
2014.09.14
С днем рождения ! 7 февраля 2014 пятница


15-1391758562
АндрейК
2014-02-07 11:36
2014.09.14
DelphiX


15-1390751141
Дмитрий СС
2014-01-26 19:45
2014.09.14
Пользуетесь ли вы absolute?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский