#include "describe.h" #include "linked_list.h" #include #include 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); }