LINUX.ORG.RU

История изменений

Исправление mittorn, (текущая версия) :

Сильно удобного решения для Си в случае уже готовой структуры нет, но можно:
1. Задефайнить описатель структуры вручную в виде массива из типов и смещений полей
2. Реализовать (де)сериализацию через обход этого массива.
Тогда тебе не придётся переделывать саму структуру, но придётся определить способ (де)сереализации каждого поля.
Можно попытаться применить какой-нибудь функциональный макрос для определения полей, чтобы изежать излишней писанины, если таких структур много.
Например:

typedef uint8_t* uint8_t_ptr;
#define DATA_STRUCT(f,s) \
f(s, uint32_t, order) \
f(s, uint8_t_ptr, name) \
f(s, uint16_t,length) \

#define DECLARE_STRUCT(s, type, name) type name;
#define DECLARE_DESC(s, type, name) {type##_e, offsetof(s,name)}
typedef struct {
DATA_STRUCT(data_t, DECLARE_STRUCT)
} data_t;
typedef enum {
uint32_t_e,
uint8_t_ptr_e,
uint16_t_e
} desctype_t;

typedef struct {
desctype_t t;
size_t off;
} desc_t;

desc_t data_desc[] = 
{
DATA_STRUCT(data_t, DECLARE_DESC)
}


После этого написать функцию, которая по массиву data_desc будет разбирать или собирать эту структуру.
Функциональный макрос позволит избежать записи структуры несколько раз, но всё это не очень хорошо читается. Код примера не проверял, могут быть ошибки
Конечно если структуру можно менять - можно сразу задефайнить её так, чтобы она на была стабильной (но если нужна совместимость данных с big endian всё равно придётся свапать данные)

Исправление mittorn, :

Сильно удобного решения для Си в случае уже готовой структуры нет, но можно:
1. Задефайнить описатель структуры вручную в виде массива из типов и смещений полей
2. Реализовать (де)сериализацию через обход этого массива.
Тогда тебе не придётся переделывать саму структуру, но придётся определить способ (де)сереализации каждого поля.
Можно попытаться применить какой-нибудь функциональный макрос для определения полей, чтобы изежать излишней писанины, если таких структур много.
Например:

typedef uint8_t* uint8_t_ptr;
#define DATA_STRUCT(s,f) \
f(s, uint32_t, order) \
f(s, uint8_t_ptr, name) \
f(s, uint16_t,length) \

#define DECLARE_STRUCT(s, type, name) type name;
#define DECLARE_DESC(s, type, name) {type##_e, offsetof(s,name)}
typedef struct {
DATA_STRUCT(data_t, DECLARE_STRUCT)
} data_t;
typedef enum {
uint32_t_e,
uint8_t_ptr_e,
uint16_t_e
} desctype_t;

typedef struct {
desctype_t t;
size_t off;
} desc_t;

desc_t data_desc[] = 
{
DATA_STRUCT(data_t, DECLARE_DESC)
}


После этого написать функцию, которая по массиву data_desc будет разбирать или собирать эту структуру.
Функциональный макрос позволит избежать записи структуры несколько раз, но всё это не очень хорошо читается. Код примера не проверял, могут быть ошибки
Конечно если структуру можно менять - можно сразу задефайнить её так, чтобы она на была стабильной (но если нужна совместимость данных с big endian всё равно придётся свапать данные)

Исправление mittorn, :

Сильно удобного решения для Си в случае уже готовой структуры нет, но можно:
1. Задефайнить описатель структуры вручную в виде массива из типов и смещений полей
2. Реализовать (де)сериализацию через обход этого массива.
Тогда тебе не придётся переделывать саму структуру, но придётся определить способ (де)сереализации каждого поля.
Можно попытаться применить какой-нибудь функциональный макрос для определения полей, чтобы изежать излишней писанины, если таких структур много.
Например:

typedef uint8_t* uint8_t_ptr;
#define DATA_STRUCT(s,f) \
f(s, uint32_t, order) \
f(s, uint8_t_ptr, name) \
f(s, uint16_t,length) \

#define DECLARE_STRUCT(s, type, name) type name;
#define DECLARE_DESC(s, type, name) {type##_e, offsetof(s,name)}
typedef struct {
DECLARE_STRUCT(data_t, DATA_STRUCT)
} data_t;
typedef enum {
uint32_t_e,
uint8_t_ptr_e,
uint16_t_e
} desctype_t;

typedef struct {
desctype_t t;
size_t off;
} desc_t;

desc_t data_desc[] = 
{
DECLARE_DESC(data_t, DATA_STRUCT)
}


После этого написать функцию, которая по массиву data_desc будет разбирать или собирать эту структуру.
Функциональный макрос позволит избежать записи структуры несколько раз, но всё это не очень хорошо читается. Код примера не проверял, могут быть ошибки
Конечно если структуру можно менять - можно сразу задефайнить её так, чтобы она на была стабильной (но если нужна совместимость данных с big endian всё равно придётся свапать данные)

Исправление mittorn, :

Сильно удобного решения для Си в случае уже готовой структуры нет, но можно:
1. Задефайнить описатель структуры вручную в виде массива из типов и смещений полей
2. Реализовать (де)сериализацию через обход этого массива.
Тогда тебе не придётся переделывать саму структуру, но придётся определить способ (де)сереализации каждого поля.
Можно попытаться применить какой-нибудь функциональный макрос для определения полей, чтобы изежать излишней писанины, если таких структур много.
Например:

typedef uint8_t* uint8_t_ptr;
#define DATA_STRUCT(s,f) \
f(s, uint32_t, order) \
f(s,uint8_t_ptr, name) \
f(s, uint16_t,length) \

#define DECLARE_STRUCT(s, type, name) type name;
#define DECLARE_DESC(s, type, name) {type##_e, offsetof(s,name)}
typedef struct {
DECLARE_STRUCT(data_t, DATA_STRUCT)
} data_t;
typedef enum {
uint32_t_e,
uint8_t_ptr_e,
uint16_t_e
} desctype_t;

typedef struct {
desctype_t t;
size_t off;
} desc_t;

desc_t data_desc[] = 
{
DECLARE_DESC(data_t, DATA_STRUCT)
}


После этого написать функцию, которая по массиву data_desc будет разбирать или собирать эту структуру.
Функциональный макрос позволит избежать записи структуры несколько раз, но всё это не очень хорошо читается. Код примера не проверял, могут быть ошибки
Конечно если структуру можно менять - можно сразу задефайнить её так, чтобы она на была стабильной (но если нужна совместимость данных с big endian всё равно придётся свапать данные)

Исходная версия mittorn, :

Сильно удобного решения для Си нет, но можно:
1. Задефайнить описатель структуры вручную в виде массива из типов и смещений полей
2. Реализовать (де)сериализацию через обход этого массива.
Тогда тебе не придётся переделывать саму структуру, но придётся определить способ (де)сереализации каждого поля.
Можно попытаться применить какой-нибудь функциональный макрос для определения полей, чтобы изежать излишней писанины, если таких структур много.
Например:

typedef uint8_t* uint8_t_ptr;
#define DATA_STRUCT(s,f) \
f(s, uint32_t, order) \
f(s,uint8_t_ptr, name) \
f(s, uint16_t,length) \

#define DECLARE_STRUCT(s, type, name) type name;
#define DECLARE_DESC(s, type, name) {type##_e, offsetof(s,name)}
typedef struct {
DECLARE_STRUCT(data_t, DATA_STRUCT)
} data_t;
typedef enum {
uint32_t_e,
uint8_t_ptr_e,
uint16_t_e
} desctype_t;

typedef struct {
desctype_t t;
size_t off;
} desc_t;

desc_t data_desc[] = 
{
DECLARE_DESC(data_t, DATA_STRUCT)
}


После этого написать функцию, которая по массиву data_desc будет разбирать или собирать эту структуру.
Функциональный макрос позволит избежать записи структуры несколько раз, но всё это не очень хорошо читается. Код примера не проверял, могут быть ошибки