aoc-2025/libguf/guf_common.h
2025-12-23 21:13:41 +01:00

131 lines
4.4 KiB
C++
Executable File

/*
is parametrized: no
*/
#ifndef GUF_COMMON_H
#define GUF_COMMON_H
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <inttypes.h>
#include <stddef.h>
#ifndef GUF_PLATFORM_BIG_ENDIAN
#define GUF_PLATFORM_LITTLE_ENDIAN
#endif
#define GUF_UINT8_MAX 0xffu
#define GUF_UINT16_MAX 0xffffu
#define GUF_UINT32_MAX 0xfffffffful
#define GUF_UINT64_MAX 0xffffffffffffffffull
#define GUF_UWRAP_8(UINT) ( (UINT) & GUF_UINT8_MAX )
#define GUF_UWRAP_16(UINT) ( (UINT) & GUF_UINT16_MAX )
#define GUF_UWRAP_32(UINT) ( (UINT) & GUF_UINT32_MAX )
#define GUF_UWRAP_64(UINT) ( (UINT) & GUF_UINT64_MAX )
#define GUF_INT8_MAX 127
#define GUF_INT8_MIN -128
#define GUF_INT16_MAX 32767
#define GUF_INT16_MIN (-GUF_INT16_MAX - 1)
#define GUF_INT32_MAX 2147483647L
#define GUF_INT32_MIN (-GUF_INT32_MAX - 1)
#define GUF_INT64_MAX 9223372036854775807LL
#define GUF_INT64_MIN (-GUF_INT64_MAX - 1)
#if SIZE_MAX == GUF_UINT64_MAX
#define GUF_PLATFORM_BITS 64
#elif SIZE_MAX == GUF_UINT32_MAX
#define GUF_PLATFORM_BITS 32
#elif SIZE_MAX == GUF_UINT16_MAX
#define GUF_PLATFORM_BITS 16
#elif SIZE_MAX == GUF_UINT8_MAX
#define GUF_PLATFORM_BITS 8
#else
#define GUF_PLATFORM_BITS 64
#error "libguf: Could not detect GUF_PLATFORM_BITS"
#endif
#if GUF_PLATFORM_BITS <= 32
#define GUF_HASH_32_BIT
#define GUF_RAND_32_BIT
#endif
#if defined(__STDC_VERSION__)
#if __STDC_VERSION__ >= 199901L
#define GUF_STDC_AT_LEAST_C99
#else
#error "libguf only supports C99 and above"
#endif
#if __STDC_VERSION__ >= 201112L
#define GUF_STDC_AT_LEAST_C11
#endif
#if __STDC_VERSION__ >= 201710L
#define GUF_STDC_AT_LEAST_C17
#endif
#if __STDC_VERSION__ >= 202311L
#define GUF_STDC_AT_LEAST_C23
#endif
#endif
#if defined(__cplusplus)
#if __cplusplus >= 201103L
#define GUF_STDCPP_AT_LEAST_CPP11
#endif
#endif
/*
// Copy- and move constructors:
GUF_T_COPY: GUF_T *(*copy)(GUF_T *dst, const GUF_T *src, void *ctx);
GUF_T_MOVE: GUF_T *(*move)(GUF_T *dst, GUF_T *src, void *ctx); // "Steals" the resources of src (named after move constructors in C++)
// Destructor:
GUF_T_FREE: void (*free)(GUF_T *obj, void *ctx);
// Comparison- and hash operators:
GUF_T_CMP: int (*cmp)(const GUF_T *a, const GUF_T *b); // a < b -> -1; a == b -> 0; a > b -> 1
GUF_T_EQ: bool (*eq)(const GUF_T *a, const GUF_T *b);
GUF_T_HASH: guf_hash_size_t (*hash)(const GUF_T *obj);
*/
typedef enum guf_cpy_opt {
GUF_CPY_VALUE = 0,
GUF_CPY_DEEP = 1,
GUF_CPY_MOVE = 2,
} guf_cpy_opt;
#define GUF_SWAP(TYPE, val_a, val_b) do {TYPE guf_swap_tmp = val_a; val_a = val_b; val_b = guf_swap_tmp;} while (0);
#define GUF_ARR_SIZE(ARR) (sizeof((ARR)) / (sizeof((ARR)[0])))
#define GUF_MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define GUF_MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#define GUF_CLAMP(X, MIN, MAX) (GUF_MAX(GUF_MIN((X), (MAX)), (MIN)))
// The GUF_CAT/GUF_TOK_CAT indirection is necessary because the ## operation alone does not evaluate the macro arguments.
#define GUF_TOK_CAT(a, b) a##b
#define GUF_CAT(a, b) GUF_TOK_CAT(a, b)
// See comment above.
#define GUF_TOK_STRINGIFY(x) #x
#define GUF_STRINGIFY(x) GUF_TOK_STRINGIFY(x)
#define GUF_CNT_NPOS PTRDIFF_MIN
#define GUF_CNT_FOREACH(CNT_PTR, CNT_TYPE, IT_NAME) for (GUF_CAT(CNT_TYPE, _iter) IT_NAME = GUF_CAT(CNT_TYPE, _begin)(CNT_PTR); IT_NAME.ptr != GUF_CAT(CNT_TYPE, _end)(CNT_PTR).ptr; IT_NAME = GUF_CAT(CNT_TYPE, _iter_next)(CNT_PTR, IT_NAME, 1))
#define GUF_CNT_FOREACH_STEP(CNT_PTR, CNT_TYPE, IT_NAME, STEP) for (GUF_CAT(CNT_TYPE, _iter) IT_NAME = GUF_CAT(CNT_TYPE, _begin)(CNT_PTR); IT_NAME.ptr != GUF_CAT(CNT_TYPE, _end)(CNT_PTR).ptr; IT_NAME = GUF_CAT(CNT_TYPE, _iter_next)(CNT_PTR, IT_NAME, STEP))
#define GUF_CNT_FOREACH_REVERSE(CNT_PTR, CNT_TYPE, IT_NAME) for (GUF_CAT(CNT_TYPE, _iter) IT_NAME = GUF_CAT(CNT_TYPE, _rbegin)(CNT_PTR); IT_NAME.ptr != GUF_CAT(CNT_TYPE, _rend)(CNT_PTR).ptr; IT_NAME = GUF_CAT(CNT_TYPE, _iter_next)(CNT_PTR, IT_NAME, 1))
#define GUF_CNT_FOREACH_REVERSE_STEP(CNT_PTR, CNT_TYPE, IT_NAME, STEP) for (GUF_CAT(CNT_TYPE, _iter) IT_NAME = GUF_CAT(CNT_TYPE, _rbegin)(CNT_PTR); IT_NAME.ptr != GUF_CAT(CNT_TYPE, _rend)(CNT_PTR).ptr; IT_NAME = GUF_CAT(CNT_TYPE, _iter_next)(CNT_PTR, IT_NAME, STEP))
#define GUF_CNT_LIFETIME_BLOCK(GUF_CNT_TYPE, CNT_VARNAME, CODE) do { \
GUF_CNT_TYPE CNT_VARNAME; \
CODE; \
GUF_CAT(GUF_CNT_TYPE, _free)(&CNT_VARNAME, NULL); \
} while (0);
#endif