LINUX.ORG.RU

История изменений

Исправление SZT, (текущая версия) :

Здесь нет возможности чтения из потока + чтения из буфера в памяти - только из буфера в памяти.

Значит надо читать поток в буфер, и потом уже разбирать его

Грузить все сразу в память - это иногда совсем не вариант (например, большие архивы или какой-нибудь 50-гигабайтный образ диска)

Можно использовать отображение файла в память (mmap в *nix, MapViewOfFile в виндах) и тогда никаких проблем. Это уже будет забота ОС с ее механизмом подкачки.

Typecasting в struct - плохая идея, как минимум нужна куча опций упаковки

Тут не происходит прямого typecasting в struct, тут через memcpy в структуру загружается часть входного буфера (кстати этот memcpy вполне можно заменить чем-то другим, например чтением из Unix domain socket и тогда можно читать из некоего потока, а не из буфера в памяти). Если мы по условию не можем опираться на всякие #pragma pack для «уплотнения» структур, то придется от структур как таковых вообще отказаться, и делать memcpy прямо в тип нужной битности (прямой каст указателя и разыменование с unaligned read это UB)

Самое главное - не получилось как такового API доступа к данным. Скажем, в любой из библиотек, сгенеренных KS сейчас, можно написать что-то типа `gif.block[1234]` и мы получим объект блока по порядковому номеру. Можно написать `gif.global_color_table[42].g` и получить доступ к зеленому компоненту цвета #42 из глобальной таблицы цветов. Здесь же такого нет - доступ к цвету есть только внутри процесса парсинга и только в момент нахождения указателя парсера на нужном цвете.

Ну тут во-первых возникает закономерный вопрос: а насколько сильно подобное API раздует и усложнит итоговый код? Насколько это будет востребовано среди тех, кому нужно будет генерировать код в Си?
Релиз Kaitai Struct v0.4 (комментарий) :

А потом приходят злые эмбеддщики и говорят, что у них 2 килобайта памяти и килобайт 15-20 флешки под код

Вряд ли эмбеддщики будут сильно рады, им не нужно столь раздутое API.

А теперь насчет нужности `gif.block[1234]`. Под block у нас понимается то, что названо тут как Image Descriptor http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html. В Packed Field есть флаг, отвечающий на вопрос, будет или не будет у нас использоваться Local Color Table после Image Descriptor. Если будет, то следующий Image Descriptor будет идти не сразу же после предыдущего, а надо еще пропустить размер этого Local Color Table. Т.е. мы не можем за константное время получить gif.block[1234], необходимо перебирать последовательно все эти gif.block и смотреть, есть или нет там этой Local Color Table после чего делать или не делать нужные отступы под эту таблицу. Ну и потом еще должен идти Image Data, так что для получения следующего блока по-любому придется считать какие-то отступы. Время доступа будет O(n). А если мы знаем, где у нас gif.block[1233] и нам надо получить gif.block[1234] то это решается элементарно, можно сравнить это со связными списками. Притом это API для доступа к произвольному элементу будет скорее всего невостребовано, и лишь займет лишнее место. Если тому же эмбеддщику надо используя микроконтроллер воспроизвести анимированный gif на какой-нибудь экранчик, ему вот эти вот gif.block[1234] совершенно не нужны, ему будет достаточно последовательного чтения всех этих блоков, что-то типа итератора.

Чтобы угодить эмбеддщикам, неплохо было бы подумать над тем, чтобы генерировать более узкоспециализированные парсеры бинарных форматов.

Во-вторых, судя по статье на хабре https://habrahabr.ru/post/281595/ основная область применения это разбор неких проприетархых форматов, а не создание эффективного кода для разбора структур с цель последующего «боевого» применения. В таком случае не совсем понятно, зачем нужно делать компиляторы для C и C++. Да и компиляторы-то не особо нужны, вполне хватило бы интерпретатора

Исходная версия SZT, :

Здесь нет возможности чтения из потока + чтения из буфера в памяти - только из буфера в памяти.

Значит надо читать поток в буфер, и потом уже разбирать его

Грузить все сразу в память - это иногда совсем не вариант (например, большие архивы или какой-нибудь 50-гигабайтный образ диска)

Можно использовать отображение файла в память (mmap в *nix, MapViewOfFile в виндах) и тогда никаких проблем. Это уже будет забота ОС с ее механизмом подкачки.

Typecasting в struct - плохая идея, как минимум нужна куча опций упаковки

Тут не происходит прямого typecasting в struct, тут через memcpy в структуру загружается часть входного буфера (кстати этот memcpy вполне можно заменить чем-то другим, например чтением из Unix domain socket и тогда можно читать из некоего потока, а не из буфера в памяти). Если мы по условию не можем опираться на всякие #pragma pack для «уплотнения» структур, то придется от структур как таковых вообще отказаться, и делать memcpy прямо в тип нужной битности (прямой каст указателя и разыменование с unaligned read это UB)

Самое главное - не получилось как такового API доступа к данным. Скажем, в любой из библиотек, сгенеренных KS сейчас, можно написать что-то типа `gif.block[1234]` и мы получим объект блока по порядковому номеру. Можно написать `gif.global_color_table[42].g` и получить доступ к зеленому компоненту цвета #42 из глобальной таблицы цветов. Здесь же такого нет - доступ к цвету есть только внутри процесса парсинга и только в момент нахождения указателя парсера на нужном цвете.

Ну тут во-первых возникает закономерный вопрос: а насколько сильно подобное API раздует и усложнит итоговый код? Насколько это будет востребовано среди тех, кому нужно будет генерировать код в Си?
Релиз Kaitai Struct v0.4 (комментарий) :

А потом приходят злые эмбеддщики и говорят, что у них 2 килобайта памяти и килобайт 15-20 флешки под код

Вряд ли эмбеддщики будут сильно рады, им не нужно столь раздутое API.

А теперь насчет нужности `gif.block[1234]`. Под block у нас понимается то, что названо тут как Image Descriptor http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html. В Packed Field есть флаг, отвечающий на вопрос, будет или не будет у нас использоваться Local Color Table после Image Descriptor. Если будет, то следующий Image Descriptor будет идти не сразу же после предыдущего, а надо еще пропустить размер этого Local Color Table. Т.е. мы не можем за константное время получить gif.block[1234], необходимо перебирать последовательно все эти gif.block и смотреть, есть или нет там этой Local Color Table после чего делать или не делать нужные отступы. А если мы знаем, где у нас gif.block[1233] и нам надо получить gif.block[1234] то это решается элементарно, можно сравнить это со связными списками. Притом это API для доступа к произвольному элементу будет скорее всего невостребовано, и лишь займет лишнее место. Если тому же эмбеддщику надо используя микроконтроллер воспроизвести анимированный gif на какой-нибудь экранчик, ему вот эти вот gif.block[1234] совершенно не нужны, ему будет достаточно последовательного чтения всех этих блоков, что-то типа итератора.

Чтобы угодить эмбеддщикам, неплохо было бы подумать над тем, чтобы генерировать более узкоспециализированные парсеры бинарных форматов.

Во-вторых, судя по статье на хабре https://habrahabr.ru/post/281595/ основная область применения это разбор неких проприетархых форматов, а не создание эффективного кода для разбора структур с цель последующего «боевого» применения. В таком случае не совсем понятно, зачем нужно делать компиляторы для C и C++. Да и компиляторы-то не особо нужны, вполне хватило бы интерпретатора