You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
4.5 KiB
102 lines
4.5 KiB
/** |
|
* @file serialize.h |
|
* @brief Бинарная сериализация структур с динамическим выделением памяти |
|
* |
|
* Поддерживает структуры с полями переменной длины (ASCIIZ, ARRAY) через указатели. |
|
* При десериализации автоматически выделяет память через u_malloc. |
|
* |
|
* Формат буфера: |
|
* [header_len байт][сериализованные данные] |
|
* |
|
* Пример использования: |
|
* @code |
|
* // Сериализация |
|
* uint8_t header[] = {0x01, 0x02, 0x03, 0x04}; |
|
* serialize_encode(&orig, &schema, header, &buf, &len); |
|
* |
|
* // Десериализация (данные без заголовка) |
|
* uint8_t* data = buf + schema.header_len; |
|
* serialize_decode(data, len - schema.header_len, &schema, &restored); |
|
* |
|
* // Освобождение |
|
* serialize_free(&schema, &restored); |
|
* u_free(buf); |
|
* @endcode |
|
*/ |
|
#ifndef SERIALIZE_H |
|
#define SERIALIZE_H |
|
|
|
#include <stdint.h> |
|
#include <stddef.h> |
|
#include "../lib/mem.h" |
|
|
|
/** |
|
* @brief Описание одного поля структуры для сериализации |
|
*/ |
|
struct SerializeField { |
|
uint16_t offset; ///< смещение указателя в структуре |
|
uint8_t elem_size; ///< 0=fixed, 1=ASCIIZ, >1=ARRAY (размер элемента в байтах) |
|
uint16_t max_size; ///< макс. длина для ASCIIZ / макс. кол-во для ARRAY |
|
uint8_t has_len; ///< 1 если есть length field |
|
uint8_t len_type; ///< 1=UINT8, 2=UINT16 |
|
uint16_t len_offset; ///< смещение length поля в структуре |
|
}; |
|
|
|
/** |
|
* @brief Схема структуры для сериализации |
|
*/ |
|
struct SerializeSchema { |
|
uint16_t field_count; ///< число полей |
|
uint16_t struct_size; ///< размер структуры для allocate |
|
uint16_t header_len; ///< длина заголовка (произвольные байты в начале) |
|
const struct SerializeField* fields; ///< массив описаний полей |
|
}; |
|
|
|
#define SERIALIZE_ERR_OK 0 ///< успех |
|
#define SERIALIZE_ERR_BUF -1 ///< ошибка выделения памяти |
|
#define SERIALIZE_ERR_NULL -2 ///< null указатель |
|
|
|
/** |
|
* @brief Сериализация структуры в бинарный буфер |
|
* @param structure указатель на исходную структуру |
|
* @param schema схема структуры |
|
* @param header заголовок (или NULL если header_len=0) |
|
* @param out_buf [out] выходной буфер (выделяется через u_malloc) |
|
* @param out_len [out] размер буфера |
|
* @return SERIALIZE_ERR_OK или код ошибки |
|
* |
|
* Формат выходного буфера: |
|
* [header_len байт][сериализованные данные] |
|
*/ |
|
int serialize_encode(const void* structure, |
|
const struct SerializeSchema* schema, |
|
const uint8_t* header, |
|
uint8_t** out_buf, |
|
size_t* out_len); |
|
|
|
/** |
|
* @brief Десериализация из буфера в структуру |
|
* @param in_buf буфер БЕЗ заголовка (уже смещённый на header_len) |
|
* @param in_len размер данных (без header) |
|
* @param schema схема структуры |
|
* @param structure [out] указатель на восстановленную структуру |
|
* @return SERIALIZE_ERR_OK или код ошибки |
|
* |
|
* Внимание: in_buf должен быть без заголовка! |
|
* Буфер со смещением: uint8_t* data = buf + schema.header_len; |
|
* Длина без header: size_t data_len = total_len - schema.header_len; |
|
*/ |
|
int serialize_decode(const uint8_t* in_buf, size_t in_len, |
|
const struct SerializeSchema* schema, |
|
void** structure); |
|
|
|
/** |
|
* @brief Освобождение структуры и всех её указателей |
|
* @param schema схема структуры |
|
* @param structure [inout] указатель на структуру (устанавливается в NULL) |
|
* |
|
* Освобождает структуру и все её динамические указатели (ASCIIZ, ARRAY). |
|
*/ |
|
void serialize_free(const struct SerializeSchema* schema, void** structure); |
|
|
|
#endif // SERIALIZE_H
|