genclibs/describe.c
2024-10-14 15:26:57 +02:00

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);
}