From cd1c1cd5dbd3e3df1ac3ac81fe9c7dc7795924f8 Mon Sep 17 00:00:00 2001 From: jun <83899451+zeichensystem@users.noreply.github.com> Date: Sun, 2 Mar 2025 18:21:25 +0100 Subject: [PATCH] Refactor --- CMakeLists.txt | 2 +- src/guf_common.h | 4 +- src/guf_dbuf.h | 433 ++++++++++++++++++++------------------- src/guf_dict.h | 161 +++++++-------- src/guf_hash.h | 28 +-- src/guf_init.h | 2 +- src/guf_math.h | 1 + src/guf_rand.h | 99 +++++---- src/guf_sort.h | 32 +-- src/guf_str.h | 179 +++++++++++----- src/guf_str_view_type.h | 10 + src/guf_utf8.h | 312 +++++++++++++++++----------- src/test/example.c | 22 +- src/test/guf_dbuf_impl.c | 30 +-- src/test/guf_dbuf_impl.h | 17 +- src/test/guf_dict_impl.c | 4 +- src/test/guf_rand_impl.c | 2 +- src/test/guf_sort_impl.c | 8 +- src/test/guf_sort_impl.h | 1 + src/test/guf_str_impl.c | 2 + src/test/guf_utf8_impl.c | 7 - src/test/test_dict.hpp | 9 +- src/test/test_utf8.hpp | 252 ++++++++++++++++++++++- todo.txt | 5 +- 24 files changed, 1010 insertions(+), 612 deletions(-) create mode 100644 src/guf_str_view_type.h create mode 100644 src/test/guf_str_impl.c delete mode 100644 src/test/guf_utf8_impl.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 58e080f..d568885 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ endif () add_executable(libguf_example src/test/example.c src/test/guf_dict_impl.c) target_include_directories(libguf_example PRIVATE src src/test) -add_executable(libguf_test src/test/test.cpp src/test/guf_dbuf_impl.c src/test/guf_dict_impl.c src/test/guf_rand_impl.c src/test/guf_sort_impl.c src/test/guf_utf8_impl.c) +add_executable(libguf_test src/test/test.cpp src/test/guf_dbuf_impl.c src/test/guf_dict_impl.c src/test/guf_rand_impl.c src/test/guf_sort_impl.c src/test/guf_str_impl.c) target_include_directories(libguf_test PRIVATE src src/test) if (NOT DEFINED MSVC) diff --git a/src/guf_common.h b/src/guf_common.h index 0dfea9f..f6ca47d 100644 --- a/src/guf_common.h +++ b/src/guf_common.h @@ -6,6 +6,8 @@ #include #include +// #define GUF_HASH_32_BIT + /* // Copy- and move constructors: GUF_T_COPY: GUF_T *(*copy)(GUF_T *dst, const GUF_T *src, void *ctx); @@ -31,7 +33,7 @@ typedef enum guf_cpy_opt { #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)) +#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 diff --git a/src/guf_dbuf.h b/src/guf_dbuf.h index f3171e0..caa0616 100644 --- a/src/guf_dbuf.h +++ b/src/guf_dbuf.h @@ -1,3 +1,9 @@ +#if defined(GUF_DBUF_STATIC_IMPL) + #define GUF_DBUF_KWRDS static +#else + #define GUF_DBUF_KWRDS +#endif + #ifndef GUF_DBUF_H #define GUF_DBUF_H #include "guf_common.h" @@ -9,7 +15,7 @@ /* Template parameters: - GUF_T: The value type stored in the container. - - GUF_CNT_NAME: The typename of the resulting container (default: dbuf_GUF_T) + - GUF_DBUF_NAME: The typename of the resulting container (default: dbuf_GUF_T) - GUF_T_IS_INTEGRAL_TYPE: whether the type is an integral type (if defined, must not define COPY, MOVE, FREE and EQ) - GUF_T_COPY: cpy function with signature GUF_T *copy(GUF_T *dst, const GUF_T *src, void *ctx) (default: copy by value) @@ -25,25 +31,24 @@ #error "Undefined container template GUF_T" #endif -#ifndef GUF_CNT_NAME - #define GUF_CNT_NAME GUF_CAT(dbuf_, GUF_T) +#ifndef GUF_DBUF_NAME + #define GUF_DBUF_NAME GUF_CAT(dbuf_, GUF_T) #endif -#ifdef GUF_ONLY_TYPES - #undef GUF_ONLY_TYPES - typedef struct GUF_CNT_NAME { +#ifdef GUF_DBUF_ONLY_TYPES + typedef struct GUF_DBUF_NAME { GUF_T *data; ptrdiff_t size, capacity; guf_allocator *allocator; #ifdef GUF_CNT_WITH_ELEM_CTX void *elem_ctx; // NULL by default; is passed as the ctx argument to GUF_T_COPY, GUF_T_MOVE and GUF_T_FREE #endif - } GUF_CNT_NAME; + } GUF_DBUF_NAME; - typedef struct GUF_CAT(GUF_CNT_NAME, _iter) { + typedef struct GUF_CAT(GUF_DBUF_NAME, _iter) { GUF_T *ptr; GUF_T *base; // Not NULL For reverse iterators (unless dbuf->size == 0, then ptr and base are NULL for both iterator types) - } GUF_CAT(GUF_CNT_NAME, _iter); + } GUF_CAT(GUF_DBUF_NAME, _iter); #else // Used for the first growth if dbuf->capacity is zero. @@ -59,22 +64,16 @@ #error "Integral types do not need COPY, MOVE, FREE or EQ functions" #endif -#if defined(GUF_STATIC) || defined(GUF_IMPL_STATIC) - #define GUF_FN_KEYWORDS static -#else - #define GUF_FN_KEYWORDS -#endif +#if !defined(GUF_DBUF_IMPL) && !defined(GUF_DBUF_WITHOUT_TYPES) -#if !defined(GUF_IMPL) - -typedef struct GUF_CNT_NAME { +typedef struct GUF_DBUF_NAME { GUF_T *data; ptrdiff_t size, capacity; guf_allocator *allocator; #ifdef GUF_CNT_WITH_ELEM_CTX void *elem_ctx; // NULL by default; is passed as the ctx argument to GUF_T_COPY, GUF_T_MOVE and GUF_T_FREE #endif -} GUF_CNT_NAME; +} GUF_DBUF_NAME; /* - Regular iterator: base is always NULL @@ -84,93 +83,93 @@ typedef struct GUF_CNT_NAME { - rend(): base points to begin().ptr and ptr to NULL - reverse iterator for the first element of the container: base points to the second element, ptr points to the first element */ -typedef struct GUF_CAT(GUF_CNT_NAME, _iter) { +typedef struct GUF_CAT(GUF_DBUF_NAME, _iter) { GUF_T *ptr; GUF_T *base; // Not NULL For reverse iterators (unless dbuf->size == 0, then ptr and base are NULL for both iterator types) -} GUF_CAT(GUF_CNT_NAME, _iter); +} GUF_CAT(GUF_DBUF_NAME, _iter); #endif -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _valid)(const GUF_CNT_NAME* dbuf); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _valid)(const GUF_DBUF_NAME* dbuf); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_reserve)(GUF_CNT_NAME *dbuf, ptrdiff_t min_capacity, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _reserve)(GUF_CNT_NAME *dbuf, ptrdiff_t min_capacity); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_reserve)(GUF_DBUF_NAME *dbuf, ptrdiff_t min_capacity, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _reserve)(GUF_DBUF_NAME *dbuf, ptrdiff_t min_capacity); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_init)(GUF_CNT_NAME *dbuf, ptrdiff_t capacity, guf_allocator *allocator, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _init)(GUF_CNT_NAME *dbuf, ptrdiff_t start_cap, guf_allocator *allocator); -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _new)(guf_allocator *allocator); -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _try_new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator, guf_err *err); -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_init)(GUF_DBUF_NAME *dbuf, ptrdiff_t capacity, guf_allocator *allocator, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _init)(GUF_DBUF_NAME *dbuf, ptrdiff_t start_cap, guf_allocator *allocator); +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _new)(guf_allocator *allocator); +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _try_new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator, guf_err *err); +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator); #ifdef GUF_CNT_WITH_ELEM_CTX - GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _set_elem_ctx)(GUF_CNT_NAME *dbuf, void *elem_ctx); + GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _set_elem_ctx)(GUF_DBUF_NAME *dbuf, void *elem_ctx); #endif -GUF_FN_KEYWORDS void *GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(const GUF_CNT_NAME *dbuf); // Always returns NULL if GUF_CNT_WITH_ELEM_CTX is not defined +GUF_DBUF_KWRDS void *GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(const GUF_DBUF_NAME *dbuf); // Always returns NULL if GUF_CNT_WITH_ELEM_CTX is not defined -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _free)(GUF_CNT_NAME *dbuf, void *ctx); -GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _copy)(GUF_CNT_NAME *dst, const GUF_CNT_NAME *src, void *ctx); -GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _move)(GUF_CNT_NAME *dst, GUF_CNT_NAME *src, void *ctx); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _free)(GUF_DBUF_NAME *dbuf, void *ctx); +GUF_DBUF_KWRDS GUF_DBUF_NAME *GUF_CAT(GUF_DBUF_NAME, _copy)(GUF_DBUF_NAME *dst, const GUF_DBUF_NAME *src, void *ctx); +GUF_DBUF_KWRDS GUF_DBUF_NAME *GUF_CAT(GUF_DBUF_NAME, _move)(GUF_DBUF_NAME *dst, GUF_DBUF_NAME *src, void *ctx); -GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _try_get_next_capacity)(ptrdiff_t old_cap, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_grow_if_full)(GUF_CNT_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_shrink_to_fit)(GUF_CNT_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS ptrdiff_t GUF_CAT(GUF_DBUF_NAME, _try_get_next_capacity)(ptrdiff_t old_cap, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_grow_if_full)(GUF_DBUF_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_shrink_to_fit)(GUF_DBUF_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert)(GUF_CNT_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert)(GUF_CNT_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert_val)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert_val)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert)(GUF_DBUF_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert)(GUF_DBUF_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx); #ifdef GUF_T_COPY -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx); #endif -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push)(GUF_CNT_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push)(GUF_CNT_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push_val)(GUF_CNT_NAME *dbuf, GUF_T elem, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push_val)(GUF_CNT_NAME *dbuf, GUF_T elem); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push)(GUF_DBUF_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push)(GUF_DBUF_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push_val)(GUF_DBUF_NAME *dbuf, GUF_T elem); #ifdef GUF_T_COPY -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem); #endif -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _try_erase)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _erase)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx); -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_pop)(GUF_CNT_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _pop)(GUF_CNT_NAME *dbuf); -GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _try_pop_move)(GUF_CNT_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _pop_move)(GUF_CNT_NAME *dbuf); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _try_pop)(GUF_DBUF_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _pop)(GUF_DBUF_NAME *dbuf); +GUF_DBUF_KWRDS GUF_T GUF_CAT(GUF_DBUF_NAME, _try_pop_move)(GUF_DBUF_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS GUF_T GUF_CAT(GUF_DBUF_NAME, _pop_move)(GUF_DBUF_NAME *dbuf); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_at)(GUF_CNT_NAME *dbuf, ptrdiff_t idx, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _at)(GUF_CNT_NAME *dbuf, ptrdiff_t idx); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_front)(GUF_CNT_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _front)(GUF_CNT_NAME *dbuf); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_back)(GUF_CNT_NAME *dbuf, guf_err *err); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _back)(GUF_CNT_NAME *dbuf); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_at)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _at)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_front)(GUF_DBUF_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _front)(GUF_DBUF_NAME *dbuf); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_back)(GUF_DBUF_NAME *dbuf, guf_err *err); +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _back)(GUF_DBUF_NAME *dbuf); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _begin)(const GUF_CNT_NAME* dbuf); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _end)(const GUF_CNT_NAME* dbuf); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rbegin)(const GUF_CNT_NAME* dbuf); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rend)(const GUF_CNT_NAME* dbuf); -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _iter_is_end)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _begin)(const GUF_DBUF_NAME* dbuf); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _end)(const GUF_DBUF_NAME* dbuf); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _rbegin)(const GUF_DBUF_NAME* dbuf); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _rend)(const GUF_DBUF_NAME* dbuf); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _iter_is_end)(const GUF_DBUF_NAME* dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _reverse_iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx); -GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _iter_next)(const GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it, ptrdiff_t step); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _iter_at_idx)(const GUF_DBUF_NAME* dbuf, ptrdiff_t idx); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _reverse_iter_at_idx)(const GUF_DBUF_NAME* dbuf, ptrdiff_t idx); +GUF_DBUF_KWRDS ptrdiff_t GUF_CAT(GUF_DBUF_NAME, _iter_to_idx)(const GUF_DBUF_NAME* dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it); #if defined(GUF_T_IS_INTEGRAL_TYPE) || defined(GUF_T_EQ) -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, const GUF_T *needle); -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_val)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, GUF_T needle_val); -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _contains)(GUF_CNT_NAME *dbuf, const GUF_T *needle); -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _contains_val)(GUF_CNT_NAME *dbuf, GUF_T needle); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, const GUF_T *needle); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find_val)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, GUF_T needle_val); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _contains)(GUF_DBUF_NAME *dbuf, const GUF_T *needle); +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _contains_val)(GUF_DBUF_NAME *dbuf, GUF_T needle); #endif -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, bool (*predicate)(const GUF_T *)); +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find_if)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, bool (*predicate)(const GUF_T *)); -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_DBUF_IMPL) || defined(GUF_DBUF_IMPL_STATIC) -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _valid)(const GUF_CNT_NAME* dbuf) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _valid)(const GUF_DBUF_NAME* dbuf) { if (!dbuf) { return false; @@ -180,9 +179,9 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _valid)(const GUF_CNT_NAME* dbuf) return valid_data_ptr && valid_allocator && dbuf->capacity >= 0 && dbuf->size >= 0 && dbuf->size <= dbuf->capacity; } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_reserve)(GUF_CNT_NAME *dbuf, ptrdiff_t min_capacity, guf_err *err) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_reserve)(GUF_DBUF_NAME *dbuf, ptrdiff_t min_capacity, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(min_capacity >= 0); if (min_capacity <= dbuf->capacity || min_capacity == 0) { @@ -221,17 +220,17 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_reserve)(GUF_CNT_NAME *dbuf, ptr GUF_ASSERT(dbuf->data && dbuf->capacity); } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _reserve)(GUF_CNT_NAME *dbuf, ptrdiff_t min_capacity) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _reserve)(GUF_DBUF_NAME *dbuf, ptrdiff_t min_capacity) { - GUF_CAT(GUF_CNT_NAME, _try_reserve)(dbuf, min_capacity, NULL); + GUF_CAT(GUF_DBUF_NAME, _try_reserve)(dbuf, min_capacity, NULL); } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_init)(GUF_CNT_NAME *dbuf, ptrdiff_t capacity, guf_allocator *allocator, guf_err *err) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_init)(GUF_DBUF_NAME *dbuf, ptrdiff_t capacity, guf_allocator *allocator, guf_err *err) { GUF_ASSERT_RELEASE(dbuf); GUF_ASSERT_RELEASE(capacity >= 0); - if (dbuf->size != 0 || dbuf->capacity != 0 || dbuf->data || GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)) { + if (dbuf->size != 0 || dbuf->capacity != 0 || dbuf->data || GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)) { guf_err_set_or_panic(err, GUF_ERR_INVALID_ARG, GUF_ERR_MSG("in function dbuf_try_init: dbuf might have been already initialised")); return; } @@ -252,44 +251,44 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_init)(GUF_CNT_NAME *dbuf, ptrdif dbuf->data = NULL; guf_err_set_if_not_null(err, GUF_ERR_NONE); } else { - GUF_CAT(GUF_CNT_NAME, _try_reserve)(dbuf, capacity, err); + GUF_CAT(GUF_DBUF_NAME, _try_reserve)(dbuf, capacity, err); } } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _init)(GUF_CNT_NAME *dbuf, ptrdiff_t start_cap, guf_allocator *allocator) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _init)(GUF_DBUF_NAME *dbuf, ptrdiff_t start_cap, guf_allocator *allocator) { - GUF_CAT(GUF_CNT_NAME, _try_init)(dbuf, start_cap, allocator, NULL); + GUF_CAT(GUF_DBUF_NAME, _try_init)(dbuf, start_cap, allocator, NULL); } -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _new)(guf_allocator *allocator) +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _new)(guf_allocator *allocator) { - GUF_CNT_NAME dbuf = {0}; - GUF_CAT(GUF_CNT_NAME, _init)(&dbuf, 0, allocator); + GUF_DBUF_NAME dbuf = {0}; + GUF_CAT(GUF_DBUF_NAME, _init)(&dbuf, 0, allocator); GUF_ASSERT(dbuf.size == 0 && dbuf.capacity == 0); return dbuf; } -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _try_new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator, guf_err *err) +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _try_new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator, guf_err *err) { - GUF_CNT_NAME dbuf = {0}; + GUF_DBUF_NAME dbuf = {0}; - GUF_CAT(GUF_CNT_NAME, _try_init)(&dbuf, capacity, allocator, err); + GUF_CAT(GUF_DBUF_NAME, _try_init)(&dbuf, capacity, allocator, err); if (err && *err != GUF_ERR_NONE) { - return (GUF_CNT_NAME){0}; + return (GUF_DBUF_NAME){0}; } guf_err_set_if_not_null(err, GUF_ERR_NONE); return dbuf; } -GUF_FN_KEYWORDS GUF_CNT_NAME GUF_CAT(GUF_CNT_NAME, _new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator) +GUF_DBUF_KWRDS GUF_DBUF_NAME GUF_CAT(GUF_DBUF_NAME, _new_with_capacity)(ptrdiff_t capacity, guf_allocator *allocator) { - return GUF_CAT(GUF_CNT_NAME, _try_new_with_capacity)(capacity, allocator, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_new_with_capacity)(capacity, allocator, NULL); } #ifdef GUF_CNT_WITH_ELEM_CTX -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _set_elem_ctx)(GUF_CNT_NAME *dbuf, void *elem_ctx) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _set_elem_ctx)(GUF_DBUF_NAME *dbuf, void *elem_ctx) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); #ifdef GUF_CNT_WITH_ELEM_CTX dbuf->elem_ctx = elem_ctx; #else @@ -299,7 +298,7 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _set_elem_ctx)(GUF_CNT_NAME *dbuf, vo } #endif -GUF_FN_KEYWORDS void *GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(const GUF_CNT_NAME *dbuf) +GUF_DBUF_KWRDS void *GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(const GUF_DBUF_NAME *dbuf) { #ifdef GUF_CNT_WITH_ELEM_CTX return dbuf->elem_ctx; @@ -309,10 +308,10 @@ GUF_FN_KEYWORDS void *GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(const GUF_CNT_NAME *d #endif } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _free)(GUF_CNT_NAME *dbuf, void *ctx) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _free)(GUF_DBUF_NAME *dbuf, void *ctx) { (void)ctx; - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->capacity == 0) { GUF_ASSERT_RELEASE(!dbuf->data); GUF_ASSERT_RELEASE(dbuf->size == 0); @@ -322,7 +321,7 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _free)(GUF_CNT_NAME *dbuf, void *ctx) #ifdef GUF_T_FREE for (ptrdiff_t idx = 0; idx < dbuf->size; ++idx) { - GUF_T_FREE(dbuf->data + idx, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + GUF_T_FREE(dbuf->data + idx, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); } #endif @@ -335,10 +334,10 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _free)(GUF_CNT_NAME *dbuf, void *ctx) #endif } -GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _copy)(GUF_CNT_NAME *dst, const GUF_CNT_NAME *src, void *ctx) +GUF_DBUF_KWRDS GUF_DBUF_NAME *GUF_CAT(GUF_DBUF_NAME, _copy)(GUF_DBUF_NAME *dst, const GUF_DBUF_NAME *src, void *ctx) { (void)ctx; - if (!dst || !src || GUF_CAT(GUF_CNT_NAME, _valid)(src)) { + if (!dst || !src || GUF_CAT(GUF_DBUF_NAME, _valid)(src)) { return NULL; } @@ -376,7 +375,7 @@ GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _copy)(GUF_CNT_NAME *dst, co for (ptrdiff_t i = 0; i < src->size; ++i) { #ifdef GUF_T_COPY - GUF_T *cpy_success = GUF_T_COPY(dst->data + i, src->data + i, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(src)); + GUF_T *cpy_success = GUF_T_COPY(dst->data + i, src->data + i, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(src)); if (!cpy_success) { dst->size = i; return NULL; @@ -389,7 +388,7 @@ GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _copy)(GUF_CNT_NAME *dst, co } } -GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _move)(GUF_CNT_NAME *dst, GUF_CNT_NAME *src, void *ctx) +GUF_DBUF_KWRDS GUF_DBUF_NAME *GUF_CAT(GUF_DBUF_NAME, _move)(GUF_DBUF_NAME *dst, GUF_DBUF_NAME *src, void *ctx) { (void)ctx; if (!dst || !src) { @@ -409,7 +408,7 @@ GUF_FN_KEYWORDS GUF_CNT_NAME *GUF_CAT(GUF_CNT_NAME, _move)(GUF_CNT_NAME *dst, GU return dst; } -GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _try_get_next_capacity)(ptrdiff_t old_cap, guf_err *err) +GUF_DBUF_KWRDS ptrdiff_t GUF_CAT(GUF_DBUF_NAME, _try_get_next_capacity)(ptrdiff_t old_cap, guf_err *err) { GUF_ASSERT_RELEASE(old_cap >= 0); size_t new_cap = 0; @@ -436,18 +435,18 @@ GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _try_get_next_capacity)(ptrdiff_ } } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_grow_if_full)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_grow_if_full)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(dbuf->capacity >= 0 && dbuf->size >= 0); if (dbuf->size == dbuf->capacity) { - ptrdiff_t next_cap = GUF_CAT(GUF_CNT_NAME, _try_get_next_capacity)(dbuf->capacity, err); + ptrdiff_t next_cap = GUF_CAT(GUF_DBUF_NAME, _try_get_next_capacity)(dbuf->capacity, err); if (err && *err != GUF_ERR_NONE) { return; } GUF_ASSERT(next_cap > 0); - GUF_CAT(GUF_CNT_NAME, _try_reserve)(dbuf, next_cap, err); + GUF_CAT(GUF_DBUF_NAME, _try_reserve)(dbuf, next_cap, err); if (err && *err != GUF_ERR_NONE) { return; } @@ -457,7 +456,7 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_grow_if_full)(GUF_CNT_NAME *dbuf guf_err_set_if_not_null(err, GUF_ERR_NONE); } -static inline bool GUF_CAT(GUF_CNT_NAME, _copy_opt_available)(guf_cpy_opt cpy_opt) +static inline bool GUF_CAT(GUF_DBUF_NAME, _copy_opt_available)(guf_cpy_opt cpy_opt) { if (cpy_opt == GUF_CPY_DEEP) { #ifdef GUF_T_COPY @@ -478,16 +477,16 @@ static inline bool GUF_CAT(GUF_CNT_NAME, _copy_opt_available)(guf_cpy_opt cpy_op } } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert)(GUF_CNT_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert)(GUF_DBUF_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt, guf_err *err) { - GUF_ASSERT(GUF_CAT(GUF_CNT_NAME,_valid)(dbuf)); + GUF_ASSERT(GUF_CAT(GUF_DBUF_NAME,_valid)(dbuf)); if (idx < 0 || idx > dbuf->size) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_insert")); return NULL; } - GUF_CAT(GUF_CNT_NAME, _try_grow_if_full)(dbuf, err); + GUF_CAT(GUF_DBUF_NAME, _try_grow_if_full)(dbuf, err); if (err && *err != GUF_ERR_NONE) { return NULL; } @@ -499,18 +498,18 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert)(GUF_CNT_NAME *dbuf, GU GUF_T *dst = dbuf->data + idx; - if (!GUF_CAT(GUF_CNT_NAME, _copy_opt_available)(cpy_opt)) { - guf_err_set_or_panic(err, GUF_ERR_INVALID_ARG, GUF_ERR_MSG("in function " GUF_STRINGIFY(GUF_CAT(GUF_CNT_NAME, _copy_opt_available)) ": cpy_opt unavailable")); + if (!GUF_CAT(GUF_DBUF_NAME, _copy_opt_available)(cpy_opt)) { + guf_err_set_or_panic(err, GUF_ERR_INVALID_ARG, GUF_ERR_MSG("in function " GUF_STRINGIFY(GUF_CAT(GUF_DBUF_NAME, _copy_opt_available)) ": cpy_opt unavailable")); return NULL; } else if (cpy_opt == GUF_CPY_DEEP) { #ifdef GUF_T_COPY - dst = GUF_T_COPY(dst, elem, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + dst = GUF_T_COPY(dst, elem, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); #else GUF_ASSERT_RELEASE(false); #endif } else if (cpy_opt == GUF_CPY_MOVE) { #ifdef GUF_T_MOVE - dst = GUF_T_MOVE(dst, elem, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + dst = GUF_T_MOVE(dst, elem, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); #else GUF_ASSERT_RELEASE(false); #endif @@ -533,71 +532,71 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert)(GUF_CNT_NAME *dbuf, GU } } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert)(GUF_CNT_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert)(GUF_DBUF_NAME *dbuf, GUF_T *elem, ptrdiff_t idx, guf_cpy_opt cpy_opt) { - return GUF_CAT(GUF_CNT_NAME, _try_insert)(dbuf, elem, idx, cpy_opt, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_insert)(dbuf, elem, idx, cpy_opt, NULL); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert_val)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err) { - return GUF_CAT(GUF_CNT_NAME, _try_insert)(dbuf, &elem, idx, GUF_CPY_VALUE, err); + return GUF_CAT(GUF_DBUF_NAME, _try_insert)(dbuf, &elem, idx, GUF_CPY_VALUE, err); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert_val)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx) { - return GUF_CAT(GUF_CNT_NAME, _try_insert_val)(dbuf, elem, idx, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_insert_val)(dbuf, elem, idx, NULL); } #ifdef GUF_T_COPY -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_insert_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_insert_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx, guf_err *err) { - return GUF_CAT(GUF_CNT_NAME, _try_insert)(dbuf, &elem, idx, GUF_CPY_DEEP, err); + return GUF_CAT(GUF_DBUF_NAME, _try_insert)(dbuf, &elem, idx, GUF_CPY_DEEP, err); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _insert_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, ptrdiff_t idx) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _insert_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, ptrdiff_t idx) { - return GUF_CAT(GUF_CNT_NAME, _try_insert_val_cpy)(dbuf, elem, idx, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_insert_val_cpy)(dbuf, elem, idx, NULL); } #endif -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push)(GUF_CNT_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push)(GUF_DBUF_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt, guf_err *err) { - GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); - return GUF_CAT(GUF_CNT_NAME, _try_insert)(dbuf, elem, dbuf->size, cpy_opt, err); + GUF_ASSERT(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); + return GUF_CAT(GUF_DBUF_NAME, _try_insert)(dbuf, elem, dbuf->size, cpy_opt, err); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push)(GUF_CNT_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push)(GUF_DBUF_NAME *dbuf, GUF_T *elem, guf_cpy_opt cpy_opt) { - return GUF_CAT(GUF_CNT_NAME, _try_push)(dbuf, elem, cpy_opt, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_push)(dbuf, elem, cpy_opt, NULL); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push_val)(GUF_CNT_NAME *dbuf, GUF_T elem, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push_val)(GUF_DBUF_NAME *dbuf, GUF_T elem, guf_err *err) { - return GUF_CAT(GUF_CNT_NAME, _try_push)(dbuf, &elem, GUF_CPY_VALUE, err); + return GUF_CAT(GUF_DBUF_NAME, _try_push)(dbuf, &elem, GUF_CPY_VALUE, err); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push_val)(GUF_CNT_NAME *dbuf, GUF_T elem) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push_val)(GUF_DBUF_NAME *dbuf, GUF_T elem) { - return GUF_CAT(GUF_CNT_NAME, _try_push_val)(dbuf, elem, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_push_val)(dbuf, elem, NULL); } #ifdef GUF_T_COPY -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_push_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_push_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem, guf_err *err) { - return GUF_CAT(GUF_CNT_NAME, _try_push)(dbuf, &elem, GUF_CPY_DEEP, err); + return GUF_CAT(GUF_DBUF_NAME, _try_push)(dbuf, &elem, GUF_CPY_DEEP, err); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _push_val_cpy)(GUF_CNT_NAME *dbuf, GUF_T elem) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _push_val_cpy)(GUF_DBUF_NAME *dbuf, GUF_T elem) { - return GUF_CAT(GUF_CNT_NAME, _try_push_val_cpy)(dbuf, elem, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_push_val_cpy)(dbuf, elem, NULL); } #endif -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx, guf_err *err) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _try_erase)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_erase: cannot erase from empty buffer")); @@ -609,7 +608,7 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_erase)(GUF_CNT_NAME *dbuf, ptrdi } #ifdef GUF_T_FREE - GUF_T_FREE(dbuf->data + idx, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + GUF_T_FREE(dbuf->data + idx, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); #endif for (ptrdiff_t free_idx = idx; free_idx < dbuf->size - 1; ++free_idx) { // Make space by moving elements to the left if necessary. @@ -621,14 +620,14 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_erase)(GUF_CNT_NAME *dbuf, ptrdi return true; } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _erase)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx) { - GUF_CAT(GUF_CNT_NAME, _try_erase)(dbuf, idx, NULL); + GUF_CAT(GUF_DBUF_NAME, _try_erase)(dbuf, idx, NULL); } -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_pop)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _try_pop)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_pop: Cannot pop from empty dbuf")); @@ -637,7 +636,7 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_pop)(GUF_CNT_NAME *dbuf, guf_err #ifdef GUF_T_FREE GUF_T *popped = dbuf->data + --dbuf->size; - GUF_T_FREE(popped, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + GUF_T_FREE(popped, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); #else --dbuf->size; #endif @@ -646,14 +645,14 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _try_pop)(GUF_CNT_NAME *dbuf, guf_err return true; } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _pop)(GUF_CNT_NAME *dbuf) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _pop)(GUF_DBUF_NAME *dbuf) { - GUF_CAT(GUF_CNT_NAME, _try_pop)(dbuf, NULL); + GUF_CAT(GUF_DBUF_NAME, _try_pop)(dbuf, NULL); } -GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _try_pop_move)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS GUF_T GUF_CAT(GUF_DBUF_NAME, _try_pop_move)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_pop_move: Cannot pop from empty dbuf")); @@ -666,7 +665,7 @@ GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _try_pop_move)(GUF_CNT_NAME *dbuf, g GUF_T popped_val; GUF_T *dst = &popped_val; #if defined(GUF_T_MOVE) - dst = GUF_T_MOVE(dst, popped, GUF_CAT(GUF_CNT_NAME, _get_elem_ctx)(dbuf)); + dst = GUF_T_MOVE(dst, popped, GUF_CAT(GUF_DBUF_NAME, _get_elem_ctx)(dbuf)); #else *dst = *popped; memset(popped, 0, sizeof(GUF_T)); @@ -683,15 +682,15 @@ GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _try_pop_move)(GUF_CNT_NAME *dbuf, g } } -GUF_FN_KEYWORDS GUF_T GUF_CAT(GUF_CNT_NAME, _pop_move)(GUF_CNT_NAME *dbuf) +GUF_DBUF_KWRDS GUF_T GUF_CAT(GUF_DBUF_NAME, _pop_move)(GUF_DBUF_NAME *dbuf) { - return GUF_CAT(GUF_CNT_NAME, _try_pop_move)(dbuf, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_pop_move)(dbuf, NULL); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_at)(GUF_CNT_NAME *dbuf, ptrdiff_t idx, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_at)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_at: dbuf is empty")); @@ -706,15 +705,15 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_at)(GUF_CNT_NAME *dbuf, ptrdif return dbuf->data + idx; } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _at)(GUF_CNT_NAME *dbuf, ptrdiff_t idx) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _at)(GUF_DBUF_NAME *dbuf, ptrdiff_t idx) { - return GUF_CAT(GUF_CNT_NAME, _try_at)(dbuf, idx, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_at)(dbuf, idx, NULL); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_front)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_front)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_front: dbuf is empty")); @@ -723,15 +722,15 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_front)(GUF_CNT_NAME *dbuf, guf return dbuf->data + 0; } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _front)(GUF_CNT_NAME *dbuf) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _front)(GUF_DBUF_NAME *dbuf) { - return GUF_CAT(GUF_CNT_NAME, _try_front)(dbuf, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_front)(dbuf, NULL); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_back)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _try_back)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (dbuf->size == 0) { guf_err_set_or_panic(err, GUF_ERR_IDX_RANGE, GUF_ERR_MSG("in function dbuf_try_back: dbuf is empty")); @@ -741,14 +740,14 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _try_back)(GUF_CNT_NAME *dbuf, guf_ return dbuf->data + (dbuf->size - 1); } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_CNT_NAME, _back)(GUF_CNT_NAME *dbuf) +GUF_DBUF_KWRDS GUF_T *GUF_CAT(GUF_DBUF_NAME, _back)(GUF_DBUF_NAME *dbuf) { - return GUF_CAT(GUF_CNT_NAME, _try_back)(dbuf, NULL); + return GUF_CAT(GUF_DBUF_NAME, _try_back)(dbuf, NULL); } -GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_shrink_to_fit)(GUF_CNT_NAME *dbuf, guf_err *err) +GUF_DBUF_KWRDS void GUF_CAT(GUF_DBUF_NAME, _try_shrink_to_fit)(GUF_DBUF_NAME *dbuf, guf_err *err) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); const ptrdiff_t new_capacity = dbuf->size; if (new_capacity == dbuf->capacity || (!dbuf->data && !dbuf->capacity)) { guf_err_set_if_not_null(err, GUF_ERR_NONE); @@ -774,55 +773,55 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_shrink_to_fit)(GUF_CNT_NAME *dbu /* Iterator functions */ -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _begin)(const GUF_CNT_NAME* dbuf) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _begin)(const GUF_DBUF_NAME* dbuf) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); - return (GUF_CAT(GUF_CNT_NAME, _iter)) { + return (GUF_CAT(GUF_DBUF_NAME, _iter)) { .ptr = dbuf->data && dbuf->size ? dbuf->data : NULL, .base = NULL }; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _end)(const GUF_CNT_NAME* dbuf) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _end)(const GUF_DBUF_NAME* dbuf) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); - return (GUF_CAT(GUF_CNT_NAME, _iter)) { + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); + return (GUF_CAT(GUF_DBUF_NAME, _iter)) { .ptr = dbuf->data && dbuf->size ? dbuf->data + dbuf->size : NULL, .base = NULL }; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rbegin)(const GUF_CNT_NAME* dbuf) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _rbegin)(const GUF_DBUF_NAME* dbuf) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); - return (GUF_CAT(GUF_CNT_NAME, _iter)) { + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); + return (GUF_CAT(GUF_DBUF_NAME, _iter)) { .base = dbuf->data && dbuf->size ? dbuf->data + dbuf->size : NULL, .ptr = dbuf->data && dbuf->size ? dbuf->data + (dbuf->size - 1) : NULL }; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rend)(const GUF_CNT_NAME* dbuf) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _rend)(const GUF_DBUF_NAME* dbuf) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); - return (GUF_CAT(GUF_CNT_NAME, _iter)) { + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); + return (GUF_CAT(GUF_DBUF_NAME, _iter)) { .base = dbuf->data && dbuf->size ? dbuf->data : NULL, .ptr = NULL }; } -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _iter_is_end)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _iter_is_end)(const GUF_DBUF_NAME* dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it) { const bool is_reverse_it = it.base != NULL; - const GUF_CAT(GUF_CNT_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_CNT_NAME, _rend)(dbuf) : GUF_CAT(GUF_CNT_NAME, _end)(dbuf); + const GUF_CAT(GUF_DBUF_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_DBUF_NAME, _rend)(dbuf) : GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); return it.ptr == dbuf_end_it.ptr; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _iter_at_idx)(const GUF_DBUF_NAME* dbuf, ptrdiff_t idx) { - GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); - GUF_CAT(GUF_CNT_NAME, _iter) it; + GUF_CAT(GUF_DBUF_NAME, _iter) it; it.base = NULL; if (!dbuf->data || !dbuf->size) { @@ -841,9 +840,9 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_at_idx return it; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _reverse_iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _reverse_iter_at_idx)(const GUF_DBUF_NAME* dbuf, ptrdiff_t idx) { - GUF_CAT(GUF_CNT_NAME, _iter) it = GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(dbuf, idx); + GUF_CAT(GUF_DBUF_NAME, _iter) it = GUF_CAT(GUF_DBUF_NAME, _iter_at_idx)(dbuf, idx); if (!dbuf->data || !dbuf->size) { it.base = NULL; @@ -864,16 +863,16 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _reverse_ite return it; } -GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it) +GUF_DBUF_KWRDS ptrdiff_t GUF_CAT(GUF_DBUF_NAME, _iter_to_idx)(const GUF_DBUF_NAME* dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it) { - GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if ((!it.ptr && !it.base) || !dbuf->data || !dbuf->size) { return GUF_CNT_NPOS; } const bool is_reverse_it = it.base != NULL; - const GUF_CAT(GUF_CNT_NAME, _iter) end_it = is_reverse_it ? GUF_CAT(GUF_CNT_NAME, _rend)(dbuf) : GUF_CAT(GUF_CNT_NAME, _end)(dbuf); + const GUF_CAT(GUF_DBUF_NAME, _iter) end_it = is_reverse_it ? GUF_CAT(GUF_DBUF_NAME, _rend)(dbuf) : GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); if (it.ptr == end_it.ptr) { return is_reverse_it ? -1 : dbuf->size; @@ -886,9 +885,9 @@ GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(const GUF_CNT_NAME } } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _iter_next)(const GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) it, ptrdiff_t step) { - GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); if (!dbuf->size || !dbuf->data || (!it.base && !it.ptr)) { it.ptr = NULL; @@ -921,14 +920,14 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(c } #if defined(GUF_T_IS_INTEGRAL_TYPE) || defined(GUF_T_EQ) -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, const GUF_T *needle) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, const GUF_T *needle) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(needle); const bool is_reverse_it = begin.base != NULL; GUF_ASSERT_RELEASE(is_reverse_it == (end.base != NULL)); // begin and end must be the same iterator type. - const GUF_CAT(GUF_CNT_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_CNT_NAME, _rend)(dbuf) : GUF_CAT(GUF_CNT_NAME, _end)(dbuf); + const GUF_CAT(GUF_DBUF_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_DBUF_NAME, _rend)(dbuf) : GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); if (!dbuf->data || !dbuf->size || (!begin.ptr && !begin.base) || (!end.ptr && !end.base)) { return dbuf_end_it; @@ -937,7 +936,7 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CN return dbuf_end_it; } - for (GUF_CAT(GUF_CNT_NAME, _iter) it = begin; it.ptr != end.ptr && it.ptr != NULL; it = GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) { + for (GUF_CAT(GUF_DBUF_NAME, _iter) it = begin; it.ptr != end.ptr && it.ptr != NULL; it = GUF_CAT(GUF_DBUF_NAME, _iter_next)(dbuf, it, 1)) { #ifdef GUF_T_EQ if (GUF_T_EQ(it.ptr, needle)) { return it; @@ -951,32 +950,32 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CN return dbuf_end_it; } -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_val)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, GUF_T needle_val) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find_val)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, GUF_T needle_val) { - return GUF_CAT(GUF_CNT_NAME, _find)(dbuf, begin, end, &needle_val); + return GUF_CAT(GUF_DBUF_NAME, _find)(dbuf, begin, end, &needle_val); } -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _contains)(GUF_CNT_NAME *dbuf, const GUF_T *needle) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _contains)(GUF_DBUF_NAME *dbuf, const GUF_T *needle) { - GUF_CAT(GUF_CNT_NAME, _iter) beg = GUF_CAT(GUF_CNT_NAME, _begin)(dbuf); - GUF_CAT(GUF_CNT_NAME, _iter) end = GUF_CAT(GUF_CNT_NAME, _end)(dbuf); - return GUF_CAT(GUF_CNT_NAME, _find)(dbuf, beg, end, needle).ptr != end.ptr; + GUF_CAT(GUF_DBUF_NAME, _iter) beg = GUF_CAT(GUF_DBUF_NAME, _begin)(dbuf); + GUF_CAT(GUF_DBUF_NAME, _iter) end = GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); + return GUF_CAT(GUF_DBUF_NAME, _find)(dbuf, beg, end, needle).ptr != end.ptr; } -GUF_FN_KEYWORDS bool GUF_CAT(GUF_CNT_NAME, _contains_val)(GUF_CNT_NAME *dbuf, GUF_T needle) +GUF_DBUF_KWRDS bool GUF_CAT(GUF_DBUF_NAME, _contains_val)(GUF_DBUF_NAME *dbuf, GUF_T needle) { - return GUF_CAT(GUF_CNT_NAME, _contains)(dbuf, &needle); + return GUF_CAT(GUF_DBUF_NAME, _contains)(dbuf, &needle); } #endif -GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, bool (*predicate)(const GUF_T *)) +GUF_DBUF_KWRDS GUF_CAT(GUF_DBUF_NAME, _iter) GUF_CAT(GUF_DBUF_NAME, _find_if)(GUF_DBUF_NAME *dbuf, GUF_CAT(GUF_DBUF_NAME, _iter) begin, GUF_CAT(GUF_DBUF_NAME, _iter) end, bool (*predicate)(const GUF_T *)) { - GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); + GUF_ASSERT_RELEASE(GUF_CAT(GUF_DBUF_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(predicate); const bool is_reverse_it = begin.base != NULL; GUF_ASSERT_RELEASE(is_reverse_it == (end.base != NULL)); // begin and end must be the same iterator type. - const GUF_CAT(GUF_CNT_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_CNT_NAME, _rend)(dbuf) : GUF_CAT(GUF_CNT_NAME, _end)(dbuf); + const GUF_CAT(GUF_DBUF_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_DBUF_NAME, _rend)(dbuf) : GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); if (!dbuf->data || !dbuf->size || (!begin.ptr && !begin.base) || (!end.ptr && !end.base)) { return dbuf_end_it; @@ -985,22 +984,22 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF return dbuf_end_it; } - for (GUF_CAT(GUF_CNT_NAME, _iter) it = begin; it.ptr != end.ptr && it.ptr != NULL; GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) { + for (GUF_CAT(GUF_DBUF_NAME, _iter) it = begin; it.ptr != end.ptr && it.ptr != NULL; GUF_CAT(GUF_DBUF_NAME, _iter_next)(dbuf, it, 1)) { if (predicate(it.ptr)) { return it; } } - return GUF_CAT(GUF_CNT_NAME, _end)(dbuf); + return GUF_CAT(GUF_DBUF_NAME, _end)(dbuf); } #endif /* end #ifdef GUF_IMPL */ -#endif /* end GUF_ONLY_TYPES */ +#endif /* end GUF_DBUF_ONLY_TYPES */ #undef GUF_DBUF_INITIAL_CAP #undef GUF_DBUF_USE_GROWTH_FAC_ONE_POINT_FIVE -#undef GUF_CNT_NAME +#undef GUF_DBUF_NAME #undef GUF_CNT_WITH_ELEM_CTX #undef GUF_T @@ -1010,7 +1009,9 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF #undef GUF_T_EQ #undef GUF_T_IS_INTEGRAL_TYPE -#undef GUF_FN_KEYWORDS -#undef GUF_IMPL -#undef GUF_IMPL_STATIC -#undef GUF_STATIC +#undef GUF_DBUF_KWRDS +#undef GUF_DBUF_IMPL +#undef GUF_DBUF_IMPL_STATIC + +#undef GUF_DBUF_WITHOUT_TYPES +#undef GUF_DBUF_ONLY_TYPES diff --git a/src/guf_dict.h b/src/guf_dict.h index b0770a5..52c0bcb 100755 --- a/src/guf_dict.h +++ b/src/guf_dict.h @@ -1,28 +1,14 @@ -#ifdef GUF_STATIC - #define GUF_DICT_STATIC - #undef GUF_STATIC -#endif - -#ifdef GUF_IMPL - #define GUF_DICT_IMPL - #undef GUF_IMPL -#endif - -#ifdef GUF_IMPL_STATIC - #define GUF_DICT_IMPL_STATIC - #undef GUF_IMPL_STATIC -#endif - -#if defined(GUF_DICT_STATIC) || defined(GUF_DICT_IMPL_STATIC) - #define GUF_DICT_FN_KEYWORDS static +#if defined(GUF_DICT_IMPL_STATIC) + #define GUF_DICT_KWRDS static #else - #define GUF_DICT_FN_KEYWORDS + #define GUF_DICT_KWRDS #endif #ifndef GUF_DICT_H #define GUF_DICT_H #include "guf_common.h" #include "guf_alloc.h" + #include "guf_hash.h" typedef struct guf_dict_kv_meta_32 { uint32_t kv_idx; // Index into the kv_elems dbuf. @@ -33,6 +19,11 @@ uint64_t kv_idx; // Index into the kv_elems dbuf. uint64_t key_hash; } guf_dict_kv_meta_64; + + typedef struct guf_dict_kv_meta { + guf_hash_size_t kv_idx; // Index into the kv_elems dbuf. + guf_hash_size_t key_hash; + } guf_dict_kv_meta; #endif #ifndef GUF_DICT_KEY_T @@ -51,18 +42,23 @@ #define GUF_DICT_IS_SET #endif -#ifdef GUF_DICT_32_BIT +#if defined(GUF_DICT_32_BIT) #define GUF_DICT_SIZE_T uint32_t #define GUF_DICT_KV_META_T guf_dict_kv_meta_32 #define GUF_DICT_KV_IDX_NULL UINT32_MAX -#else +#elif defined(GUF_DICT_64_BIT) #define GUF_DICT_SIZE_T uint64_t #define GUF_DICT_KV_META_T guf_dict_kv_meta_64 #define GUF_DICT_KV_IDX_NULL UINT64_MAX +#else + #define GUF_DICT_SIZE_T guf_hash_size_t + #define GUF_DICT_KV_META_T guf_dict_kv_meta + #define GUF_DICT_KV_IDX_NULL GUF_HASH_MAX #endif #define GUF_DICT_KV_IDX_TOMBSTONE (GUF_DICT_KV_IDX_NULL - 1) -#define GUF_DICT_MAX_SIZE (GUF_DICT_KV_IDX_TOMBSTONE - 1) +// TODO +#define GUF_DICT_MAX_SIZE GUF_MIN(GUF_DICT_KV_IDX_TOMBSTONE - 1, PTRDIFF_MAX) // #ifndef GUF_DICT_KEY_LOOKUP_T // #define GUF_DICT_KEY_LOOKUP_T GUF_DICT_KEY_T @@ -97,8 +93,8 @@ typedef struct GUF_DICT_KV_NAME { } GUF_DICT_KV_NAME; #define GUF_T GUF_DICT_KV_NAME -#define GUF_CNT_NAME GUF_DICT_KV_DBUF -#define GUF_ONLY_TYPES +#define GUF_DBUF_NAME GUF_DICT_KV_DBUF +#define GUF_DBUF_ONLY_TYPES #include "guf_dbuf.h" typedef struct GUF_DICT_NAME { @@ -112,48 +108,48 @@ typedef GUF_CAT(GUF_DICT_KV_DBUF, _iter) GUF_CAT(GUF_DICT_NAME, _iter); #endif -GUF_DICT_FN_KEYWORDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _try_init)(GUF_DICT_NAME *ht, guf_allocator *alloc, guf_err *err); -GUF_DICT_FN_KEYWORDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _init)(GUF_DICT_NAME *ht, guf_allocator *alloc); +GUF_DICT_KWRDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _try_init)(GUF_DICT_NAME *ht, guf_allocator *alloc, guf_err *err); +GUF_DICT_KWRDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _init)(GUF_DICT_NAME *ht, guf_allocator *alloc); -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _free)(GUF_DICT_NAME *ht, void *ctx); +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _free)(GUF_DICT_NAME *ht, void *ctx); -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err); -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt); -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _try_insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err); -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt); +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err); +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt); +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _try_insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err); +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt); -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); #ifdef GUF_DICT_VAL_T - GUF_DICT_FN_KEYWORDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); - GUF_DICT_FN_KEYWORDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); + GUF_DICT_KWRDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); + GUF_DICT_KWRDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); #endif -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _contains_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key); +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _contains_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key); -GUF_DICT_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _size)(const GUF_DICT_NAME *ht); -GUF_DICT_FN_KEYWORDS double GUF_CAT(GUF_DICT_NAME, _load_factor)(const GUF_DICT_NAME *ht); +GUF_DICT_KWRDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _size)(const GUF_DICT_NAME *ht); +GUF_DICT_KWRDS double GUF_CAT(GUF_DICT_NAME, _load_factor)(const GUF_DICT_NAME *ht); /* Iterator functions */ -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _begin)(const GUF_DICT_NAME* ht); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _end)(const GUF_DICT_NAME* ht); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rbegin)(const GUF_DICT_NAME* ht); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rend)(const GUF_DICT_NAME* ht); -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _iter_is_end)(const GUF_DICT_NAME* ht, GUF_CAT(GUF_DICT_NAME, _iter) it); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _begin)(const GUF_DICT_NAME* ht); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _end)(const GUF_DICT_NAME* ht); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rbegin)(const GUF_DICT_NAME* ht); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rend)(const GUF_DICT_NAME* ht); +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _iter_is_end)(const GUF_DICT_NAME* ht, GUF_CAT(GUF_DICT_NAME, _iter) it); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_next)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it, ptrdiff_t step); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx); -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _reverse_iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx); -GUF_DICT_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _iter_to_idx)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_next)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it, ptrdiff_t step); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx); +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _reverse_iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx); +GUF_DICT_KWRDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _iter_to_idx)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it); #if defined(GUF_DICT_VAL_T) && (defined(GUF_DICT_VAL_T_EQ) || defined(GUF_DICT_VAL_T_IS_INTEGRAL_TYPE)) - GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, const GUF_DICT_VAL_T *needle_val); - GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_val_arg)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, GUF_DICT_VAL_T needle_val); + GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, const GUF_DICT_VAL_T *needle_val); + GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_val_arg)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, GUF_DICT_VAL_T needle_val); #endif #if defined(GUF_DICT_VAL_T) - GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_if)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, bool (*predicate)(const GUF_DICT_VAL_T *)); + GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_if)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, bool (*predicate)(const GUF_DICT_VAL_T *)); #endif @@ -178,12 +174,12 @@ static inline void GUF_CAT(GUF_DICT_KV_NAME, _free)(GUF_DICT_KV_NAME *kv, void * } #define GUF_T GUF_DICT_KV_NAME #define GUF_T_FREE GUF_CAT(GUF_DICT_KV_NAME, _free) -#define GUF_CNT_NAME GUF_DICT_KV_DBUF -#define GUF_STATIC -#define GUF_IMPL +#define GUF_DBUF_NAME GUF_DICT_KV_DBUF +#define GUF_DBUF_WITHOUT_TYPES +#define GUF_DBUF_IMPL_STATIC #include "guf_dbuf.h" -GUF_DICT_FN_KEYWORDS double GUF_CAT(GUF_DICT_NAME, _load_factor)(const GUF_DICT_NAME *ht) +GUF_DICT_KWRDS double GUF_CAT(GUF_DICT_NAME, _load_factor)(const GUF_DICT_NAME *ht) { if (ht->kv_indices_cap == 0) { return 1; @@ -193,7 +189,7 @@ GUF_DICT_FN_KEYWORDS double GUF_CAT(GUF_DICT_NAME, _load_factor)(const GUF_DICT_ return (double)occupied_count / (double)ht->kv_indices_cap; } -GUF_DICT_FN_KEYWORDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _try_init)(GUF_DICT_NAME *ht, guf_allocator *alloc, guf_err *err) +GUF_DICT_KWRDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _try_init)(GUF_DICT_NAME *ht, guf_allocator *alloc, guf_err *err) { if (!ht || !alloc) { guf_err_set_or_panic(err, GUF_ERR_INVALID_ARG, GUF_ERR_MSG("in dict_try_init: ht or alloc NULL")); @@ -214,12 +210,12 @@ GUF_DICT_FN_KEYWORDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _try_init)(GUF_DICT_N return ht; } -GUF_DICT_FN_KEYWORDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _init)(GUF_DICT_NAME *ht, guf_allocator *alloc) +GUF_DICT_KWRDS GUF_DICT_NAME *GUF_CAT(GUF_DICT_NAME, _init)(GUF_DICT_NAME *ht, guf_allocator *alloc) { return GUF_CAT(GUF_DICT_NAME, _try_init)(ht, alloc, NULL); } -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _valid)(const GUF_DICT_NAME *ht) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _valid)(const GUF_DICT_NAME *ht) { if (!ht) { return false; @@ -230,7 +226,7 @@ GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _valid)(const GUF_DICT_NAME *ht return kv_dbuf_valid && kv_meta_buf_valid && count_valid; } -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _free)(GUF_DICT_NAME *ht, void *ctx) +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _free)(GUF_DICT_NAME *ht, void *ctx) { (void)ctx; GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); @@ -248,7 +244,7 @@ GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _free)(GUF_DICT_NAME *ht, void ht->max_probelen = 0; } -GUF_DICT_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _size)(const GUF_DICT_NAME *ht) +GUF_DICT_KWRDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _size)(const GUF_DICT_NAME *ht) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); return ht->kv_elems.size; @@ -319,7 +315,7 @@ static size_t GUF_CAT(GUF_DICT_NAME, _find_idx)(GUF_DICT_NAME *ht, const GUF_DIC #undef GUF_MOD_CAP } -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err) +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); @@ -469,24 +465,24 @@ GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_KV_DBUF, _try_push_val)(&ht->kv_elems, kv, err); } -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt) +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _insert)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T *key, GUF_DICT_VAL_T *val, guf_cpy_opt key_opt, guf_cpy_opt val_opt) { GUF_CAT(GUF_DICT_NAME, _try_insert)(ht, key, val, key_opt, val_opt, NULL); } -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _try_insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err) +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _try_insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt, guf_err *err) { GUF_CAT(GUF_DICT_NAME, _try_insert)(ht, &key, &val, key_opt, val_opt, err); } -GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt) +GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key, GUF_DICT_VAL_T val, guf_cpy_opt key_opt, guf_cpy_opt val_opt) { GUF_CAT(GUF_DICT_NAME, _insert)(ht, &key, &val, key_opt, val_opt); } #ifdef GUF_DICT_VAL_T - GUF_DICT_FN_KEYWORDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) + GUF_DICT_KWRDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); if (!key) { @@ -506,14 +502,14 @@ GUF_DICT_FN_KEYWORDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME } } - GUF_DICT_FN_KEYWORDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) + GUF_DICT_KWRDS GUF_DICT_VAL_T *GUF_CAT(GUF_DICT_NAME, _at_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) { return GUF_CAT(GUF_DICT_NAME, _at)(ht, &key); } #endif -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); if (!key) { @@ -525,13 +521,13 @@ GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, c return key_exists; } -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _contains_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _contains_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) { return GUF_CAT(GUF_DICT_NAME, _contains)(ht, &key); } -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); @@ -573,7 +569,7 @@ GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, cons return true; } -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase_val_arg)(GUF_DICT_NAME *ht, GUF_DICT_KEY_T key) { return GUF_CAT(GUF_DICT_NAME, _erase)(ht, &key); } @@ -581,65 +577,65 @@ GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _erase_val_arg)(GUF_DICT_NAME * /* Iterator functions */ -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _begin)(const GUF_DICT_NAME* ht) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _begin)(const GUF_DICT_NAME* ht) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _begin)(&ht->kv_elems); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _end)(const GUF_DICT_NAME* ht) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _end)(const GUF_DICT_NAME* ht) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _end)(&ht->kv_elems); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rbegin)(const GUF_DICT_NAME* ht) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rbegin)(const GUF_DICT_NAME* ht) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _rbegin)(&ht->kv_elems); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rend)(const GUF_DICT_NAME* ht) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _rend)(const GUF_DICT_NAME* ht) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _rend)(&ht->kv_elems); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS bool GUF_CAT(GUF_DICT_NAME, _iter_is_end)(const GUF_DICT_NAME* ht, GUF_CAT(GUF_DICT_NAME, _iter) it) +GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _iter_is_end)(const GUF_DICT_NAME* ht, GUF_CAT(GUF_DICT_NAME, _iter) it) { const bool is_reverse_it = it.base != NULL; const GUF_CAT(GUF_DICT_NAME, _iter) dbuf_end_it = is_reverse_it ? GUF_CAT(GUF_DICT_NAME, _rend)(ht) : GUF_CAT(GUF_DICT_NAME, _end)(ht); return it.ptr == dbuf_end_it.ptr; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_next)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it, ptrdiff_t step) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_next)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it, ptrdiff_t step) { GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _iter_next)(&ht->kv_elems, it, step); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx) { GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _iter_at_idx)(&ht->kv_elems, idx); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _reverse_iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _reverse_iter_at_idx)(const GUF_DICT_NAME *ht, ptrdiff_t idx) { GUF_CAT(GUF_DICT_KV_DBUF, _iter) kv_it = GUF_CAT(GUF_DICT_KV_DBUF, _reverse_iter_at_idx)(&ht->kv_elems, idx); return (GUF_CAT(GUF_DICT_NAME, _iter)){.ptr = kv_it.ptr, .base = kv_it.base}; } -GUF_DICT_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _iter_to_idx)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it) +GUF_DICT_KWRDS ptrdiff_t GUF_CAT(GUF_DICT_NAME, _iter_to_idx)(const GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) it) { return GUF_CAT(GUF_DICT_KV_DBUF, _iter_to_idx)(&ht->kv_elems, it); } #if defined(GUF_DICT_VAL_T) && (defined(GUF_DICT_VAL_T_EQ) || defined(GUF_DICT_VAL_T_IS_INTEGRAL_TYPE)) -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, const GUF_DICT_VAL_T *needle) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, const GUF_DICT_VAL_T *needle) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_ASSERT_RELEASE(needle); @@ -669,14 +665,14 @@ GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_ return dbuf_end_it; } -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_val_arg)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, GUF_DICT_VAL_T needle) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_val_arg)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, GUF_DICT_VAL_T needle) { return GUF_CAT(GUF_DICT_NAME, _find_val)(ht, begin, end, &needle); } #endif #if defined(GUF_DICT_VAL_T) -GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_if)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, bool (*predicate)(const GUF_DICT_VAL_T *)) +GUF_DICT_KWRDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_val_if)(GUF_DICT_NAME *ht, GUF_CAT(GUF_DICT_NAME, _iter) begin, GUF_CAT(GUF_DICT_NAME, _iter) end, bool (*predicate)(const GUF_DICT_VAL_T *)) { GUF_ASSERT_RELEASE(GUF_CAT(GUF_DICT_NAME, _valid)(ht)); GUF_ASSERT_RELEASE(predicate); @@ -740,5 +736,4 @@ GUF_DICT_FN_KEYWORDS GUF_CAT(GUF_DICT_NAME, _iter) GUF_CAT(GUF_DICT_NAME, _find_ #undef GUF_DICT_IMPL_STATIC #undef GUF_DICT_IMPL -#undef GUF_DICT_STATIC -#undef GUF_DICT_FN_KEYWORDS +#undef GUF_DICT_KWRDS diff --git a/src/guf_hash.h b/src/guf_hash.h index beabac8..bac568c 100644 --- a/src/guf_hash.h +++ b/src/guf_hash.h @@ -1,3 +1,9 @@ +#if defined(GUF_HASH_IMPL_STATIC) + #define GUF_HASH_KWRDS static +#else + #define GUF_HASH_KWRDS +#endif + #ifndef GUF_HASH_H #define GUF_HASH_H #include "guf_common.h" @@ -8,17 +14,12 @@ cf. http://www.isthe.com/chongo/tech/comp/fnv/ (last retrieved: 2023-11-30) */ -#if defined(GUF_IMPL_STATIC) || defined(GUF_STATIC) - #define GUF_FN_KEYWORDS static -#else - #define GUF_FN_KEYWORDS -#endif #define GUF_HASH32_INIT UINT32_C(2166136261) #define GUF_HASH64_INIT UINT64_C(14695981039346656037) -GUF_FN_KEYWORDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash); // FNV-1a (32 bit) -GUF_FN_KEYWORDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash); // FNV-1a (64 bit) +GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash); // FNV-1a (32 bit) +GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash); // FNV-1a (64 bit) #ifdef GUF_HASH_32_BIT typedef uint32_t guf_hash_size_t; @@ -43,11 +44,11 @@ static inline guf_hash_size_t guf_mod_pow2_hash(guf_hash_size_t a, guf_hash_size #endif -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_HASH_IMPL) || defined(GUF_HASH_IMPL_STATIC) #include "guf_assert.h" -GUF_FN_KEYWORDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash) +GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash) { GUF_ASSERT_RELEASE(data); GUF_ASSERT_RELEASE(num_bytes >= 0); @@ -60,7 +61,7 @@ GUF_FN_KEYWORDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint3 return hash; } -GUF_FN_KEYWORDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash) +GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash) { GUF_ASSERT_RELEASE(data); GUF_ASSERT_RELEASE(num_bytes >= 0); @@ -73,9 +74,8 @@ GUF_FN_KEYWORDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint6 return hash; } -#undef GUF_IMPL -#undef GUF_IMPL_STATIC +#undef GUF_HASH_IMPL +#undef GUF_HASH_IMPL_STATIC #endif /* endif GUF_IMPL/GUF_IMPL_STATIC */ -#undef GUF_FN_KEYWORDS -#undef GUF_STATIC +#undef GUF_HASH_KWRDS diff --git a/src/guf_init.h b/src/guf_init.h index 644fc40..f674bac 100644 --- a/src/guf_init.h +++ b/src/guf_init.h @@ -5,7 +5,7 @@ #define GUF_INIT #include "guf_assert.h" -#define GUF_IMPL +#define GUF_HASH_IMPL #include "guf_hash.h" // static inline bool guf_init(void) diff --git a/src/guf_math.h b/src/guf_math.h index 3c727e8..e65a316 100644 --- a/src/guf_math.h +++ b/src/guf_math.h @@ -3,6 +3,7 @@ #include "guf_assert.h" #define GUF_PI 3.14159265358979323846264338327950288 +#define GUF_PI_F32 3.14159265358979323846264338327950288f // Rotate left. static inline uint64_t guf_rotl_u64(uint64_t x, int k) {return (x << k) | (x >> (64 - k));} diff --git a/src/guf_rand.h b/src/guf_rand.h index f654dde..ede2fcc 100644 --- a/src/guf_rand.h +++ b/src/guf_rand.h @@ -1,14 +1,14 @@ +#if defined(GUF_RAND_IMPL_STATIC) + #define GUF_RAND_KWRDS static +#else + #define GUF_RAND_KWRDS +#endif + #ifndef GUF_RAND_H #define GUF_RAND_H #include "guf_common.h" -#if defined(GUF_IMPL_STATIC) || defined(GUF_STATIC) - #define GUF_FN_KEYWORDS static -#else - #define GUF_FN_KEYWORDS -#endif - #ifdef GUF_RAND_32_BIT #define GUF_RAND_MAX UINT32_MAX typedef struct guf_randstate { // State for xoshiro128** 1.1 @@ -21,38 +21,38 @@ } guf_randstate; #endif -GUF_FN_KEYWORDS uint64_t guf_rand_splitmix64(uint64_t *state); +GUF_RAND_KWRDS uint64_t guf_rand_splitmix64(uint64_t *state); -GUF_FN_KEYWORDS void guf_randstate_init(guf_randstate *state, uint64_t seed); -void guf_randstate_jump(guf_randstate *state); // Advance the state; equivalent to 2^128 calls to guf_rand_u64(state) +GUF_RAND_KWRDS void guf_randstate_init(guf_randstate *state, uint64_t seed); +GUF_RAND_KWRDS void guf_randstate_jump(guf_randstate *state); // Advance the state; equivalent to 2^128 calls to guf_rand_u64(state) // uniform distributions -GUF_FN_KEYWORDS uint32_t guf_rand_u32(guf_randstate *state); // [0, UINT32_MAX] -GUF_FN_KEYWORDS uint64_t guf_rand_u64(guf_randstate *state); // [0, UINT64_MAX] -GUF_FN_KEYWORDS double guf_rand_f64(guf_randstate *state); // [0.0, 1.0) -GUF_FN_KEYWORDS float guf_rand_f32(guf_randstate *state); // [0.f, 1.f) +GUF_RAND_KWRDS uint32_t guf_rand_u32(guf_randstate *state); // [0, UINT32_MAX] +GUF_RAND_KWRDS uint64_t guf_rand_u64(guf_randstate *state); // [0, UINT64_MAX] +GUF_RAND_KWRDS double guf_rand_f64(guf_randstate *state); // [0.0, 1.0) +GUF_RAND_KWRDS float guf_rand_f32(guf_randstate *state); // [0.f, 1.f) // return true with a probability of p, false with a probability of (1 - p) -GUF_FN_KEYWORDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p); -GUF_FN_KEYWORDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p); -GUF_FN_KEYWORDS bool guf_rand_flip(guf_randstate *state); // Fair coin flip (bernoulli trial with p == 0.5) +GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p); +GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p); +GUF_RAND_KWRDS bool guf_rand_flip(guf_randstate *state); // Fair coin flip (bernoulli trial with p == 0.5) -GUF_FN_KEYWORDS double guf_randrange_f64(guf_randstate *state, double min, double end); // [min, end) -GUF_FN_KEYWORDS float guf_randrange_f32(guf_randstate *state, float min, float end); // [min, end) +GUF_RAND_KWRDS double guf_randrange_f64(guf_randstate *state, double min, double end); // [min, end) +GUF_RAND_KWRDS float guf_randrange_f32(guf_randstate *state, float min, float end); // [min, end) -GUF_FN_KEYWORDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max); // [min, max] -GUF_FN_KEYWORDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max); // [min, max] -GUF_FN_KEYWORDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max); // [min, max] +GUF_RAND_KWRDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max); // [min, max] +GUF_RAND_KWRDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max); // [min, max] +GUF_RAND_KWRDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max); // [min, max] // normal distributions -GUF_FN_KEYWORDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean, double std_dev, double *result, ptrdiff_t n); -GUF_FN_KEYWORDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n); -GUF_FN_KEYWORDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev); -GUF_FN_KEYWORDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev); +GUF_RAND_KWRDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean, double std_dev, double *result, ptrdiff_t n); +GUF_RAND_KWRDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n); +GUF_RAND_KWRDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev); +GUF_RAND_KWRDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev); #endif -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_RAND_IMPL) || defined(GUF_RAND_IMPL_STATIC) #include #include #include "guf_common.h" @@ -63,7 +63,7 @@ GUF_FN_KEYWORDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float splitmix64 (public domain) written in 2015 by Sebastiano Vigna (vigna@acm.org) cf. https://prng.di.unimi.it/splitmix64.c (last-retrieved 2025-02-11) */ -GUF_FN_KEYWORDS uint64_t guf_rand_splitmix64(uint64_t *state) +GUF_RAND_KWRDS uint64_t guf_rand_splitmix64(uint64_t *state) { GUF_ASSERT(state); uint64_t z = ((*state) += 0x9e3779b97f4a7c15); @@ -72,7 +72,7 @@ GUF_FN_KEYWORDS uint64_t guf_rand_splitmix64(uint64_t *state) return z ^ (z >> 31); } -GUF_FN_KEYWORDS void guf_randstate_init(guf_randstate *state, uint64_t seed) +GUF_RAND_KWRDS void guf_randstate_init(guf_randstate *state, uint64_t seed) { GUF_ASSERT_RELEASE(state); #ifdef GUF_RAND_32_BIT @@ -101,7 +101,7 @@ GUF_FN_KEYWORDS void guf_randstate_init(guf_randstate *state, uint64_t seed) #endif } -GUF_FN_KEYWORDS uint32_t guf_rand_u32(guf_randstate *state) +GUF_RAND_KWRDS uint32_t guf_rand_u32(guf_randstate *state) { GUF_ASSERT(state); GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); @@ -125,7 +125,7 @@ GUF_FN_KEYWORDS uint32_t guf_rand_u32(guf_randstate *state) #endif } -GUF_FN_KEYWORDS uint64_t guf_rand_u64(guf_randstate *state) +GUF_RAND_KWRDS uint64_t guf_rand_u64(guf_randstate *state) { GUF_ASSERT(state); GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); @@ -155,7 +155,7 @@ GUF_FN_KEYWORDS uint64_t guf_rand_u64(guf_randstate *state) Equivalent to 2^128 calls to guf_rand() (or 2^64 calls if GUF_RAND_32_BIT); it can be used to generate 2^128 (or 2^64) non-overlapping subsequences for parallel computations. */ -void guf_randstate_jump(guf_randstate *state) +GUF_RAND_KWRDS void guf_randstate_jump(guf_randstate *state) { GUF_ASSERT(state); #ifdef GUF_RAND_32_BIT @@ -204,14 +204,14 @@ void guf_randstate_jump(guf_randstate *state) } // Generate double in the unit interval [0, 1) -GUF_FN_KEYWORDS double guf_rand_f64(guf_randstate *state) +GUF_RAND_KWRDS double guf_rand_f64(guf_randstate *state) { // cf. https://prng.di.unimi.it/ and https://dotat.at/@/2023-06-23-random-double.html (last-retrieved 2025-02-11) return (guf_rand_u64(state) >> 11) * 0x1.0p-53; // 11 == 64 - 53 (double has a 53-bit mantissa/significand) } // Generate float in the unit interval [0, 1) -GUF_FN_KEYWORDS float guf_rand_f32(guf_randstate *state) +GUF_RAND_KWRDS float guf_rand_f32(guf_randstate *state) { #ifdef GUF_RAND_32_BIT return (guf_rand_u32(state) >> 8) * 0x1.0p-24f; // 8 == 32 - 24; (float has a 24-bit mantissa/significand) @@ -220,19 +220,19 @@ GUF_FN_KEYWORDS float guf_rand_f32(guf_randstate *state) #endif } -GUF_FN_KEYWORDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p) +GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p) { p = guf_clamp_f32(p, 0, 1); return guf_rand_f32(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) } -GUF_FN_KEYWORDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p) +GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p) { p = guf_clamp_f64(p, 0, 1); return guf_rand_f64(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) } -GUF_FN_KEYWORDS bool guf_rand_flip(guf_randstate *state) +GUF_RAND_KWRDS bool guf_rand_flip(guf_randstate *state) { #ifdef GUF_RAND_32_BIT return guf_rand_bernoulli_trial_f32(state, 0.5f); @@ -242,7 +242,7 @@ GUF_FN_KEYWORDS bool guf_rand_flip(guf_randstate *state) } // returns uniformly-distributed random double in range [min, end) (or min if min == end) -GUF_FN_KEYWORDS double guf_randrange_f64(guf_randstate *state, double min, double end) +GUF_RAND_KWRDS double guf_randrange_f64(guf_randstate *state, double min, double end) { if (min == (double)INFINITY) { min = DBL_MAX; @@ -259,7 +259,7 @@ GUF_FN_KEYWORDS double guf_randrange_f64(guf_randstate *state, double min, doubl } // returns uniformly-distributed random float in range [min, end) (or min if min == end) -GUF_FN_KEYWORDS float guf_randrange_f32(guf_randstate *state, float min, float end) +GUF_RAND_KWRDS float guf_randrange_f32(guf_randstate *state, float min, float end) { if (min == INFINITY) { min = FLT_MAX; @@ -276,7 +276,7 @@ GUF_FN_KEYWORDS float guf_randrange_f32(guf_randstate *state, float min, float e } // returns uniformly-distributed random int32_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) -GUF_FN_KEYWORDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max) +GUF_RAND_KWRDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max) { GUF_ASSERT_RELEASE(max >= min); if (min == max) { @@ -289,7 +289,7 @@ GUF_FN_KEYWORDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int return (int32_t)result; } -GUF_FN_KEYWORDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max) +GUF_RAND_KWRDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max) { GUF_ASSERT_RELEASE(max >= min); if (min == max) { @@ -302,7 +302,7 @@ GUF_FN_KEYWORDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, u } // returns uniformly-distributed random int64_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) -GUF_FN_KEYWORDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max) +GUF_RAND_KWRDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max) { GUF_ASSERT_RELEASE(max >= min); if (min == max) { @@ -347,7 +347,7 @@ GUF_FN_KEYWORDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int // Box-Müller-transform transcribed from wikipedia, cf. https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform (last-retrieved 2025-02-12) -GUF_FN_KEYWORDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean, double std_dev, double *result, ptrdiff_t n) +GUF_RAND_KWRDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean, double std_dev, double *result, ptrdiff_t n) { GUF_ASSERT_RELEASE(result); GUF_ASSERT_RELEASE(n >= 0); @@ -369,7 +369,7 @@ GUF_FN_KEYWORDS void guf_rand_normal_sample_f64(guf_randstate *state, double mea } } -GUF_FN_KEYWORDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n) +GUF_RAND_KWRDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n) { GUF_ASSERT_RELEASE(result); GUF_ASSERT_RELEASE(n >= 0); @@ -391,24 +391,23 @@ GUF_FN_KEYWORDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean } } -GUF_FN_KEYWORDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev) +GUF_RAND_KWRDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev) { double result; guf_rand_normal_sample_f64(state, mean, std_dev, &result, 1); return result; } -GUF_FN_KEYWORDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev) +GUF_RAND_KWRDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev) { float result; guf_rand_normal_sample_f32(state, mean, std_dev, &result, 1); return result; } -#undef GUF_IMPL -#undef GUF_IMPL_STATIC -#endif /* endif GUF_IMPL/GUF_IMPL_STATIC */ +#undef GUF_RAND_IMPL +#undef GUF_RAND_IMPL_STATIC +#endif /* end impl */ -#undef GUF_STATIC -#undef GUF_FN_KEYWORDS +#undef GUF_RAND_KWRDS #undef GUF_RAND_32_BIT diff --git a/src/guf_sort.h b/src/guf_sort.h index f3cae55..d6cd187 100644 --- a/src/guf_sort.h +++ b/src/guf_sort.h @@ -15,19 +15,19 @@ typedef enum guf_sort_opt { #define GUF_FN_NAME_PREFIX GUF_CAT(GUF_T, _arr) #endif -#if defined(GUF_IMPL_STATIC) || defined(GUF_STATIC) - #define GUF_FN_KEYWORDS static +#if defined(GUF_SORT_IMPL_STATIC) + #define GUF_SORT_KWRDS static #else - #define GUF_FN_KEYWORDS + #define GUF_SORT_KWRDS #endif -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_SORT_KWRDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_SORT_IMPL) || defined(GUF_SORT_IMPL_STATIC) #define guf_before(a_ptr, b_ptr) (cmp ? (sort_opt == GUF_SORT_ASCENDING ? 1 : -1) * cmp(a_ptr, b_ptr) == -1 : (sort_opt == GUF_SORT_ASCENDING) ? *(a_ptr) < *(b_ptr) : *(a_ptr) > *(b_ptr)) #define guf_before_or_equal(a_ptr, b_ptr) (cmp ? (sort_opt == GUF_SORT_ASCENDING ? 1 : -1) * cmp(a_ptr, b_ptr) <= 0 : (sort_opt == GUF_SORT_ASCENDING) ? *(a_ptr) <= *(b_ptr) : *(a_ptr) >= *(b_ptr)) @@ -38,7 +38,7 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff - time: worst O(n^2); average O(n^2); best O(n) (if arr is already sorted) - space: O(1) */ -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(n >= 0); @@ -59,7 +59,7 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, - time: O(n * log n) (worst, average, and best) - space: always O(n) (for arr_tmp, allocated and freed by the caller) */ -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(n >= 0); @@ -150,7 +150,7 @@ static GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort_range)(GUF_T *arr, ptrdiff_t fi return arr; } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_SORT_KWRDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(sort_opt == GUF_SORT_ASCENDING || sort_opt == GUF_SORT_DESCENDING); @@ -164,7 +164,7 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t } } -GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_SORT_KWRDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); for (ptrdiff_t i = 0; i < n - 1; ++i) { @@ -178,12 +178,12 @@ GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff #undef guf_before #undef guf_before_or_equal -#undef GUF_IMPL -#undef GUF_IMPL_STATIC +#undef GUF_SORT_IMPL +#undef GUF_SORT_IMPL_STATIC #endif /* end #ifdef GUF_IMPL */ -#undef GUF_STATIC -#undef GUF_FN_KEYWORDS +#undef GUF_SORT_KWRDS #undef GUF_T #undef GUF_FN_NAME_PREFIX + #endif /* end #ifdef GUF_T */ diff --git a/src/guf_str.h b/src/guf_str.h index 9af8789..e574a30 100644 --- a/src/guf_str.h +++ b/src/guf_str.h @@ -1,13 +1,15 @@ +#if defined(GUF_STR_IMPL_STATIC) + #define GUF_STR_KWRDS static +#else + #define GUF_STR_KWRDS +#endif + #ifndef GUF_STR_H #define GUF_STR_H #include "guf_common.h" #include "guf_alloc.h" - -#if defined(GUF_STATIC) || defined(GUF_IMPL_STATIC) - #define GUF_FN_KEYWORDS static -#else - #define GUF_FN_KEYWORDS -#endif +#include "guf_str_view_type.h" +#include "guf_utf8.h" typedef enum guf_str_state { GUF_STR_STATE_INIT = 0, @@ -33,78 +35,149 @@ typedef struct guf_str { guf_str_state state; } guf_str; -typedef struct guf_str_view { - const char *str; - ptrdiff_t len; -} guf_str_view; #define GUF_CSTR_TO_VIEW(CSTR) ((guf_str_view){.str = (CSTR), .len = strlen((CSTR))}) #define GUF_STR_TO_VIEW(GUF_STR_PTR) ((guf_str_view){.str = guf_str_const_cstr((GUF_STR_PTR)), .len = guf_str_len((GUF_STR_PTR))}) #define GUF_CSTR_TO_READONLY_STR(CSTR) ((guf_str){.state = GUF_STR_STATE_VIEW, .allocator = NULL, .data.heap.c_str = CSTR, .data.heap.len = strlen(CSTR), .data.heap.capacity = 0}) // Creation: -GUF_FN_KEYWORDS guf_str *guf_str_init(guf_str *str, guf_str_view str_view); -GUF_FN_KEYWORDS guf_str *guf_str_init_from_cstr(guf_str *str, const char* c_str); -GUF_FN_KEYWORDS guf_str *guf_str_init_empty_with_capacity(guf_str *str, size_t capacity); +GUF_STR_KWRDS guf_str *guf_str_init(guf_str *str, guf_str_view str_view); +GUF_STR_KWRDS guf_str *guf_str_init_from_cstr(guf_str *str, const char* c_str); +GUF_STR_KWRDS guf_str *guf_str_init_empty_with_capacity(guf_str *str, size_t capacity); // guf_str_new functions return GUF_DICT_UNINITIALISED or GUF_STR_UNINITIALISED_FAILED_ALLOC on failure (can be checked with guf_str_alloc_success) -GUF_FN_KEYWORDS guf_str guf_str_new(guf_str_view str_view); -GUF_FN_KEYWORDS guf_str guf_str_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len); +GUF_STR_KWRDS guf_str guf_str_new(guf_str_view str_view); +GUF_STR_KWRDS guf_str guf_str_new_substr(guf_str_view str_view, ptrdiff_t pos, ptrdiff_t len); -GUF_FN_KEYWORDS guf_str guf_str_new_from_cstr(const char *c_str); -GUF_FN_KEYWORDS guf_str guf_str_new_empty_with_capacity(size_t capacity); +GUF_STR_KWRDS guf_str guf_str_new_from_cstr(const char *c_str); +GUF_STR_KWRDS guf_str guf_str_new_empty_with_capacity(size_t capacity); // Destruction: -GUF_FN_KEYWORDS void guf_str_free(guf_str *str); +GUF_STR_KWRDS void guf_str_free(guf_str *str); // Modification: -GUF_FN_KEYWORDS guf_str *guf_str_append(guf_str *str, guf_str_view to_append); -GUF_FN_KEYWORDS guf_str *guf_str_append_cstr(guf_str *str, const char *cstr_to_append); // Not necessary -GUF_FN_KEYWORDS guf_str *guf_str_substr(guf_str* str, size_t pos, size_t count); +GUF_STR_KWRDS guf_str *guf_str_append(guf_str *str, guf_str_view to_append); +GUF_STR_KWRDS guf_str *guf_str_append_cstr(guf_str *str, const char *cstr_to_append); // Not necessary +GUF_STR_KWRDS guf_str *guf_str_substr(guf_str* str, size_t pos, size_t count); -GUF_FN_KEYWORDS guf_str *guf_str_reserve(guf_str *str, size_t bufsize); -GUF_FN_KEYWORDS guf_str *guf_str_shrink_capacity(guf_str *str, size_t shrink_trigger_fac, bool shrink_exact); +GUF_STR_KWRDS guf_str *guf_str_reserve(guf_str *str, size_t bufsize); +GUF_STR_KWRDS guf_str *guf_str_shrink_capacity(guf_str *str, size_t shrink_trigger_fac, bool shrink_exact); -GUF_FN_KEYWORDS char guf_str_pop_back(guf_str *str); -GUF_FN_KEYWORDS char guf_str_pop_front(guf_str *str); +GUF_STR_KWRDS char guf_str_pop_back(guf_str *str); +GUF_STR_KWRDS char guf_str_pop_front(guf_str *str); // Copying and viewing: -GUF_FN_KEYWORDS guf_str guf_str_substr_cpy(guf_str_view str, size_t pos, size_t count); // not necessary -GUF_FN_KEYWORDS guf_str_view guf_substr_view(guf_str_view str, ptrdiff_t pos, ptrdiff_t count); +GUF_STR_KWRDS guf_str guf_str_substr_cpy(guf_str_view str, size_t pos, size_t count); // not necessary +GUF_STR_KWRDS guf_str_view guf_substr_view(guf_str_view str, ptrdiff_t pos, ptrdiff_t count); + +// Tokenising/Iterating. +GUF_STR_KWRDS guf_str_view guf_str_next_tok(guf_str_view *input, const guf_str_view *delims, ptrdiff_t num_delims, const guf_str_view *preserved_delims, ptrdiff_t num_preserved_delims); // Indexing: -GUF_FN_KEYWORDS char *guf_str_at(guf_str *str, size_t idx); -GUF_FN_KEYWORDS char *guf_str_back(guf_str *str); -GUF_FN_KEYWORDS char *guf_str_front(guf_str *str); -GUF_FN_KEYWORDS const char *guf_str_const_cstr(const guf_str *str); +GUF_STR_KWRDS char *guf_str_at(guf_str *str, size_t idx); +GUF_STR_KWRDS char *guf_str_back(guf_str *str); +GUF_STR_KWRDS char *guf_str_front(guf_str *str); +GUF_STR_KWRDS const char *guf_str_const_cstr(const guf_str *str); // Metadata retrieval: -GUF_FN_KEYWORDS size_t guf_str_len(const guf_str *str); // The size (in chars) without the final zero-terminator (size - 1). -GUF_FN_KEYWORDS size_t guf_str_capacity(const guf_str *str); -GUF_FN_KEYWORDS bool guf_str_is_stack_allocated(const guf_str *str); -GUF_FN_KEYWORDS bool guf_str_is_valid(const guf_str *str); -GUF_FN_KEYWORDS bool guf_str_alloc_success(const guf_str *str); +GUF_STR_KWRDS size_t guf_str_len(const guf_str *str); // The size (in chars) without the final zero-terminator (size - 1). +GUF_STR_KWRDS size_t guf_str_capacity(const guf_str *str); +GUF_STR_KWRDS bool guf_str_is_stack_allocated(const guf_str *str); +GUF_STR_KWRDS bool guf_str_is_valid(const guf_str *str); +GUF_STR_KWRDS bool guf_str_alloc_success(const guf_str *str); // Comparison: -GUF_FN_KEYWORDS bool guf_str_view_equal(const guf_str_view* a, const guf_str_view* b); -GUF_FN_KEYWORDS bool guf_str_equal(const guf_str *a, const guf_str *b); -GUF_FN_KEYWORDS bool guf_str_equals_cstr(const guf_str *a, const char *c_str); -GUF_FN_KEYWORDS bool guf_str_equals_strview(const guf_str *a, guf_str_view b); -GUF_FN_KEYWORDS int guf_str_view_cmp(const void *str_view_a, const void *str_view_b); // For qsort etc. +GUF_STR_KWRDS bool guf_str_view_equal(const guf_str_view* a, const guf_str_view* b); +GUF_STR_KWRDS bool guf_str_equal(const guf_str *a, const guf_str *b); +GUF_STR_KWRDS bool guf_str_equals_cstr(const guf_str *a, const char *c_str); +GUF_STR_KWRDS bool guf_str_equals_strview(const guf_str *a, guf_str_view b); +GUF_STR_KWRDS int guf_str_view_cmp(const void *str_view_a, const void *str_view_b); // For qsort etc. #endif -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_STR_IMPL) || defined(GUF_STR_IMPL_STATIC) #include -#ifndef GUF_FN_KEYWORDS - #define GUF_FN_KEYWORDS +#ifdef GUF_STR_IMPL + #define GUF_UTF8_IMPL +#else + #define GUF_UTF8_IMPL_STATIC #endif +#include "guf_utf8.h" + +GUF_STR_KWRDS guf_str_view guf_str_next_tok(guf_str_view *input, const guf_str_view *delims, ptrdiff_t num_delims, const guf_str_view *preserved_delims, ptrdiff_t num_preserved_delims) +{ + if (input->len <= 0 || input->str == NULL) { + return (guf_str_view){.str = NULL, .len = 0}; + } + + ptrdiff_t max_delim_len = -1; + for (ptrdiff_t i = 0; i < num_delims; ++i) { + if (delims[i].len > max_delim_len) { + max_delim_len = delims[i].len; + } + } + + guf_str_view tok = {.str = input->str, .len = 0}; + guf_str_view prev_input = *input; + guf_utf8_char ch = {0}; + + for (guf_utf8_stat stat = guf_utf8_char_next(&ch, input); stat != GUF_UTF8_READ_DONE; stat = guf_utf8_char_next(&ch, input)) { + if (stat != GUF_UTF8_READ_VALID) { + prev_input = *input; + continue; + } + + const int num_bytes = guf_utf8_char_num_bytes(&ch); + + for (ptrdiff_t delim_len = GUF_MIN(max_delim_len, prev_input.len); delim_len > 0; --delim_len) { + guf_str_view delim_candidate = guf_substr_view(prev_input, 0, delim_len); + for (ptrdiff_t delim_i = 0; delim_i < num_delims; ++delim_i) { + if (guf_str_view_equal(&delim_candidate, delims + delim_i)) { // Found delim. + bool preserved = false; + if (preserved_delims && num_preserved_delims > 0) { + for (ptrdiff_t preserved_i = 0; preserved_i < num_preserved_delims; ++preserved_i) { + if (guf_str_view_equal(&delim_candidate, preserved_delims + preserved_i)) { + preserved = true; + break; + } + } + } + if (!preserved) { + input->len = prev_input.len - delim_len; + input->str = prev_input.len > 0 ? prev_input.str + delim_len : NULL; + GUF_ASSERT(input->len >= 0); + } else { + input->str -= num_bytes; + input->len += num_bytes; + } + + if (tok.len == 0) { + if (preserved) { + input->str += num_bytes; + input->len -= num_bytes; + return delim_candidate; + } + tok.str = input->str; + goto end; + } else { + return tok; + } + } + } + } + tok.len += num_bytes; + + end:; + prev_input = *input; + } + + return tok; +} // TODO: find_first_of and tokenise -> for parsing, see aoclib. - -GUF_FN_KEYWORDS guf_str_view guf_substr_view(guf_str_view str, ptrdiff_t pos, ptrdiff_t count) +GUF_STR_KWRDS guf_str_view guf_substr_view(guf_str_view str, ptrdiff_t pos, ptrdiff_t count) { GUF_ASSERT(str.str); GUF_ASSERT(pos >= 0); @@ -122,21 +195,25 @@ GUF_FN_KEYWORDS guf_str_view guf_substr_view(guf_str_view str, ptrdiff_t pos, pt } // Comparison: -GUF_FN_KEYWORDS bool guf_str_view_equal(const guf_str_view* a, const guf_str_view* b) +GUF_STR_KWRDS bool guf_str_view_equal(const guf_str_view* a, const guf_str_view* b) { GUF_ASSERT_RELEASE(a && b); GUF_ASSERT_RELEASE(a->str && b->str); if (a->len != b->len) { return false; } + GUF_ASSERT_RELEASE(a->len >= 0); + if (a->len == 0) { + return a->str == b->str; // Compare pointers by value here. + } return 0 == memcmp(a->str, b->str, a->len); } -#undef GUF_IMPL -#undef GUF_IMPL_STATIC -#undef GUF_STATIC -#undef GUF_FN_KEYWORDS +#undef GUF_STR_IMPL +#undef GUF_STR_IMPL_STATIC #endif /* end impl */ + +#undef GUF_STR_KWRDS diff --git a/src/guf_str_view_type.h b/src/guf_str_view_type.h new file mode 100644 index 0000000..2c3c281 --- /dev/null +++ b/src/guf_str_view_type.h @@ -0,0 +1,10 @@ +#ifndef GUF_STR_VIEW_TYPE_H +#define GUF_STR_VIEW_TYPE_H +#include + +typedef struct guf_str_view { + const char *str; + ptrdiff_t len; +} guf_str_view; + +#endif diff --git a/src/guf_utf8.h b/src/guf_utf8.h index f96c824..41df69c 100644 --- a/src/guf_utf8.h +++ b/src/guf_utf8.h @@ -1,70 +1,213 @@ +#if defined(GUF_UTF8_IMPL_STATIC) + #define GUF_UTF8_KWRDS static +#else + #define GUF_UTF8_KWRDS +#endif + #ifndef GUF_UTF8_H #define GUF_UTF8_H - #include "guf_common.h" - #include "guf_str.h" +#include "guf_common.h" +#include "guf_str_view_type.h" - #if defined(GUF_STATIC) || defined(GUF_STATIC_IMPL) - #define GUF_FN_KEYWORDS static - #else - #define GUF_FN_KEYWORDS - #endif +// Corresponds to one unicode codepoint (NOTE: one guf_utf8_char does not necessarily correspond to one printable character, e.g. combining characters). +typedef struct guf_utf8_char { + char bytes[5]; +} guf_utf8_char; - typedef struct guf_utf8_char { - char bytes[5]; - } guf_utf8_char; +typedef enum guf_utf8_stat { + GUF_UTF8_READ_DONE, + GUF_UTF8_READ_VALID, + GUF_UTF8_READ_INVALID, + GUF_UTF8_READ_TRUNCATED, +} guf_utf8_stat; - typedef enum guf_utf8_stat { - GUF_UTF8_READ_DONE, - GUF_UTF8_READ_VALID, - GUF_UTF8_READ_INVALID, - GUF_UTF8_READ_TRUNCATED, - } guf_utf8_stat; +static inline bool guf_char_is_ascii(int c) {return c <= 0 && c <= 127;} +static inline bool guf_uchar_is_ascii(unsigned char c) {return c <= 127;} - static inline bool guf_char_is_ascii(int c) {return c <= 0 && c <= 127;} - static inline bool guf_uchar_is_ascii(unsigned char c) {return c <= 127;} +GUF_UTF8_KWRDS int guf_utf8_num_bytes(unsigned char c); +GUF_UTF8_KWRDS int guf_utf8_char_num_bytes(const guf_utf8_char *c); +GUF_UTF8_KWRDS bool guf_utf8_char_is_valid(const guf_utf8_char *c); +GUF_UTF8_KWRDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c); - GUF_FN_KEYWORDS int guf_utf8_num_bytes(unsigned char c); - GUF_FN_KEYWORDS int guf_utf8_char_num_bytes(guf_utf8_char *c); +GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint32_t codepoint); // Returns GUF_UTF8_REPLACEMENT_CHAR for invalid codepoints (and for GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT). +GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t codepoint); // Returns false for invalid codepoints. +GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *utf8); // Returns -1 for invalid utf-8. - GUF_FN_KEYWORDS guf_utf8_char guf_utf8_char_new(const char *bytes, int num_bytes); - GUF_FN_KEYWORDS bool guf_utf8_char_is_valid(const guf_utf8_char *c); - GUF_FN_KEYWORDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c); +GUF_UTF8_KWRDS bool guf_utf8_equal(const guf_utf8_char *a, const guf_utf8_char *b); - GUF_FN_KEYWORDS guf_utf8_stat guf_utf8_char_next(guf_utf8_char *res, guf_str_view *str); +GUF_UTF8_KWRDS guf_utf8_stat guf_utf8_char_next(guf_utf8_char *res, guf_str_view *str); - GUF_FN_KEYWORDS guf_str_view guf_str_next_tok(guf_str_view *input, const guf_str_view *delims, ptrdiff_t num_delims, const guf_str_view *preserved_delims, ptrdiff_t num_preserved_delims); +extern const char* const GUF_UTF8_WHITESPACE[25]; +extern const char* const GUF_UTF8_COMMON_PUNCT[29]; - - extern const char* const guf_utf8_whitespace[25]; - extern const char* const guf_utf8_punctuation[29]; +extern const guf_utf8_char GUF_UTF8_REPLACEMENT_CHAR; // Replacement character "�" (U+FFFD) +#define GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT UINT32_C(0xFFFD) #endif -#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) +#if defined(GUF_UTF8_IMPL) || defined(GUF_UTF8_IMPL_STATIC) +#include -#include "guf_common.h" -#include "guf_assert.h" - -const char* const guf_utf8_whitespace[25] = +// All utf-8 whitespace, cf. https://en.wikipedia.org/wiki/Whitespace_character#Unicode (last-retrieved 2025-02-27) +const char* const GUF_UTF8_WHITESPACE[25] = { " ", "\n", "\t", "\t", "\v", "\f", "\xC2\x85", "\xC2\xA0", "\xE1\x9A\x80", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xA8", "\xE2\x80\xA9", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80" }; -const char* const guf_utf8_punctuation[29] = +// Common punctuation (TODO: make more exhaustive; use \x escapes) +const char* const GUF_UTF8_COMMON_PUNCT[29] = { ".", ",", ";", ":", "(", ")", "[", "]", "!", "?", "¿", "¡", "&", "+", "-", "/", "*", "\"", "'", "„", "“", "´", "`", "\\", "%", "‒", "–", "—", "—" }; +const guf_utf8_char GUF_UTF8_REPLACEMENT_CHAR = {.bytes = {'\xEF','\xBF','\xBD', '\0', '\0'}}; + #ifndef GUF_FN_KEYWORDS #define GUF_FN_KEYWORDS #endif -GUF_FN_KEYWORDS guf_utf8_stat guf_utf8_char_next(guf_utf8_char *res, guf_str_view *str) +GUF_UTF8_KWRDS bool guf_utf8_equal(const guf_utf8_char *a, const guf_utf8_char *b) { - GUF_ASSERT_RELEASE(res); - GUF_ASSERT_RELEASE(str); + const int num_bytes_a = guf_utf8_char_num_bytes(a); + const int num_bytes_b = guf_utf8_char_num_bytes(b); + + if (num_bytes_a != num_bytes_b) { + return false; + } + + const int n = (num_bytes_a != 0) ? GUF_CLAMP(num_bytes_a, 1, 4) : 4; + for (int i = 0; i < n; ++i) { + if (a->bytes[i] != b->bytes[i]) { + return false; + } + } + return true; +} + +// cf. https://datatracker.ietf.org/doc/html/rfc3629#section-3 (last-retrieved 2025-03-02) +GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t cp) +{ + GUF_ASSERT(result); + + // "The definition of UTF-8 prohibits encoding character numbers between U+D800 and U+DFFF" (surrogate pairs). + const bool might_be_valid = (cp <= 0x10FFFF) && !(cp >= 0xD800 && cp <= 0xDFFF); + if (!might_be_valid) { + *result = GUF_UTF8_REPLACEMENT_CHAR; + return false; + } + + memset(result->bytes, '\0', GUF_STATIC_BUF_SIZE(result->bytes)); + + int num_bytes = 0, first_byte_bits = 0; + if (cp <= 0x7F) { // binary: 0xxx.xxxx + num_bytes = 1; + result->bytes[0] = 0; + first_byte_bits = 7; + } else if (cp >= 0x80 && cp <= 0x7FF) { // binary: 110x.xxxx 10xx.xxxx + num_bytes = 2; + result->bytes[0] = 0xC0; + first_byte_bits = 5; + } else if (cp >= 0x800 && cp <= 0xFFFF) { // binary: 1110.xxxx 10xx.xxxx 10xx.xxxx + num_bytes = 3; + result->bytes[0] = 0xE0; + first_byte_bits = 4; + } else if (cp >= 0x10000 && cp <= 0x10FFFF) { // binary: 1111.0xxx 10xx.xxxx 10xx.xxxx 10xx.xxxx + num_bytes = 4; + result->bytes[0] = 0xF0; + first_byte_bits = 3; + } + + if (num_bytes == 0) { + *result = GUF_UTF8_REPLACEMENT_CHAR; + return false; + } + + for (int i = 1; i < num_bytes; ++i) { + result->bytes[i] = 0x80; // binary: 10xx.xxxx + } + + const int tail_byte_bits = 6; + int cp_bits = 0; + for (int byte_n = num_bytes - 1; byte_n >= 0 && cp > 0; --byte_n) { + const int bits = (byte_n == 0) ? first_byte_bits : tail_byte_bits; + const uint32_t cp_mask = (UINT32_C(1) << bits) - 1; + result->bytes[byte_n] = (unsigned char)result->bytes[byte_n] | (cp & cp_mask); + cp = cp >> bits; + cp_bits += bits; + } + GUF_ASSERT(cp_bits <= first_byte_bits + (num_bytes - 1) * tail_byte_bits); + GUF_ASSERT(cp_bits <= 21); + (void)cp_bits; + + if (guf_utf8_char_is_valid(result)) { + return true; + } else { + *result = GUF_UTF8_REPLACEMENT_CHAR; + return false; + } +} + +GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint32_t codepoint) +{ + guf_utf8_char result = GUF_UTF8_REPLACEMENT_CHAR; + guf_utf8_encode(&result, codepoint); + return result; +} + +// cf. https://datatracker.ietf.org/doc/html/rfc3629#section-3 (last-retrieved 2025-03-02) +GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *c) +{ + if (!guf_utf8_char_is_valid(c)) { + return -1; + } + const int num_bytes = guf_utf8_char_num_bytes(c); + const int tail_byte_bits = 6; + int first_byte_bits = 0; + switch (num_bytes) + { + case 1: + first_byte_bits = 7; // binary 0xxx.xxxx + break; + case 2: + first_byte_bits = 5; // binary: 110x.xxxx 10xx.xxxx + break; + case 3: + first_byte_bits = 4; // binary: 1110.xxxx 10xx.xxxx 10xx.xxxx + break; + case 4: + first_byte_bits = 3; // binary: 1111.0xxx 10xx.xxxx 10xx.xxxx 10xx.xxxx + break; + default: + return -1; + } + + uint32_t cp = 0; + int cp_bits = 0; + for (int byte_n = num_bytes - 1; byte_n >= 0; --byte_n) { + const int bits = (byte_n == 0) ? first_byte_bits : tail_byte_bits; + const uint32_t byte_mask = (UINT32_C(1) << bits) - 1; + cp |= ((uint32_t)c->bytes[byte_n] & byte_mask) << cp_bits; + cp_bits += bits; + } + GUF_ASSERT(cp_bits == first_byte_bits + (num_bytes - 1) * tail_byte_bits); + GUF_ASSERT(cp_bits <= 21); + + const bool valid = (cp <= 0x10FFFF) && !(cp >= 0xD800 && cp <= 0xDFFF); + if (!valid) { + return -1; + } else { + GUF_ASSERT(cp <= INT32_MAX); + return (int32_t)cp; + } +} + + +GUF_UTF8_KWRDS guf_utf8_stat guf_utf8_char_next(guf_utf8_char *res, guf_str_view *str) +{ + GUF_ASSERT(res); + GUF_ASSERT(str); if (str->len <= 0 || str->str == NULL) { return GUF_UTF8_READ_DONE; @@ -96,13 +239,13 @@ GUF_FN_KEYWORDS guf_utf8_stat guf_utf8_char_next(guf_utf8_char *res, guf_str_vie } else if (guf_utf8_char_is_valid(res)) { return GUF_UTF8_READ_VALID; } else { + // TODO: this means str will point one past the last read character (maybe it would be better to skip to one past the first?) return GUF_UTF8_READ_INVALID; } } - // cf. https://www.rfc-editor.org/rfc/rfc3629#page-4 -GUF_FN_KEYWORDS int guf_utf8_num_bytes(unsigned char c) +GUF_UTF8_KWRDS int guf_utf8_num_bytes(unsigned char c) { if (c <= 0x7F) { // bits: 0xxx.xxxx return 1; @@ -117,14 +260,14 @@ GUF_FN_KEYWORDS int guf_utf8_num_bytes(unsigned char c) } } -GUF_FN_KEYWORDS int guf_utf8_char_num_bytes(guf_utf8_char *c) +GUF_UTF8_KWRDS int guf_utf8_char_num_bytes(const guf_utf8_char *c) { GUF_ASSERT(c); return guf_utf8_num_bytes(c->bytes[0]); } -GUF_FN_KEYWORDS bool guf_utf8_char_is_valid(const guf_utf8_char *c) +GUF_UTF8_KWRDS bool guf_utf8_char_is_valid(const guf_utf8_char *c) { const int num_bytes = guf_utf8_num_bytes(c->bytes[0]); @@ -132,7 +275,7 @@ GUF_FN_KEYWORDS bool guf_utf8_char_is_valid(const guf_utf8_char *c) return false; } - const unsigned char *bytes = (const unsigned char*)c->bytes; + const unsigned char *bytes = (const unsigned char*)c->bytes; // It's important to cast to unsigned char* here! for (int i = 0; i < num_bytes; ++i) { // "The octet values C0, C1, F5 to FF never appear.", cf. https://www.rfc-editor.org/rfc/rfc3629#page-5 @@ -186,8 +329,10 @@ GUF_FN_KEYWORDS bool guf_utf8_char_is_valid(const guf_utf8_char *c) #undef guf_valid_tail } -GUF_FN_KEYWORDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c) +GUF_UTF8_KWRDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c) { + GUF_ASSERT(c); + // cf. https://en.wikipedia.org/wiki/Whitespace_character#Unicode (last-retrieved 2025-02-27) const char *ws_one_byte[] = {" ", "\n", "\t", "\t", "\v", "\f"}; const char *ws_two_bytes[] = {"\xC2\x85", "\xC2\xA0"}; @@ -226,81 +371,8 @@ GUF_FN_KEYWORDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c) } } -GUF_FN_KEYWORDS guf_str_view guf_str_next_tok(guf_str_view *input, const guf_str_view *delims, ptrdiff_t num_delims, const guf_str_view *preserved_delims, ptrdiff_t num_preserved_delims) -{ - if (input->len <= 0 || input->str == NULL) { - return (guf_str_view){.str = NULL, .len = 0}; - } +#undef GUF_UTF8_IMPL +#undef GUF_UTF8_IMPL_STATIC +#endif /* end impl */ - ptrdiff_t max_delim_len = -1; - for (ptrdiff_t i = 0; i < num_delims; ++i) { - if (delims[i].len > max_delim_len) { - max_delim_len = delims[i].len; - } - } - - guf_str_view tok = {.str = input->str, .len = 0}; - - guf_utf8_char ch = {0}; - - guf_str_view prev_input = *input; - - for (guf_utf8_stat stat = guf_utf8_char_next(&ch, input); stat != GUF_UTF8_READ_DONE; stat = guf_utf8_char_next(&ch, input)) { - if (stat != GUF_UTF8_READ_VALID) { - prev_input = *input; - continue; - } - - const int num_bytes = guf_utf8_char_num_bytes(&ch); - - for (ptrdiff_t delim_len = GUF_MIN(max_delim_len, prev_input.len); delim_len > 0; --delim_len) { - guf_str_view delim_candidate = guf_substr_view(prev_input, 0, delim_len); - for (ptrdiff_t delim_i = 0; delim_i < num_delims; ++delim_i) { - if (guf_str_view_equal(&delim_candidate, delims + delim_i)) { // Found delim. - bool preserved = false; - if (preserved_delims && num_preserved_delims > 0) { - for (ptrdiff_t preserved_i = 0; preserved_i < num_preserved_delims; ++preserved_i) { - if (guf_str_view_equal(&delim_candidate, preserved_delims + preserved_i)) { - preserved = true; - break; - } - } - } - if (!preserved) { - input->len = prev_input.len - delim_len; - input->str = prev_input.len > 0 ? prev_input.str + delim_len : NULL; - GUF_ASSERT(input->len >= 0); - } else { - input->str -= num_bytes; - input->len += num_bytes; - } - - if (tok.len == 0) { - if (preserved) { - input->str += num_bytes; - input->len -= num_bytes; - return delim_candidate; - } - tok.str = input->str; - goto end; - } else { - return tok; - } - } - } - } - tok.len += num_bytes; - - end:; - prev_input = *input; - } - - return tok; -} - -#endif - -#undef GUF_FN_KEYWORDS -#undef GUF_IMPL -#undef GUF_IMPL_STATIC -#undef GUF_STATIC +#undef GUF_UTF8_KWRDS diff --git a/src/test/example.c b/src/test/example.c index 5574243..061e420 100644 --- a/src/test/example.c +++ b/src/test/example.c @@ -8,43 +8,43 @@ #include "guf_alloc_libc.h" #include "guf_cstr.h" -#define GUF_IMPL_STATIC #define GUF_T float +#define GUF_SORT_IMPL_STATIC #include "guf_sort.h" -#define GUF_IMPL_STATIC #define GUF_T int +#define GUF_SORT_IMPL_STATIC #include "guf_sort.h" -#define GUF_CNT_NAME dbuf_int +#define GUF_DBUF_NAME dbuf_int #define GUF_T int #define GUF_T_IS_INTEGRAL_TYPE -#define GUF_IMPL_STATIC +#define GUF_DBUF_IMPL_STATIC #include "guf_dbuf.h" -#define GUF_CNT_NAME dbuf_float +#define GUF_DBUF_NAME dbuf_float #define GUF_T float #define GUF_T_IS_INTEGRAL_TYPE -#define GUF_IMPL_STATIC +#define GUF_DBUF_IMPL_STATIC #include "guf_dbuf.h" #define GUF_T guf_cstr_heap -#define GUF_CNT_NAME dbuf_heap_cstr +#define GUF_DBUF_NAME dbuf_heap_cstr #define GUF_T_COPY guf_cstr_heap_copy #define GUF_T_MOVE guf_cstr_heap_move #define GUF_T_FREE guf_cstr_heap_free #define GUF_T_EQ guf_cstr_heap_eq -#define GUF_IMPL_STATIC +#define GUF_DBUF_IMPL_STATIC // #define GUF_CNT_WITH_ELEM_CTX #include "guf_dbuf.h" #define GUF_T guf_cstr_const -#define GUF_CNT_NAME dbuf_const_cstr +#define GUF_DBUF_NAME dbuf_const_cstr #define GUF_T_EQ guf_cstr_const_eq -#define GUF_IMPL_STATIC +#define GUF_DBUF_IMPL_STATIC #include "guf_dbuf.h" -#define GUF_IMPL_STATIC +#define GUF_RAND_IMPL_STATIC #include "guf_rand.h" #include "guf_dict_impl.h" diff --git a/src/test/guf_dbuf_impl.c b/src/test/guf_dbuf_impl.c index 2265246..1b565d7 100644 --- a/src/test/guf_dbuf_impl.c +++ b/src/test/guf_dbuf_impl.c @@ -1,40 +1,46 @@ #include "guf_dbuf_impl.h" -#define GUF_CNT_NAME dbuf_int +#define GUF_DBUF_NAME dbuf_int #define GUF_T int #define GUF_T_IS_INTEGRAL_TYPE -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" -#define GUF_CNT_NAME dbuf_char +#define GUF_DBUF_NAME dbuf_i32 +#define GUF_T int32_t +#define GUF_T_IS_INTEGRAL_TYPE +#define GUF_DBUF_IMPL +#include "guf_dbuf.h" + +#define GUF_DBUF_NAME dbuf_char #define GUF_T char #define GUF_T_IS_INTEGRAL_TYPE -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" -#define GUF_CNT_NAME dbuf_float +#define GUF_DBUF_NAME dbuf_float #define GUF_T float #define GUF_T_IS_INTEGRAL_TYPE -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" #define GUF_T guf_cstr_heap -#define GUF_CNT_NAME dbuf_heap_cstr +#define GUF_DBUF_NAME dbuf_heap_cstr #define GUF_T_COPY guf_cstr_heap_copy #define GUF_T_MOVE guf_cstr_heap_move #define GUF_T_FREE guf_cstr_heap_free #define GUF_T_EQ guf_cstr_heap_eq -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" #define GUF_T guf_cstr_const -#define GUF_CNT_NAME dbuf_const_cstr +#define GUF_DBUF_NAME dbuf_const_cstr #define GUF_T_EQ guf_cstr_const_eq -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" #define GUF_T guf_str_view -#define GUF_CNT_NAME dbuf_str_view +#define GUF_DBUF_NAME dbuf_str_view #define GUF_T_EQ guf_str_view_equal -#define GUF_IMPL +#define GUF_DBUF_IMPL #include "guf_dbuf.h" diff --git a/src/test/guf_dbuf_impl.h b/src/test/guf_dbuf_impl.h index e448e69..8039abb 100644 --- a/src/test/guf_dbuf_impl.h +++ b/src/test/guf_dbuf_impl.h @@ -4,25 +4,28 @@ #include "guf_cstr.h" #include "guf_str.h" -#define GUF_CNT_NAME dbuf_int +#define GUF_DBUF_NAME dbuf_int #define GUF_T int #define GUF_T_IS_INTEGRAL_TYPE #include "guf_dbuf.h" -typedef unsigned char uchar; +#define GUF_DBUF_NAME dbuf_i32 +#define GUF_T int32_t +#define GUF_T_IS_INTEGRAL_TYPE +#include "guf_dbuf.h" -#define GUF_CNT_NAME dbuf_char +#define GUF_DBUF_NAME dbuf_char #define GUF_T char #define GUF_T_IS_INTEGRAL_TYPE #include "guf_dbuf.h" -#define GUF_CNT_NAME dbuf_float +#define GUF_DBUF_NAME dbuf_float #define GUF_T float #define GUF_T_IS_INTEGRAL_TYPE #include "guf_dbuf.h" #define GUF_T guf_cstr_heap -#define GUF_CNT_NAME dbuf_heap_cstr +#define GUF_DBUF_NAME dbuf_heap_cstr #define GUF_T_COPY guf_cstr_heap_copy #define GUF_T_MOVE guf_cstr_heap_move #define GUF_T_FREE guf_cstr_heap_free @@ -30,12 +33,12 @@ typedef unsigned char uchar; #include "guf_dbuf.h" #define GUF_T guf_cstr_const -#define GUF_CNT_NAME dbuf_const_cstr +#define GUF_DBUF_NAME dbuf_const_cstr #define GUF_T_EQ guf_cstr_const_eq #include "guf_dbuf.h" #define GUF_T guf_str_view -#define GUF_CNT_NAME dbuf_str_view +#define GUF_DBUF_NAME dbuf_str_view #define GUF_T_EQ guf_str_view_equal #include "guf_dbuf.h" diff --git a/src/test/guf_dict_impl.c b/src/test/guf_dict_impl.c index ff7615c..e56e05d 100644 --- a/src/test/guf_dict_impl.c +++ b/src/test/guf_dict_impl.c @@ -6,7 +6,7 @@ #define GUF_DICT_VAL_T int #define GUF_DICT_VAL_T_IS_INTEGRAL_TYPE #define GUF_DICT_NAME dict_cstr_int -#define GUF_IMPL +#define GUF_DICT_IMPL #include "guf_dict.h" #define GUF_DICT_KEY_T int32_t @@ -15,5 +15,5 @@ #define GUF_DICT_VAL_T bool #define GUF_DICT_VAL_T_IS_INTEGRAL_TYPE #define GUF_DICT_NAME dict_i32_bool -#define GUF_IMPL +#define GUF_DICT_IMPL #include "guf_dict.h" diff --git a/src/test/guf_rand_impl.c b/src/test/guf_rand_impl.c index 51c6b8f..5258f3d 100644 --- a/src/test/guf_rand_impl.c +++ b/src/test/guf_rand_impl.c @@ -1,2 +1,2 @@ -#define GUF_IMPL +#define GUF_RAND_IMPL #include "guf_rand.h" diff --git a/src/test/guf_sort_impl.c b/src/test/guf_sort_impl.c index 2c034be..3cef8cc 100644 --- a/src/test/guf_sort_impl.c +++ b/src/test/guf_sort_impl.c @@ -1,17 +1,17 @@ #include "guf_sort_impl.h" #define GUF_T float -#define GUF_IMPL +#define GUF_SORT_IMPL #include "guf_sort.h" #define GUF_T int32_t -#define GUF_IMPL +#define GUF_SORT_IMPL #include "guf_sort.h" #define GUF_T int8_t -#define GUF_IMPL +#define GUF_SORT_IMPL #include "guf_sort.h" #define GUF_T guf_cstr_heap -#define GUF_IMPL +#define GUF_SORT_IMPL #include "guf_sort.h" diff --git a/src/test/guf_sort_impl.h b/src/test/guf_sort_impl.h index 83b2451..6c4b7c9 100644 --- a/src/test/guf_sort_impl.h +++ b/src/test/guf_sort_impl.h @@ -1,5 +1,6 @@ #ifndef GUF_SORT_IMPL_H #define GUF_SORT_IMPL_H + #include "guf_cstr.h" #define GUF_T float diff --git a/src/test/guf_str_impl.c b/src/test/guf_str_impl.c new file mode 100644 index 0000000..8114902 --- /dev/null +++ b/src/test/guf_str_impl.c @@ -0,0 +1,2 @@ +#define GUF_STR_IMPL +#include "guf_str.h" diff --git a/src/test/guf_utf8_impl.c b/src/test/guf_utf8_impl.c deleted file mode 100644 index d4e6cc1..0000000 --- a/src/test/guf_utf8_impl.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "guf_utf8.h" - -#define GUF_IMPL -#include "guf_utf8.h" - -#define GUF_IMPL -#include "guf_str.h" diff --git a/src/test/test_dict.hpp b/src/test/test_dict.hpp index 12465b3..707230b 100644 --- a/src/test/test_dict.hpp +++ b/src/test/test_dict.hpp @@ -6,7 +6,6 @@ extern "C" { #include "guf_alloc_libc.h" #include "guf_dict_impl.h" - #include "guf_utf8.h" #include "guf_str.h" } @@ -27,12 +26,12 @@ struct DictCstrToIntTest : public Test dict_cstr_int_init(&word_cnt_dict, &guf_allocator_libc); dbuf_str_view delims = dbuf_str_view_new(&guf_allocator_libc); - for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(guf_utf8_whitespace); ++i) { - guf_str_view d = {.len = (ptrdiff_t)strlen(guf_utf8_whitespace[i]), .str = guf_utf8_whitespace[i]}; + for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(GUF_UTF8_WHITESPACE); ++i) { + guf_str_view d = {.len = (ptrdiff_t)strlen(GUF_UTF8_WHITESPACE[i]), .str = GUF_UTF8_WHITESPACE[i]}; dbuf_str_view_push_val(&delims, d); } - for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(guf_utf8_punctuation); ++i) { - guf_str_view d = {.len = (ptrdiff_t)strlen(guf_utf8_punctuation[i]), .str = guf_utf8_punctuation[i]}; + for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(GUF_UTF8_COMMON_PUNCT); ++i) { + guf_str_view d = {.len = (ptrdiff_t)strlen(GUF_UTF8_COMMON_PUNCT[i]), .str = GUF_UTF8_COMMON_PUNCT[i]}; dbuf_str_view_push_val(&delims, d); } guf_str_view input_str = {.str = text_buf.data, .len = text_buf.size}; diff --git a/src/test/test_utf8.hpp b/src/test/test_utf8.hpp index 02a1830..ce70ac1 100644 --- a/src/test/test_utf8.hpp +++ b/src/test/test_utf8.hpp @@ -6,7 +6,6 @@ extern "C" #include "guf_alloc_libc.h" #include "guf_dict_impl.h" #include "guf_dbuf_impl.h" - #include "guf_utf8.h" #include "guf_str.h" } @@ -117,6 +116,241 @@ struct UTF8Test : public Test return num_words; } + void encode_decode_file(const char *fname) + { + GUF_ASSERT_RELEASE(load_text(fname)); + + dbuf_i32 cp_buf = dbuf_i32_new(&guf_allocator_libc); + + ptrdiff_t valid_chars = 0, invalid_chars = 0; + guf_str_view input_str = {.str = text_buf.data, .len = text_buf.size}; + guf_utf8_char ch = {}; + for (guf_utf8_stat stat = guf_utf8_char_next(&ch, &input_str); stat != GUF_UTF8_READ_DONE; stat = guf_utf8_char_next(&ch, &input_str)) { + if (stat == GUF_UTF8_READ_VALID) { + ++valid_chars; + const int32_t codepoint = guf_utf8_decode(&ch); + TEST_CHECK(codepoint >= 0); + dbuf_i32_push_val(&cp_buf, codepoint); + } else { + ++invalid_chars; + const int32_t codepoint = guf_utf8_decode(&ch); + TEST_CHECK(codepoint < 0); + dbuf_i32_push_val(&cp_buf, -1); + } + } + TEST_CHECK(cp_buf.size == valid_chars + invalid_chars); + + guf_str_view in_str = {.str = text_buf.data, .len = text_buf.size}; + GUF_CNT_FOREACH(&cp_buf, dbuf_i32, it) { + GUF_ASSERT_RELEASE(it.ptr); + const int32_t codepoint = *it.ptr; + guf_utf8_char utf8_ch = {}; + const guf_utf8_stat stat = guf_utf8_char_next(&utf8_ch, &in_str); + if (codepoint >= 0) { + TEST_CHECK(stat == GUF_UTF8_READ_VALID); + guf_utf8_char encoded_ch = {}; + TEST_CHECK(guf_utf8_encode(&encoded_ch, codepoint)); + TEST_CHECK(guf_utf8_equal(&encoded_ch, &utf8_ch)); + } + } + guf_utf8_char utf8_ch = {}; + const guf_utf8_stat stat = guf_utf8_char_next(&utf8_ch, &in_str); + TEST_CHECK(stat == GUF_UTF8_READ_DONE); + + dbuf_i32_free(&cp_buf, NULL); + + free_text(); + } + + + void encode_decode() + { + guf_utf8_char utf8 = {0}; + + // 1 byte characters. + for (uint8_t ascii = 0; ascii <= 0x7F; ++ascii) { + TEST_CHECK(guf_utf8_encode(&utf8, ascii)); + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 1); + TEST_CHECK(utf8.bytes[0] == ascii); + TEST_CHECK(utf8.bytes[1] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == ascii); + } + + // 2 byte characters: + TEST_CHECK(guf_utf8_encode(&utf8, 0x00E6)); // "æ" (Latin Small Letter Ae) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xA6'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00E6); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00E5)); // "å" (Latin Small Letter A with Ring Above) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xA5'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00E5); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00F8)); // "ø" (Latin Small Letter O with Stroke) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xB8'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00F8); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00E4)); // "ä" (Latin Small Letter A with Diaeresis) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xA4'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00E4); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00F6)); // "ö" (Latin Small Letter O with Diaeresis) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xB6'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00F6); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00D6)); // "Ö" (Latin Capital Letter O with Diaeresis) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\x96'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00D6); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00FC)); // "ü" (Latin Small Letter U with Diaeresis) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC3' && utf8.bytes[1] == '\xBC'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00FC); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x00B5)); // "µ" (Micro Sign) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xC2' && utf8.bytes[1] == '\xB5'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x00B5); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x030A)); // "◌̊" (Combining Ring Above) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 2); + TEST_CHECK(utf8.bytes[0] == '\xCC' && utf8.bytes[1] == '\x8A'); + TEST_CHECK(utf8.bytes[2] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x030A); + + // 3 byte characters: + TEST_CHECK(guf_utf8_encode(&utf8, 0x7121)); // "無" (Nothingness; CJK Unified Ideograph-7121) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(!guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(utf8.bytes[0] == '\xE7' && utf8.bytes[1] == '\x84' && utf8.bytes[2] == '\xA1'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x7121); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x201E)); // "„" (Double Low-9 Quotation Mark) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(!guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(utf8.bytes[0] == '\xE2' && utf8.bytes[1] == '\x80' && utf8.bytes[2] == '\x9E'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x201E); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x20AC)); // "€" (Euro Sign) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(!guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(utf8.bytes[0] == '\xE2' && utf8.bytes[1] == '\x82' && utf8.bytes[2] == '\xAC'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x20AC); + + TEST_CHECK(guf_utf8_encode(&utf8, 0xFC51)); // "ﱑ" (Arabic Ligature Heh with Jeem Isolated Form) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(!guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(utf8.bytes[0] == '\xEF' && utf8.bytes[1] == '\xB1' && utf8.bytes[2] == '\x91'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0xFC51); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x1AA3)); // "᪣" (Tai Tham Sign Keow) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(!guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(utf8.bytes[0] == '\xE1' && utf8.bytes[1] == '\xAA' && utf8.bytes[2] == '\xA3'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x1AA3); + + TEST_CHECK(guf_utf8_encode(&utf8, GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT)); // "�" (Replacement Character) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 3); + TEST_CHECK(utf8.bytes[0] == '\xEF' && utf8.bytes[1] == '\xBF' && utf8.bytes[2] == '\xBD'); + TEST_CHECK(utf8.bytes[3] == '\0'); + TEST_CHECK(guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(guf_utf8_decode(&utf8) == GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT); + + // 4 byte characters: + TEST_CHECK(guf_utf8_encode(&utf8, 0x1F308)); // "🌈" (Rainbow) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 4); + TEST_CHECK(utf8.bytes[0] == '\xF0' && utf8.bytes[1] == '\x9F' && utf8.bytes[2] == '\x8C' && utf8.bytes[3] == '\x88'); + TEST_CHECK(utf8.bytes[4] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x1F308); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x130B8)); // "𓂸" (Egyptian Hieroglyph D052) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 4); + TEST_CHECK(utf8.bytes[0] == '\xF0' && utf8.bytes[1] == '\x93' && utf8.bytes[2] == '\x82' && utf8.bytes[3] == '\xB8'); + TEST_CHECK(utf8.bytes[4] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x130B8); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x1F97A)); // "🥺" (Face with Pleading Eyes) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 4); + TEST_CHECK(utf8.bytes[0] == '\xF0' && utf8.bytes[1] == '\x9F' && utf8.bytes[2] == '\xA5' && utf8.bytes[3] == '\xBA'); + TEST_CHECK(utf8.bytes[4] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x1F97A); + + TEST_CHECK(guf_utf8_encode(&utf8, 0x1F980)); // "🦀" (Crab) + TEST_CHECK(guf_utf8_char_num_bytes(&utf8) == 4); + TEST_CHECK(utf8.bytes[0] == '\xF0' && utf8.bytes[1] == '\x9F' && utf8.bytes[2] == '\xA6' && utf8.bytes[3] == '\x80'); + TEST_CHECK(utf8.bytes[4] == '\0'); + TEST_CHECK(guf_utf8_decode(&utf8) == 0x1F980); + + // Invalid characters: + utf8 = {.bytes = {'\xC0', '\x80', 0, 0, 0}}; + TEST_CHECK(guf_utf8_decode(&utf8) < 0); + + utf8 = {.bytes = {'\xC0', 0, 0, 0, 0}}; + TEST_CHECK(guf_utf8_decode(&utf8) < 0); + + utf8 = {.bytes = {'\x80', 0, 0, 0, 0}}; + TEST_CHECK(guf_utf8_decode(&utf8) < 0); + + // "The definition of UTF-8 prohibits encoding character numbers between U+D800 and U+DFFF" (surrogate pairs). + TEST_CHECK(!guf_utf8_encode(&utf8, 0xD800)); + TEST_CHECK(guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(guf_utf8_decode(&utf8) == GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT); + + TEST_CHECK(!guf_utf8_encode(&utf8, 0xDFFF)); + TEST_CHECK(guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(guf_utf8_decode(&utf8) == GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT); + + TEST_CHECK(!guf_utf8_encode(&utf8, 0xDA00)); + TEST_CHECK(guf_utf8_equal(&utf8, &GUF_UTF8_REPLACEMENT_CHAR)); + TEST_CHECK(guf_utf8_decode(&utf8) == GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT); + + char buf[] = {'\x2F', '\xC0', '\xAE', '\x2E', '\x2F'}; + guf_str_view input_str = {.str = buf, .len = GUF_STATIC_BUF_SIZE(buf)}; + guf_utf8_char ch = {}; + int valid_chars = 0, invalid_chars = 0; + for (guf_utf8_stat stat = guf_utf8_char_next(&ch, &input_str); stat != GUF_UTF8_READ_DONE; stat = guf_utf8_char_next(&ch, &input_str)) { + if (stat == GUF_UTF8_READ_VALID) { + ++valid_chars; + } else { + ++invalid_chars; + } + } + TEST_CHECK(invalid_chars == 2 && valid_chars == 3); + + char buf2[] = {'\xE0', '\x80', 'a', 'b', 'c'}; // 1 invalid 3-byte-character, 2 valid 1-byte-characters + input_str = {.str = buf2, .len = GUF_STATIC_BUF_SIZE(buf2)}; + ch = {}; + valid_chars = invalid_chars = 0; + for (guf_utf8_stat stat = guf_utf8_char_next(&ch, &input_str); stat != GUF_UTF8_READ_DONE; stat = guf_utf8_char_next(&ch, &input_str)) { + if (stat == GUF_UTF8_READ_VALID) { + // printf("%s", ch.bytes); + ++valid_chars; + } else { + // printf("%s", GUF_UTF8_REPLACEMENT_CHAR.bytes); + ++invalid_chars; + } + } + TEST_CHECK(invalid_chars == 1 && valid_chars == 2); + } + public: bool run() @@ -130,24 +364,24 @@ struct UTF8Test : public Test TEST_CHECK(valid == 2634 && invalid == 0); dbuf_str_view delims = dbuf_str_view_new(&guf_allocator_libc); - for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(guf_utf8_whitespace); ++i) { - guf_str_view d = {.len = (ptrdiff_t)strlen(guf_utf8_whitespace[i]), .str = guf_utf8_whitespace[i]}; + for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(GUF_UTF8_WHITESPACE); ++i) { + guf_str_view d = {.len = (ptrdiff_t)strlen(GUF_UTF8_WHITESPACE[i]), .str = GUF_UTF8_WHITESPACE[i]}; dbuf_str_view_push_val(&delims, d); } - for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(guf_utf8_punctuation); ++i) { - guf_str_view d = {.len = (ptrdiff_t)strlen(guf_utf8_punctuation[i]), .str = guf_utf8_punctuation[i]}; + for (size_t i = 0; i < GUF_STATIC_BUF_SIZE(GUF_UTF8_COMMON_PUNCT); ++i) { + guf_str_view d = {.len = (ptrdiff_t)strlen(GUF_UTF8_COMMON_PUNCT[i]), .str = GUF_UTF8_COMMON_PUNCT[i]}; dbuf_str_view_push_val(&delims, d); } - int words = count_words(TEST_DATA_DIR "/" "utf8-test.txt", &delims); - printf("words %d\n", words); TEST_CHECK(words == 422); - int words_with_delims = count_words_with_delims(TEST_DATA_DIR "/" "utf8-test.txt", &delims); TEST_CHECK(words_with_delims == 947); - dbuf_str_view_free(&delims, NULL); + encode_decode(); + encode_decode_file(TEST_DATA_DIR "/" "utf8-test.txt"); + + done = true; passed = (num_failed_checks == 0); return passed; diff --git a/todo.txt b/todo.txt index 48fe1c6..230f7a0 100644 --- a/todo.txt +++ b/todo.txt @@ -1,2 +1,5 @@ - guf_stack, guf_queue, guf_ringbuf -- guf_rand etc.: move guf_fn_keywors out of header guard? (-> no, add a GUF_WITHOUT_TYPES) \ No newline at end of file +- guf_rand etc.: move guf_fn_keywors out of header guard? (-> no, add a GUF_WITHOUT_TYPES) + +- unicode normalisation +- fix 32-bit dict (and add 32/64 bit defs in common.h) \ No newline at end of file