Some basic libraries
This commit is contained in:
parent
483f2a440f
commit
c4da343141
177
array.h
Normal file
177
array.h
Normal 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
171
describe.c
Normal 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
73
describe.h
Normal 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
51
for_each.h
Normal 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
92
linked_list.h
Normal 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); \
|
||||||
|
¤t_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); \
|
||||||
|
¤t_elem->member != (list); \
|
||||||
|
current_elem = n, n = container_of(n->member.next, typeof(*n), member))
|
||||||
70
narg.h
Normal file
70
narg.h
Normal 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
89
network_byte_order.h
Normal 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
14
runtime_assert.h
Normal 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
140
test.c
Normal 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
75
time_it.h
Normal 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
|
||||||
Loading…
Reference in New Issue
Block a user