171 lines
5.1 KiB
C
171 lines
5.1 KiB
C
#include "describe.h"
|
|
#include "linked_list.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
typedef struct{
|
|
linked_list_t list;
|
|
struct_descriptor_t descriptor;
|
|
} struct_descriptor_node_t;
|
|
|
|
static linked_list_t descriptors;
|
|
|
|
[[gnu::constructor]] static void struct_descriptor_module_constructor(void){
|
|
linked_list_init_head(&descriptors);
|
|
}
|
|
|
|
[[gnu::destructor]] static void struct_descriptor_module_destructor(void){
|
|
struct_descriptor_node_t *node, *n;
|
|
list_for_each_entry_safe(node, n, &descriptors, list){
|
|
free(node);
|
|
}
|
|
}
|
|
|
|
static struct_descriptor_t *struct_descriptor_find_type(char const *name){
|
|
struct_descriptor_node_t *node, *n;
|
|
list_for_each_entry_safe(node, n, &descriptors, list){
|
|
if(strcmp(name, node->descriptor.name) == 0){
|
|
return &(node->descriptor);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct_descriptor_t *struct_descriptor_init_va_list(char const *name, size_t size, size_t count, va_list list){
|
|
struct_descriptor_t *descriptor;
|
|
size_t real_count = count == 0 ? 1 : count;
|
|
|
|
|
|
descriptor = malloc(sizeof(struct_descriptor_t) - sizeof(descriptor->fields) + sizeof_fam_struct(field_descriptor_arr_t, real_count));
|
|
descriptor->fields.len = real_count;
|
|
descriptor->name = name;
|
|
descriptor->size = size;
|
|
|
|
descriptor->fields.data[0] = (field_descriptor_t){.name = name, .offset = 0, .size = size};
|
|
|
|
for(size_t i = 0; i < count; i++){
|
|
descriptor->fields.data[i] = va_arg(list, field_descriptor_t);
|
|
}
|
|
|
|
return descriptor;
|
|
}
|
|
|
|
struct_descriptor_t *struct_descriptor_init(char const *name, size_t size, size_t count, ...){
|
|
va_list list;
|
|
va_start(list, count);
|
|
struct_descriptor_t *descriptor = struct_descriptor_init_va_list(name, size, count, list);
|
|
va_end(list);
|
|
|
|
return descriptor;
|
|
}
|
|
|
|
void struct_descriptor_register(char const *name, size_t size, size_t count, ...){
|
|
va_list list;
|
|
|
|
struct_descriptor_t *descriptor = struct_descriptor_find_type(name);
|
|
struct_descriptor_node_t *node;
|
|
if(descriptor != NULL){
|
|
node = container_of(descriptor, struct_descriptor_node_t, descriptor);
|
|
linked_list_del(&node->list);
|
|
free(node);
|
|
}
|
|
|
|
va_start(list, count);
|
|
size_t real_count = count == 0 ? 1 : count;
|
|
descriptor = struct_descriptor_init_va_list(name, size, count, list);
|
|
node = malloc(sizeof(struct_descriptor_node_t) - sizeof(descriptor->fields) + sizeof_fam_struct(field_descriptor_arr_t, real_count));
|
|
va_end(list);
|
|
|
|
memcpy(&(node->descriptor), descriptor, sizeof(struct_descriptor_t) - sizeof(descriptor->fields) + sizeof_fam_struct(field_descriptor_arr_t, real_count));
|
|
linked_list_add_head(&descriptors, &(node->list));
|
|
|
|
free(descriptor);
|
|
|
|
}
|
|
|
|
|
|
void print_struct_descriptor(struct_descriptor_t *descriptor){
|
|
printf("Type %s:\n", descriptor->name);
|
|
for(size_t i = 0; i < descriptor->fields.len; i++){
|
|
printf(" Field %s at offset %zd and size %zu\n", descriptor->fields.data[i].name, descriptor->fields.data[i].offset, descriptor->fields.data[i].size);
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_arr_t *struct_descriptor_serialize_data_internal(char const *name, void *data, struct_descriptor_t *descriptor){
|
|
uint8_arr_t *arr = NULL;
|
|
arr = uint8_arr_init(descriptor->size);
|
|
for(size_t i = 0; i < descriptor->fields.len; i++){
|
|
char const * field_name = descriptor->fields.data[i].name;
|
|
if (struct_descriptor_find_type(field_name) != NULL){
|
|
|
|
}
|
|
else{
|
|
memcpy(&(arr->data[arr->len]), ((uint8_t *)data) + descriptor->fields.data[i].offset, descriptor->fields.data[i].size);
|
|
descriptor->fields.data[i].serializer(&(arr->data[arr->len]));
|
|
arr->len += descriptor->fields.data[i].size;
|
|
}
|
|
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
uint8_arr_t *struct_descriptor_serialize_data(char const *name, void *data){
|
|
uint8_arr_t *arr = NULL;
|
|
struct_descriptor_t *descriptor = struct_descriptor_find_type(name);
|
|
if(descriptor != NULL){
|
|
arr = struct_descriptor_serialize_data_internal(name, data, descriptor);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
void *struct_descriptor_deserialize_data(char const *name, uint8_arr_t *arr){
|
|
void *res = NULL;
|
|
struct_descriptor_t *descriptor = struct_descriptor_find_type(name);
|
|
if(descriptor != NULL){
|
|
size_t offset = 0;
|
|
res = malloc(descriptor->size);
|
|
for(size_t i = 0; i < descriptor->fields.len; i++){
|
|
memcpy(((uint8_t *)res) + descriptor->fields.data[i].offset, &(arr->data[offset]), descriptor->fields.data[i].size);
|
|
descriptor->fields.data[i].serializer(((uint8_t *)res) + descriptor->fields.data[i].offset);
|
|
offset += descriptor->fields.data[i].size;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
bool struct_descriptor_set_serializer(char const *name, char const *field, serializer_function_t serializer){
|
|
struct_descriptor_node_t *node, *n;
|
|
list_for_each_entry_safe(node, n, &descriptors, list){
|
|
if(strcmp(name, node->descriptor.name) == 0){
|
|
for(size_t i = 0; i < node->descriptor.fields.len; i++){
|
|
if(strcmp(field, node->descriptor.fields.data[i].name) == 0){
|
|
node->descriptor.fields.data[i].serializer = serializer;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void serialize_generic(void *data){ }
|
|
|
|
void serialize_64bits(void *data){
|
|
uint64_t *data64 = (uint64_t *)data;
|
|
*data64 = hton(*data64);
|
|
}
|
|
void serialize_32bits(void *data){
|
|
uint32_t *data32 = (uint32_t *)data;
|
|
*data32 = hton(*data32);
|
|
}
|
|
|
|
void serialize_16bits(void *data){
|
|
uint16_t *data16 = (uint16_t *)data;
|
|
*data16 = hton(*data16);
|
|
} |