Для подобных вещей вы обычно используете генератор кода. Давайте предположим, что источник выглядит так:
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 где-то еще (в служебном модуле).
Теперь у вас есть код, который читает определения структуры из файла заголовка и создает новый код, который может считывать структуру из некоторого потока. Дублируйте это, чтобы записать структуру в поток. Скомпилируйте сгенерированный код, и все готово.
Вы также захотите написать модульные тесты, чтобы убедиться, что синтаксический анализ работает правильно :) Просто создайте структуру в памяти, используйте методы записи, чтобы сохранить ее где-нибудь и снова прочитать ее. Теперь две структуры должны быть идентичны. Вы захотите написать третий генератор кода для создания кода для сравнения двух структур.