Разбор потока байтов в структуру / класс - PullRequest
0 голосов
/ 25 ноября 2008

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

Ниже приведен пример того, что я хочу, где я использовал BitConverter для анализа значений. Я надеюсь, что есть более эффективный способ сделать это, потому что мои структуры ОГРОМНЫ!

ref struct TestStruct
{
    int TestInt;
    float TestFloat;
};

int main(array<System::String ^> ^args)
{
    // populating array - just for demo, it's really coming from a file
    array<unsigned char>^ arrBytes = gcnew array<unsigned char>(8);
    Array::Copy(BitConverter::GetBytes((int)1234), arrBytes, 4);
    Array::Copy(BitConverter::GetBytes((float)12.34), 0, arrBytes, 4, 4);

    // parsing to struct - I want help
    TestStruct^ myStruct = gcnew TestStruct();
    myStruct->TestInt = BitConverter::ToInt32(arrBytes, 0);
    myStruct->TestFloat = BitConverter::ToSingle(arrBytes, 4);

    String^ str = Console::ReadLine();
    return 0;
}

Ответы [ 4 ]

1 голос
/ 25 ноября 2008

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

struct a {
    int i;
}

struct b {
    string name;
    struct a a;
}

Что вы делаете, вы пишете простой синтаксический анализатор, который ищет в источнике (возможно, в каком-то заголовочном файле) слово "struct", затем вы читаете имя структуры (что-нибудь между "struct" и "{"). Запишите это в вывод:

cout << "struct " << name << " * read_struct_" << name << " (stream in) {" << NL
    << "    struct " << name << " * result = malloc (sizeof(struct " << name << "));" NL
parseFields (headerStream);
cout << "    return result;" << NL << "}" << NL ; } 

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

В parseFields вы читаете каждую строку и разделяете ее на две части: все, что находится перед последним пробелом (то есть «int» в первом примере), и содержимое между последним пробелом и и «;». В этом случае это будет «я». Теперь вы пишете на выход:

cout << "read_" << fieldType << "(in, &result->" << fieldName << ");" << NL;

Примечание. Вам нужно заменить все пробелы типа поля на "_".

На выходе это выглядит так:

struct a * read_struct_a (stream in) {
   struct a * result = malloc(sizeof(struct a));
   read_int(in, &result->i);
   return result;
}

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

Теперь у вас есть код, который читает определения структуры из файла заголовка и создает новый код, который может считывать структуру из некоторого потока. Дублируйте это, чтобы записать структуру в поток. Скомпилируйте сгенерированный код, и все готово.

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

1 голос
/ 25 ноября 2008

Здесь - объяснение сериализации в .NET

Для общего C ++ (не управляется), посмотрите на boost :: serialize

0 голосов
/ 27 ноября 2008

Сериализация отличная, но в моем случае мне не нужны «дополнительные», и мне все равно пришлось бы делать ту же работу, чтобы иметь полный контроль над битами. Для большинства это может быть решением, я думаю.

Дам мистеру Дигулле правильный ответ, так как он больше всего напоминает мое решение. Также спасибо мистеру Дэвису, который объяснил мне, что это нужно было сделать ...

0 голосов
/ 25 ноября 2008

Вы упоминаете как C ++, так и .net. Только для C ++, вы должны быть в состоянии что-то сделать в соответствии с

char buffer[sizeof(MYSTRUCT)];
memcopy((char*) &mystruct, buffer, sizeof(MYSTRUCT));

Для .net вы ДОЛЖНЫ использовать сериализацию , если хотите избежать отдельного сохранения каждого элемента - классы не гарантированно хранятся в непрерывном блоке памяти. Это раздражает, но это одна из «особенностей» управляемого кода - вы должны позволить ему управлять этим за вас.

-Adam

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