/* is parametrized: no */ #ifndef GUF_COMMON_H #define GUF_COMMON_H #include #include #include #include #include #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