genclibs/array.h
2024-10-14 15:26:57 +02:00

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