Some basic libraries

This commit is contained in:
Malik Irain 2024-10-14 15:26:57 +02:00
parent 483f2a440f
commit c4da343141
10 changed files with 952 additions and 0 deletions

177
array.h Normal file
View File

@ -0,0 +1,177 @@
#ifndef sizeof_fam_struct
#define sizeof_fam_struct(type, len) (sizeof(type) + (len)*sizeof(((type*)NULL)->data[0]))
#endif
#ifndef map
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#define map(arr, fun) __extension__({ \
typeof(arr) map_copy_arr = arr; \
size_t data_len = sizeof(typeof(fun(NULL))); \
void *res = malloc(sizeof(size_t) + map_copy_arr->len*data_len); \
*((size_t*)res) = map_copy_arr->len; \
for(size_t i = 0; i < map_copy_arr->len; i++){ \
*((typeof(fun(NULL))*)(((uint8_t*)res) + sizeof(size_t)) + i) = fun(&(arr->data[i])); \
} \
res; \
})
#endif
#ifndef fold
#include <stddef.h>
#define fold(arr,fun, init) __extension__({ \
typeof(arr) fold_copy_arr = arr; \
typeof(init) accu = init; \
for(size_t i = 0; i < fold_copy_arr->len;i++){ \
accu = fun(accu, (fold_copy_arr->data[i]));\
}\
accu;\
})
#endif
#ifndef filter
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#define filter(arr, fun) __extension__({ \
typeof(arr) filter_copy_arr = arr; \
typeof(arr) res = malloc(sizeof_fam_struct(typeof(*arr), filter_copy_arr->len)); \
res->len = 0; \
for(size_t i = 0; i < filter_copy_arr->len; i++){ \
if(fun(filter_copy_arr->data[i])){ \
res->data[(res->len)++] = filter_copy_arr->data[i]; \
} \
} \
res; \
})
#endif
#ifndef apply
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#define apply(arr, fun) __extension__({ \
typeof(arr) apply_copy_arr = arr; \
for(size_t i = 0; i < apply_copy_arr->len; i++){ \
fun(&(apply_copy_arr->data[i])); \
} \
apply_copy_arr; \
})
#endif
#ifndef ARR_T_GENERIC_MACROS
#define ARR_T_GENERIC_MACROS
#include <stddef.h>
#define arr_t(T) struct ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, s){ \
size_t cap; \
size_t len; \
T data[]; \
}\
#define ARR_T_NOT_EXPOSED__ARR_NAME_COMBINE(T, name) T##_arr_##name
#define ARR_T_NOT_EXPOSED__ARR_NAME_EXPAND(T, name) ARR_T_NOT_EXPOSED__ARR_NAME_COMBINE(T, name)
#define ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, name) ARR_T_NOT_EXPOSED__ARR_NAME_EXPAND(ARR_T_NOT_EXPOSED__GET_TYPE(T), name)
#define ARR_T_NOT_EXPOSED__GET_TYPE_CONTAINS_struct 0,
#define ARR_T_NOT_EXPOSED__GET_TYPE_CONTAINS_enum 1,
#define ARR_T_NOT_EXPOSED__RETURN_TYPE(T, ...) T
#define ARR_T_NOT_EXPOSED__GET_TYPE_EXPAND(maybe_T, _, ...) ARR_T_NOT_EXPOSED__RETURN_TYPE(__VA_OPT__(__VA_ARGS__ ,) maybe_T)
#define ARR_T_NOT_EXPOSED__GET_TYPE_EXTRACT_PREFIX(maybe_T, _) ARR_T_NOT_EXPOSED__GET_TYPE_EXPAND(maybe_T, _)
#define ARR_T_NOT_EXPOSED__GET_TYPE(T) ARR_T_NOT_EXPOSED__GET_TYPE_EXTRACT_PREFIX(T, ARR_T_NOT_EXPOSED__GET_TYPE_CONTAINS_##T)
#endif
#ifndef array_of
#define array_of(T) ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, t)
#endif
#ifndef autofree
#define autofree_array_of(T) [[gnu::__cleanup__(ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, autofree))]] array_of(T)
#endif
#ifndef ARRAY_OF
#warning "ARRAY_OF not defined. This includes does nothing."
#else
#include <stdlib.h>
#define arr__stringify_expand(x) #x
#define arr__stringify(x) arr__stringify_expand(x)
#define arr_init_declare(T) [[maybe_unused]] static array_of(T) *ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, init)(size_t cap)
#define arr_init_body(T) [[maybe_unused]] static array_of(T) *ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, init)(size_t cap){ \
array_of(T) *arr = malloc(sizeof_fam_struct(array_of(T), cap)); \
arr->cap = cap; \
arr->len = 0; \
return arr; \
}
#define arr_push_declare(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, push)(array_of(T) *arr, T val)
#define arr_push_body(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, push)(array_of(T) *arr, T val){ \
if(arr->len < arr->cap){ \
arr->data[(arr->len)++] = val; \
} \
}
#define arr_pop_declare(T) [[maybe_unused]] static T ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, pop)(array_of(T) *arr)
#define arr_pop_body(T) [[maybe_unused]] static T ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, pop)(array_of(T) *arr){ \
return arr->data[--(arr->len)]; \
}
#define arr_free_declare(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, free)(array_of(T) *arr)
#define arr_free_body(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, free)(array_of(T) *arr){ \
free(arr); \
}
#ifdef CUSTOM_AUTOFREE
#define arr_autofree_declare(T) [[maybe_unused,gnu::alias(arr__stringify(CUSTOM_AUTOFREE))]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, autofree)(array_of(T) **p)
#define arr_autofree_body(T)
#else
#define arr_autofree_declare(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, autofree)(array_of(T) **p)
#define arr_autofree_body(T) [[maybe_unused]] static void ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(T, autofree)(array_of(T) **p){\
free(*p);\
}
#endif
typedef arr_t(ARRAY_OF) ARR_T_NOT_EXPOSED__ARR_MAKE_NAME(ARRAY_OF, t);
arr_init_declare(ARRAY_OF);
arr_push_declare(ARRAY_OF);
arr_pop_declare(ARRAY_OF);
arr_free_declare(ARRAY_OF);
arr_autofree_declare(ARRAY_OF);
#ifndef ARRAY_NO_IMPLEM
arr_init_body(ARRAY_OF)
arr_push_body(ARRAY_OF)
arr_pop_body(ARRAY_OF)
arr_free_body(ARRAY_OF)
arr_autofree_body(ARRAY_OF)
#endif
#undef arr_init_declare
#undef arr_init_body
#undef arr_push_declare
#undef arr_push_body
#undef arr_pop_declare
#undef arr_pop_body
#undef arr_free_declare
#undef arr_free_body
#undef arr_autofree_declare
#undef arr_autofree_body
#undef arr__stringify_expand
#undef arr__stringify
#undef CUSTOM_AUTOFREE
#undef ARRAY_OF
#endif

171
describe.c Normal file
View File

@ -0,0 +1,171 @@
#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);
}

73
describe.h Normal file
View File

@ -0,0 +1,73 @@
#pragma once
#include <stddef.h>
#include <stdarg.h>
#include <stdint.h>
#include "network_byte_order.h"
typedef uint8_t uint8;
#define ARRAY_OF uint8
#include "array.h"
typedef struct struct_descriptor_s struct_descriptor_t;
typedef void (*serializer_function_t)(uint8_t *);
typedef struct field_descriptor{
char const *name;
ptrdiff_t offset;
size_t size;
serializer_function_t serializer;
} field_descriptor_t;
#define ARRAY_OF struct field_descriptor
#include "array.h"
typedef struct struct_descriptor_s{
char const *name;
size_t size;
field_descriptor_arr_t fields;
} struct_descriptor_t;
#include "narg.h"
#include "for_each.h"
#define default_serializer_function(s) __extension__({ \
(s == 64) ? serialize_64bits : ( \
(s == 32) ? serialize_32bits : ( \
(s == 16) ? serialize_16bits : \
serialize_generic ));\
})
#define sizeof_field(T, field) sizeof(((T *)NULL)->field)
#define describe_field(T, field) ((field_descriptor_t) {.name = #field, .offset = offsetof(T, field), .size = sizeof_field(T, field), .serializer = default_serializer_function(sizeof_field(T, field))})
#define describe_fields(T, ...) for_each_pair(describe_field, T, __VA_ARGS__)
#define describe_type(T, ...) struct_descriptor_init(#T, sizeof(T), NARG(__VA_ARGS__) __VA_OPT__(, describe_fields(T, __VA_ARGS__)))
struct_descriptor_t *struct_descriptor_init(char const *name, size_t size, size_t count, ...);
#define register_type(T, ...) struct_descriptor_register(#T, sizeof(T), NARG(__VA_ARGS__) __VA_OPT__(, describe_fields(T, __VA_ARGS__)))
void struct_descriptor_register(char const *name, size_t size, size_t count, ...);
#define serialize_type(T, data) struct_descriptor_serialize_data(#T, data)
uint8_arr_t *struct_descriptor_serialize_data(char const *name, void *data);
#define deserialize_data(T, data) (T *) struct_descriptor_deserialize_data(#T, data)
void *struct_descriptor_deserialize_data(char const *name, uint8_arr_t *data);
bool struct_descriptor_set_serializer(char const *name, char const *field, serializer_function_t serializer);
void print_struct_descriptor(struct_descriptor_t *descriptor);
void serialize_64bits(void *data);
void serialize_32bits(void *data);
void serialize_16bits(void *data);
void serialize_generic(void *data);

51
for_each.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef FOR_EACH_H
#define FOR_EACH_H
/*
* for_each - apply a function-like object (fun) to each
* following argument (a1, a2, ..., an)
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
*
* @fun: the function-like object to apply
* @...: the list of agurments on which to apply
*
* Note: fun can be either a macro, a function or a cast
* in parenthesis (e.g. for_each((char), 67, 10))
*/
#define for_each(fun, ...) __VA_OPT__(FOR_EACH_NOT_EXPOSED__EXPAND(FOR_EACH_NOT_EXPOSED__HELPER(fun, __VA_ARGS__)))
/*
* for_each_pair - apply a function-like object (fun) to the same
* value (s) and each following argument (a1, a2, ..., an)
* resulting in (fun(s, a1)), (fun(s, a2)), ..., (fun(s, an))
*
* @fun: the function-like object to apply
* @s: the repeated first argument
* @...: the list of seconds agurments on which to apply
*
* Note: fun can be either a macro or a function
*/
#define for_each_pair(fun, s, ...) __VA_OPT__(FOR_EACH_NOT_EXPOSED__EXPAND(FOR_EACH_NOT_EXPOSED__HELPER_PAIR(fun, s, __VA_ARGS__)))
#define FOR_EACH_NOT_EXPOSED__LEFT_PAREN (
#define FOR_EACH_NOT_EXPOSED__RIGHT_PAREN )
#define FOR_EACH_NOT_EXPOSED__EXPAND(...) FOR_EACH_NOT_EXPOSED__EXPAND1(FOR_EACH_NOT_EXPOSED__EXPAND1(FOR_EACH_NOT_EXPOSED__EXPAND1(FOR_EACH_NOT_EXPOSED__EXPAND1(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND1(...) FOR_EACH_NOT_EXPOSED__EXPAND2(FOR_EACH_NOT_EXPOSED__EXPAND2(FOR_EACH_NOT_EXPOSED__EXPAND2(FOR_EACH_NOT_EXPOSED__EXPAND2(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND2(...) FOR_EACH_NOT_EXPOSED__EXPAND3(FOR_EACH_NOT_EXPOSED__EXPAND3(FOR_EACH_NOT_EXPOSED__EXPAND3(FOR_EACH_NOT_EXPOSED__EXPAND3(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND3(...) FOR_EACH_NOT_EXPOSED__EXPAND4(FOR_EACH_NOT_EXPOSED__EXPAND4(FOR_EACH_NOT_EXPOSED__EXPAND4(FOR_EACH_NOT_EXPOSED__EXPAND4(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND4(...) FOR_EACH_NOT_EXPOSED__EXPAND5(FOR_EACH_NOT_EXPOSED__EXPAND5(FOR_EACH_NOT_EXPOSED__EXPAND5(FOR_EACH_NOT_EXPOSED__EXPAND5(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND5(...) FOR_EACH_NOT_EXPOSED__EXPAND6(FOR_EACH_NOT_EXPOSED__EXPAND6(FOR_EACH_NOT_EXPOSED__EXPAND6(FOR_EACH_NOT_EXPOSED__EXPAND6(__VA_ARGS__))))
#define FOR_EACH_NOT_EXPOSED__EXPAND6(...) __VA_ARGS__
#define FOR_EACH_NOT_EXPOSED__RECURSE(helper) FOR_EACH_NOT_EXPOSED__ ## helper
#define FOR_EACH_NOT_EXPOSED__HELPER(fun, a1, ...) (fun(a1)) \
__VA_OPT__(, FOR_EACH_NOT_EXPOSED__RECURSE FOR_EACH_NOT_EXPOSED__LEFT_PAREN HELPER FOR_EACH_NOT_EXPOSED__RIGHT_PAREN(fun, __VA_ARGS__))
#define FOR_EACH_NOT_EXPOSED__HELPER_PAIR(fun, a1, a2, ...) (fun(a1, a2)) \
__VA_OPT__(, FOR_EACH_NOT_EXPOSED__RECURSE FOR_EACH_NOT_EXPOSED__LEFT_PAREN HELPER_PAIR FOR_EACH_NOT_EXPOSED__RIGHT_PAREN(fun, a1, __VA_ARGS__))
#endif //FOR_EACH_H

92
linked_list.h Normal file
View File

@ -0,0 +1,92 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define container_of(ptr, type, member) ((type *) ((uint8_t *)(ptr) - offsetof(type, member)))
typedef struct linked_list {
struct linked_list *prev;
struct linked_list *next;
} linked_list_t;
static inline void linked_list_init_head(linked_list_t *head){
head->prev = head;
head->next = head;
}
static inline void linked_list_add_internal(linked_list_t *prev, linked_list_t *elem, linked_list_t *next){
prev->next = elem;
elem->prev = prev;
elem->next = next;
next->prev = elem;
}
[[maybe_unused]] static inline void linked_list_add_head(linked_list_t *head, linked_list_t *elem){
linked_list_add_internal(head, elem, head->next);
}
[[maybe_unused]] static inline void linked_list_add_tail(linked_list_t *elem, linked_list_t *head)
{
linked_list_add_internal(head->prev, elem, head);
}
[[maybe_unused]] static inline bool list_empty(linked_list_t const *list){
return list->next == list;
}
static inline void linked_list_del_internal(linked_list_t *prev, linked_list_t *next){
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
[[maybe_unused]] static inline void linked_list_del(linked_list_t *elem){
linked_list_del_internal(elem->prev, elem->next);
elem->next = NULL;
elem->prev = NULL;
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
[[maybe_unused]] static inline void linked_list_extract(linked_list_t *elem){
linked_list_del_internal(elem->prev, elem->next);
linked_list_init_head(elem);
}
/**
* list_for_each_entry - iterate over list of given type
* @current_elem: the type * to use as a loop counter.
* @list: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(current_elem, list, member) \
for (current_elem = container_of((list)->next, typeof(*current_elem), member); \
&current_elem->member != (list); \
current_elem = container_of(current_elem->member.next, typeof(*current_elem), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @current_elem: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @list: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(current_elem, n, list, member) \
for (current_elem = container_of((list)->next, typeof(*current_elem), member), \
n = container_of(current_elem->member.next, typeof(*current_elem), member); \
&current_elem->member != (list); \
current_elem = n, n = container_of(n->member.next, typeof(*n), member))

70
narg.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef NARG_MACRO_H
#define NARG_MACRO_H
#define ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, N, ...) N
#define RSEQ_N() \
63, 62, 61, 60, \
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define RSEQ_N_2() \
1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 0
#define NARG_(...) ARG_N(__VA_ARGS__)
#define COMMASEQ_N() \
1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 0, 0
#define COMMA(...) ,
#define HASCOMMA(...) \
NARG_(__VA_ARGS__, COMMASEQ_N())
#define NARG(...) \
NARG_HELPER1( \
HASCOMMA(__VA_ARGS__), \
HASCOMMA(COMMA __VA_ARGS__ ()), \
NARG_(__VA_ARGS__, RSEQ_N()))
#define NARG_2(...) \
NARG_HELPER1( \
HASCOMMA(__VA_ARGS__), \
HASCOMMA(COMMA __VA_ARGS__ ()), \
NARG_(__VA_ARGS__, RSEQ_N_2()))
#define NARG_HELPER1(a, b, N) NARG_HELPER2(a, b, N)
#define NARG_HELPER2(a, b, N) NARG_HELPER3_ ## a ## b(N)
#define NARG_HELPER3_01(N) 0
#define NARG_HELPER3_00(N) 1
#define NARG_HELPER3_11(N) N
#define COMBINE_EXPANDED(A, B) A ## B
#define COMBINE(A, B) COMBINE_EXPANDED(A,B)
#endif //NARG_MACRO_H

89
network_byte_order.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef NETWORK_BYTE_ORDER_H
#define NETWORK_BYTE_ORDER_H
#include <stdint.h>
static inline uint64_t hton64(uint64_t host);
static inline uint32_t hton32(uint32_t host);
static inline uint16_t hton16(uint16_t host);
static inline uint8_t hton8 (uint8_t host);
#define hton(x) _Generic( (x), \
uint64_t : hton64, \
uint32_t : hton32, \
uint16_t : hton16, \
uint8_t : hton8 \
)(x)
[[gnu::alias("hton64")]] static inline uint64_t ntoh64(uint64_t network);
[[gnu::alias("hton32")]] static inline uint32_t ntoh32(uint32_t network);
[[gnu::alias("hton16")]] static inline uint16_t ntoh16(uint16_t network);
[[gnu::alias("hton8") ]] static inline uint8_t ntoh8 (uint8_t network);
#define ntoh(x) _Generic( (x), \
uint64_t : ntoh64, \
uint32_t : ntoh32, \
uint16_t : ntoh16, \
uint8_t : ntoh8 \
)(x)
#ifndef NETWORK_BYTE_ORDER_IMPLEMENTED
#define NETWORK_BYTE_ORDER_IMPLEMENTED
#include <stdbool.h>
#define bswap64(x) \
((((x) & 0xff00000000000000ull) >> 56) \
| (((x) & 0x00ff000000000000ull) >> 40) \
| (((x) & 0x0000ff0000000000ull) >> 24) \
| (((x) & 0x000000ff00000000ull) >> 8) \
| (((x) & 0x00000000ff000000ull) << 8) \
| (((x) & 0x0000000000ff0000ull) << 24) \
| (((x) & 0x000000000000ff00ull) << 40) \
| (((x) & 0x00000000000000ffull) << 56))
#define bswap32(x) \
((((x) & 0xff000000ul) >> 24) \
| (((x) & 0x00ff0000ul) >> 8) \
| (((x) & 0x0000ff00ul) << 8) \
| (((x) & 0x000000fful) << 24))
#define bswap16(x) \
((((x) & 0xff00u) >> 8) \
| (((x) & 0x00ffu) << 8))
static inline bool is_big_endian(void){
return ((const union { uint16_t full; struct{ uint8_t high; uint8_t low; } __attribute__((packed)); } __attribute__((packed))) { .full = 1 }).low == 1;
}
static inline uint64_t hton64(uint64_t host){
if(is_big_endian()){
return host;
}
else{
return bswap64(host);
}
}
static inline uint32_t hton32(uint32_t host){
if(is_big_endian()){
return host;
}
else{
return bswap32(host);
}
}
static inline uint16_t hton16(uint16_t host){
if(is_big_endian()){
return host;
}
else{
return bswap16(host);
}
}
static inline uint8_t hton8 (uint8_t host){
return host;
}
#endif
#endif

14
runtime_assert.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef RUNTIME_ASSERT_H
#define RUNTIME_ASSERT_H
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define runtime_assert(x, ...) for (bool expression = x; !(expression); assert(expression && # x)) __VA_OPT__(fprintf(stderr, __VA_ARGS__), fprintf(stderr, " (errno : %s)", (errno == 0) ? "OK" : strerror(errno)), fprintf(stderr, "\n"))
#endif //RUNTIME_ASSERT_H

140
test.c Normal file
View File

@ -0,0 +1,140 @@
#define ARRAY_OF int
#include "array.h"
#include "time_it.h"
#include "describe.h"
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
typedef double_arr_t *double_arr;
#define ARRAY_OF double_arr
#define CUSTOM_AUTOFREE double_arr_arr_cleanup
#include "array.h"
void double_arr_arr_cleanup(double_arr_arr_t **arr){
if(*arr != NULL){
for(size_t i = 0; i < (*arr)->len; i++){
double_arr_free((*arr)->data[i]);
}
free(*arr);
}
}
#define SLEEP_DURATION 2
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
int hello(int* _){
printf("%d, ", *_);
return 0;
}
#define generic _Generic
#define sum(a, e) generic((a), int : sumi, double : sumd)(a,e)
int sumi(int accu, int e){
return accu + e;
}
double sumd(double accu, double e){
return accu + e;
}
double average(double_arr_t *arr){
return fold(arr, sum, 0)/(arr->len == 0 ? 1 : arr->len);
}
bool over_5(int e){
return e > 5;
}
typedef struct type_{
size_t foo;
float bar;
} type_;
void wrapper(void){
register_type(field_descriptor_t, name, offset, size);
register_type(field_descriptor_t, offset, size);
register_type(field_descriptor_t);
register_type(struct type_);
autofree_array_of(uint8) *ser = serialize_type(struct type_, &((struct type_){ .foo = 5, .bar = .05f}));
if(ser != NULL){
struct type_ *des = deserialize_data(struct type_, ser);
printf("%zu, %f\n", des->foo, des->bar);
free(des);
}
}
int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv){
//#define test_macro(x) (constexpr serializer_function_t _ = (serializer_function_t)(NULL), _)
wrapper();
autofree_array_of(int) *zozo = int_arr_init(10);
for(size_t i = 0; i < zozo->cap; i++){
int_arr_push(zozo, i);
}
autofree_array_of(int) *over = filter(zozo, over_5);
apply(zozo, hello);
printf("\n");
printf("%d\n", fold(zozo, sum, 0));
for(size_t i = 0; i < over->len; i++){
printf("%d, ", over->data[i]);
}
printf("\n");
//free(over);
// for(size_t i = 0; i < 64; i++){
// printf("log2(%zu) = %zu\n", i, log2(i));
// }
//free(zozo);
autofree_array_of(double_arr) *results = double_arr_arr_init(10);
double_arr_arr_push(results, time_it_repeat(sleep(SLEEP_DURATION), .repeat = 0, .number = 2));
double_arr_arr_push(results, time_it_repeat(sleep(SLEEP_DURATION), .number = 7));
double_arr_arr_push(results, time_it_repeat(sleep(SLEEP_DURATION), .repeat = 0));
double_arr_arr_push(results, time_it_repeat(sleep(SLEEP_DURATION)));
printf("##############################\n");
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .repeat = 0, .number = 2 took %f seconds\n", average(results->data[0]));
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .number = 7 took %f seconds\n", average(results->data[1]));
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .repeat = 0 took %f seconds\n", average(results->data[2]));
printf("sleep(" STRINGIFY(SLEEP_DURATION) ") took %f seconds\n", average(results->data[3]));
printf("##############################\n");
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .repeat = 0, .number = 2 took %f seconds\n", time_it(sleep(SLEEP_DURATION), .number = 2));
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .number = 7 took %f seconds\n", time_it(sleep(SLEEP_DURATION), .number = 7));
printf("sleep(" STRINGIFY(SLEEP_DURATION) "), .repeat = 0 took %f seconds\n", time_it(sleep(SLEEP_DURATION), .number = 0));
printf("sleep(" STRINGIFY(SLEEP_DURATION) ") took %f seconds\n", time_it(sleep(SLEEP_DURATION)));
free(double_arr_arr_pop(results));
return 0;
}

75
time_it.h Normal file
View File

@ -0,0 +1,75 @@
#ifndef TIME_IT_H
#define TIME_IT_H
#include <stddef.h>
#include <time.h>
#define ARRAY_OF double
#include "array.h"
/*
* time_it - executes the provided code and returns a
* following argument (a1, a2, ..., an)
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
*
* @code: the code to time; It can be a simple function call or
* a full block code
* @...: the optional argument number that
*
* @return: the elapsed execution time in seconds
* Note: fun can be either a macro, a function or a cast
* in parenthesis (e.g. for_each((char), 67, 10))
*/
#define time_it(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(, code, __VA_ARGS__)
/*
* for_each - apply a function-like object (fun) to each
* following argument (a1, a2, ..., an)
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
*
* @fun: the function-like object to apply
* @...: the list of agurments on which to apply
*
* Note: fun can be either a macro, a function or a cast
* in parenthesis (e.g. for_each((char), 67, 10))
*/
#define time_it_repeat(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(REPEAT, code, __VA_ARGS__)
#define TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(type, code, ...) __extension__({ \
struct time_it_params { TIME_IT_NOT_EXPOSED__IF_REPEAT(type, size_t repeat;) size_t number;} time_it_params = (struct time_it_params){ TIME_IT_NOT_EXPOSED__IF_REPEAT(type, .repeat = 1, _) .number = 1}; \
__VA_OPT__(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG(__VA_ARGS__);) \
__VA_OPT__(TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG, __VA_ARGS__);) \
TIME_IT_NOT_EXPOSED__INIT_RES(type, time_it_params.repeat);\
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, for(size_t i = 0; i < time_it_params.repeat; i++){) \
double time_it_time = 0; \
for(size_t j = 0; j < time_it_params.number; j++){ \
struct timespec time_it_start, time_it_stop; \
clock_gettime(CLOCK_MONOTONIC, &time_it_start); \
code; \
clock_gettime(CLOCK_MONOTONIC, &time_it_stop); \
time_it_time += ((time_it_stop.tv_sec - time_it_start.tv_sec) + (time_it_stop.tv_nsec - time_it_start.tv_nsec) / 1000000000.0); \
}\
TIME_IT_NOT_EXPOSED__WRITE_RES(type, time_it_time); \
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, }) \
res;\
})
#define TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(macro, a1, ...) __VA_OPT__(macro(__VA_ARGS__))
#define TIME_IT_NOT_EXPOSED__FIRST_ARG(a1, ...) a1
#define TIME_IT_NOT_EXPOSED__INIT_RES_REPEAT(repeat) double_arr_t *res = double_arr_init(repeat)
#define TIME_IT_NOT_EXPOSED__INIT_RES_(_) double res = 0
#define TIME_IT_NOT_EXPOSED__INIT_RES(type, repeat) TIME_IT_NOT_EXPOSED__INIT_RES_ ## type (repeat)
#define TIME_IT_NOT_EXPOSED__WRITE_RES_REPEAT(value) double_arr_push(res, value)
#define TIME_IT_NOT_EXPOSED__WRITE_RES_(value) res = value
#define TIME_IT_NOT_EXPOSED__WRITE_RES(type, value) TIME_IT_NOT_EXPOSED__WRITE_RES_ ## type(value)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_REPEAT(code, ...) code __VA_OPT__(,)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_(...)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT(type, ...) TIME_IT_NOT_EXPOSED__IF_REPEAT_ ## type (__VA_ARGS__)
#endif //TIME_IT_H