‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

программизм-2

Зачем мне, собсно, понадобился такой изврат?

А вот зачем.

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

В каждом таком случае есть что-то общее, что-то разное. Например, в очень обобщённом случае, извлечение данных из приходящей информации делаетс одним и тем же методом, но сами данные -- разные для каждого типа пакета. И последующая обработка их тоже разная. Естественно, хочется "вынести за скобки", но как это сделать, если в одном случае вам надо принять и разобрать два 32-битных числа, например, а в другом - шесть байт, затем один байт и ещё строчку с нулём? Разумеется, можно соорудить гигантский блок switch, в котором долго и занудно расписывать, что куда.

Но это муторно и череповато неуловимыми ошибками.

Можно вдохновиться примером библиотечной scanf и сделать что-то подобное, разбирающее заранее неопределённые данные по заранее определённым шаблонам. Этим задача облегчится эдак наполовину, но нет предела совершенству!

А что, если мы разнесём отдельно шаблоны и саму обработку? чтобы не вызывать в этом несчастном switch сто тыщ раз один и тот же "наш scanf", а вызвать его один раз (разумеется, заранее как-то осознав, какой нужен шаблон и в какие переменные складывать полученные значения)? Тем самым мы ещё более облегчим задачу и, что приятно, уплотним код. Достаточно как-то описать структуры, содержащие шаблоны и списки переменных... и вот тут нас постигает залипуха: Си не поддерживает списки переменных. Совсем никак, в принципе.

Ладно, пусть тогда это будут списки указателей на переменные? Отлично, отлично.

Но, блин, они все будут разной длины! мы не сможем составить список списков (точнее, массив массивов), если вложенные структуры имеют разную длину. Язык этого НЕ ПОЗВОЛЯЕТ. Но, разумеется, мы можем каждый из список переменных выделить в отдельный список, и в самый главный напихать указатели (void*) на них. Это подзасрёт пространство имён, но, к счастью, не фатально повлияет на итоговый размер программы.

Вощем, я выкрутился так: написал макросы, при помощи которых нагенерил кучу массивов указателей на переменные, вбил их внутрь структур, содержащих (const char*) на шаблоны и, заодно, указатели на функции пост-обработки данных. И собрал все эти структуры в один большойтакой массив. Итого, процессинг поступающих разнородных данных уместился в ОДНУ функцию, которая разбирает данные по переменным и, если надо, вызывает пост-обработку.

А в лиспе я бы просто сделал список списков...
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 9 comments