Декодирование потока байтов - PullRequest
0 голосов
/ 16 декабря 2008

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

У меня более 1000 различных сообщений, которые необходимо декодировать, поэтому я не уверен, стоит ли определять все форматы структуры в XML и затем использовать XSL или какой-либо перевод или есть лучший способ сделать это.

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

Какие-либо рекомендации для методов / инструментов / алгоритмов для создания декодера / парсера?

struct:
struct {
  dword messageid;
  dword datavalue1;
  dword datavalue2;
} struct1;

Пример необработанных данных:

0101010A0A0A0A0F0F0F0F

Декодированное сообщение (желаемый вывод):

message id: 0x01010101, datavalue1: 0x0A0A0A0A, datavalue2: 0x0F0F0F0F

Я использую C ++ для этой разработки.

Ответы [ 4 ]

0 голосов
/ 28 июля 2009

Я собираюсь предположить, что все, что вам нужно сделать, это отформатировать записи и вывести их.

Используйте собственный генератор кода. Сгенерированный код будет выглядеть примерно так:

typedef struct { word messageid; } Header;

//repeated for each record type
typedef struct {
    word messageid;
    // <members here>
} Record_##;
//END


void Process(Input inp, Output out) {
    char buffer[BIG_ENOUGH];
    char *offset;

    offset = &buffer[BIG_ENOUGH];

    while(notEnd) {
        if(&offset[sizeof(LargestStruct)] >= &buffer[BIG_ENOUGH])
            // move remaining buffer to start and fill tail from inp

        Header *hpt = (Header*)offset;

        switch(hpt->messageid)
        {
            //repeated for each record type
            case <recond ID for given type>: 
            {
                Record_##* rpt = (Record_##*)offset;
                outp.format("name1: %t, ...\n", rpt->name1, ...);
                offset += sizeof(Record_##);
                break;
            }
            //END
        }
    }
}

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

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


Редактировать: после перечитывания вопроса, похоже, вы уже определили структуры. В этом случае вы можете просто #include использовать их и использовать напрямую. Однако тогда вы сталкиваетесь с проблемой синтаксического анализа структур для генерации входных данных для функции форматирования. Awk или sed могут быть там полезны.

0 голосов
/ 17 декабря 2008

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

Вместо этого вы должны попытаться написать компилятор, который принимает эти определения методов и компилирует их в функцию декодера.

В наши дни рекомендуется использовать ANTLR в качестве генератора синтаксического анализатора, используя любой из языков ANTLR для реального компилятора (Java, Python, Ruby, C #, C ++). Затем этот компилятор должен вывести код C, который выполняет полное декодирование и красивую печать.

0 голосов
/ 28 июля 2009

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

0 голосов
/ 16 декабря 2008

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

Я также не уверен в том, в чем проблема - учитывая вопрос сейчас - у вас есть 3 DWORD в структуре, и вы утверждаете, что существует более 1000 уникальных сообщений, основанных на этих значениях.

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

Если у вас есть сопоставление значения со строкой, тогда большой оператор switch прост - или, если вы хотите, чтобы иметь возможность добавлять их динамически или изменять отображение, тогда я бы предоставил ключ / значение пары (сопоставление) в файле конфигурации (текст, XML и т. д.), а затем выполнить поиск при чтении файла журнала / необработанных данных.

карта - это то, что я бы использовал в этом случае.

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

...