Один из способов сделать это - создать статические таблицы данных const, которые описывают ваши структуры, чтобы с ними мог работать простой механизм чтения / записи.
Вам необходимо определить структуру, которая может представлять все, что вам нужно знать, чтобы прочитать или написать одно поле одной структуры.
typedef struct {
char * name;
size_t offset;
size_t size;
int format_as;
void* format_struct; // if format_as & IS_STRUCT, this is the structure type
} field_info_t
enum {
AS_CHAR =1,
AS_SHORT,
AS_LONG,
// add other types here
AS_MASK = 0xFF,
// these flags can be OR'd with type to refine the behavior
IS_POINTER = 0x100,
IS_STRUCT = 0x200,
};
Затем создайте из них таблицы, которые описывают все ваши структуры данных.
#define FIELD_OFF(type, field) ((size_t)(LONG_PTR)&(((type *)0)->field))
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
static const field_info_t g_fs_directory_table_item_table[] = {
{ "inode",
FIELD_OFF(fs_directory_table_item_t, inode),
FIELD_SIZE(fs_directory_table_item_t, inode),
AS_LONG,
NULL
},
{ "filename",
FIELD_OFF(fs_directory_table_item_t, filename),
sizeof(filename_t),
AS_CHAR | IS_POINTER,
NULL
},
{ "other_field",
FIELD_OFF(fs_directory_table_item_t, other_field),
FIELD_SIZE(fs_directory_table_item_t, other_field),
AS_STRUCT,
&some_other_field_table,
},
};
А затем читайте и пишите движки, которые получают указатель на структуру и указатель на таблицу, описывающую структуру, и читают / пишут различные поля.
void ReadStructure(FILE * fh, void * pStruct, field_info_t * pFields, int num_fields)
{
// this is just a rough sketch of the code.
for (int ii = 0; ii < num_fields; ++ii)
{
int * field_size = pFields[ii].size;
char * pfield = (char*)pStruct + pFields[ii].offset;
if (pFields[ii].format_as & AS_POINTER)
pfield = *(char**)pfield;
switch (pFields[ii].format_as & AS_MASK)
{
case AS_CHAR:
....
}
}
}
void WriteStructure(FILE * fh, void * pStruct, field_info_t * pFields, int num_fields);
Вам все равно придется поддерживать массив field_info_t
для каждой из ваших структур данных, но как только вы его получите, вы сможете читать, записывать, проверять и печатать свои данные с помощью набора довольно простых функций.