#ifndef GUF_COMMON_H #define GUF_COMMON_H #include #include #include #include #include /* // 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_STATIC_BUF_SIZE(BUF) (sizeof((BUF)) / (sizeof((BUF)[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_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 = 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 = 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 = 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, _begin)(CNT_PTR); IT_NAME.ptr != GUF_CAT(CNT_TYPE, _end)(CNT_PTR).ptr; it = 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