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