Для каждой структуры данных имеется функция serialize_X (где X - имя структуры), которая принимает указатель на X и указатель на непрозрачную структуру буфера и вызывает соответствующие функции сериализации.Вы должны предоставить некоторые примитивы, такие как serialize_int, которые записывают в буфер и обновляют выходной индекс.Примитивам придется вызывать что-то вроде reserve_space (N), где N - это количество байтов, которое требуется перед записью каких-либо данных.Reserve_space () перераспределит буфер void *, чтобы сделать его по крайней мере таким же большим, как его текущий размер плюс N байтов.Чтобы сделать это возможным, структура буфера должна содержать указатель на фактические данные, индекс для записи следующего байта (выходной индекс) и размер, выделенный для данных.В этой системе все ваши функции serialize_X должны быть довольно простыми, например:
struct X {
int n, m;
char *string;
}
void serialize_X(struct X *x, struct Buffer *output) {
serialize_int(x->n, output);
serialize_int(x->m, output);
serialize_string(x->string, output);
}
И код платформы будет выглядеть примерно так:
#define INITIAL_SIZE 32
struct Buffer {
void *data;
int next;
size_t size;
}
struct Buffer *new_buffer() {
struct Buffer *b = malloc(sizeof(Buffer));
b->data = malloc(INITIAL_SIZE);
b->size = INITIAL_SIZE;
b->next = 0;
return b;
}
void reserve_space(Buffer *b, size_t bytes) {
if((b->next + bytes) > b->size) {
/* double size to enforce O(lg N) reallocs */
b->data = realloc(b->data, b->size * 2);
b->size *= 2;
}
}
Отсюда должно бытьдовольно просто реализовать все необходимые вам функции serialize_ ().
РЕДАКТИРОВАТЬ: Например:
void serialize_int(int x, Buffer *b) {
/* assume int == long; how can this be done better? */
x = htonl(x);
reserve_space(b, sizeof(int));
memcpy(((char *)b->data) + b->next, &x, sizeof(int));
b->next += sizeof(int);
}
РЕДАКТИРОВАТЬ: Также обратите внимание, что в моем коде есть некоторые потенциальные ошибки.Размер буферного массива хранится в size_t, но индекс имеет тип int (я не уверен, считается ли size_t приемлемым типом для индекса).Кроме того, нет никаких условий для обработки ошибок и нет функции для освобождения буфера после того, как вы закончите, поэтому вам придется делать это самостоятельно.Я просто демонстрировал основную архитектуру, которую буду использовать.