178 lines
5.4 KiB
C
178 lines
5.4 KiB
C
#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
|