From e668be2612007e47c57edc14d926599b84a0cc68 Mon Sep 17 00:00:00 2001 From: jun <83899451+zeichensystem@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:40:58 +0100 Subject: [PATCH] Add integer functions --- CMakeLists.txt | 2 +- src/guf_common.h | 1 + src/guf_common_utils.h | 46 +--------- src/guf_dbuf.h | 40 +++++--- src/guf_int.c | 65 +++++++++++++ src/guf_int.h | 202 +++++++++++++++++++++++++++++++++++++++++ src/guf_obj.h | 67 +++++++++----- src/guf_test.c | 51 +++++++++-- 8 files changed, 388 insertions(+), 86 deletions(-) create mode 100644 src/guf_int.c create mode 100644 src/guf_int.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d48b747..18818e1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) set(PROJECT_NAME libguf) project(${PROJECT_NAME}) -set(SOURCES src/guf_str.c src/guf_dict.c) +set(SOURCES src/guf_str.c src/guf_dict.c src/guf_int.c) add_library(${PROJECT_NAME} STATIC ${SOURCES}) # target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}}/lib/guf) diff --git a/src/guf_common.h b/src/guf_common.h index 5d0dcd6..d9f79a4 100644 --- a/src/guf_common.h +++ b/src/guf_common.h @@ -7,6 +7,7 @@ #include #include "guf_common_utils.h" +#include "guf_int.h" #include "guf_hash.h" #include "guf_assert.h" diff --git a/src/guf_common_utils.h b/src/guf_common_utils.h index 9dcf7f3..38dc18d 100644 --- a/src/guf_common_utils.h +++ b/src/guf_common_utils.h @@ -11,47 +11,11 @@ #define GUF_STATIC_BUF_SIZE(BUF) (sizeof((BUF)) / (sizeof((BUF)[0]))) -#define GUF_ABS(X) ((X) >= 0 ? (X) : -(X)) -#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)) - -static inline int guf_abs_int(int x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT_MIN ); return -x;} -static inline long guf_abs_lng(long x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > LONG_MIN ); return -x;} -static inline int8_t guf_abs_i8 (int8_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT8_MIN ); return -x;} -static inline int16_t guf_abs_i16(int16_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT16_MIN); return -x;} -static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT32_MIN); return -x;} -static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;} - -static inline bool guf_is_mul_overflow_size_t(size_t a, size_t b) -{ - size_t c = a * b; - return a != 0 && ((c / a) != b); -} - -static inline size_t guf_safe_mul_size_t(size_t a, size_t b) -{ - GUF_ASSERT_RELEASE(!guf_is_mul_overflow_size_t(a, b)); - return a * b; -} - -static inline bool guf_is_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) -{ - if (count < 0 || sizeof_elem <= 0) { - return false; - } - size_t size = guf_safe_mul_size_t(count, sizeof_elem); - return size <= PTRDIFF_MAX; -} - -static inline ptrdiff_t guf_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) -{ - GUF_ASSERT_RELEASE(count >= 0); - GUF_ASSERT_RELEASE(sizeof_elem > 0); - size_t size = guf_safe_mul_size_t(count, sizeof_elem); - GUF_ASSERT_RELEASE(size <= PTRDIFF_MAX); - return size; -} +#define GUF_LIFETIME_BLOCK(obj_init_code, obj_name, free_fn, code) do { \ + obj_init_code; \ + code;\ + free_fn(&obj_name);\ +} while (0); static inline bool guf_is_big_endian(void) { diff --git a/src/guf_dbuf.h b/src/guf_dbuf.h index a98f64e..1300faf 100644 --- a/src/guf_dbuf.h +++ b/src/guf_dbuf.h @@ -28,16 +28,16 @@ #error "Undefined container template GUF_CONTAINER_T" #endif +#ifndef GUF_CNT_T_OPS + #error "Undefined container template GUF_CNT_T_OPS" +#endif + #ifndef GUF_CNT_NAME #define GUF_CNT_NAME GUF_CAT(dbuf_, GUF_CNT_T) #endif -#ifndef GUF_CNT_T_OPS - #define GUF_OBJ_TYPE GUF_CNT_T - #include "guf_obj.h" - #define GUF_CNT_T_OPS GUF_OBJ_OPS_EMPTY(GUFCAT(GUF_CNT_T, _ops_type)) -#endif -#define GUF_CNT_T_OPS_CPY GUFCAT(GUFCAT(GUF_CNT_T, _ops_type), _cpy) +// TODO: does not work with custom obj_ops_typename +// #define GUF_CNT_T_OPS_CPY GUFCAT(GUFCAT(GUF_CNT_T, _ops_type), _cpy) typedef struct GUF_CNT_NAME { GUF_CNT_T *data; @@ -161,7 +161,14 @@ GUF_CNT_T *GUFCAT(GUF_CNT_NAME, _push)(GUF_CNT_NAME *dbuf, GUF_CNT_T *elem, guf_ } GUF_CNT_T *dst = dbuf->data + dbuf->size++; - return GUF_CNT_T_OPS_CPY(dst, elem, &GUF_CNT_T_OPS, cpy_opt); + bool cpy_success = false; + GUF_OBJ_CPY(GUF_CNT_T, GUF_CNT_T_OPS, dst, elem, cpy_opt, &cpy_success); + GUF_ASSERT(cpy_success); + if (cpy_success) { + return dst; + } else { + return NULL; + } } GUF_CNT_T *GUFCAT(GUF_CNT_NAME, _push_val)(GUF_CNT_NAME *dbuf, GUF_CNT_T elem) @@ -196,9 +203,19 @@ GUF_CNT_T *GUFCAT(GUF_CNT_NAME, _insert)(GUF_CNT_NAME *dbuf, GUF_CNT_T *elem, pt for (ptrdiff_t free_idx = dbuf->size++; free_idx > idx; --free_idx) { GUF_CNT_T *dst = dbuf->data + free_idx; GUF_CNT_T *src = dst - 1; - GUF_CNT_T_OPS_CPY(dst, src, &GUF_CNT_T_OPS, GUF_CPY_VALUE); + *dst = *src; + } + + GUF_CNT_T *dst = dbuf->data + idx; + bool cpy_success = false; + GUF_OBJ_CPY(GUF_CNT_T, GUF_CNT_T_OPS, dst, elem, cpy_opt, &cpy_success) + GUF_ASSERT(cpy_success); + + if (cpy_success) { + return dst; + } else { + return NULL; } - return GUF_CNT_T_OPS_CPY(dbuf->data + idx, elem, &GUF_CNT_T_OPS, cpy_opt); } void GUFCAT(GUF_CNT_NAME, _erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx) @@ -214,7 +231,7 @@ void GUFCAT(GUF_CNT_NAME, _erase)(GUF_CNT_NAME *dbuf, ptrdiff_t idx) for (ptrdiff_t free_idx = idx; free_idx < dbuf->size - 1; ++free_idx) { GUF_CNT_T *dst = dbuf->data + free_idx; GUF_CNT_T *src = dst + 1; - GUF_CNT_T_OPS_CPY(dst, src, &GUF_CNT_T_OPS, GUF_CPY_VALUE); + *dst = *src; } } @@ -232,7 +249,8 @@ GUF_CNT_T GUFCAT(GUF_CNT_NAME, pop_cpy)(GUF_CNT_NAME *dbuf, guf_obj_cpy_opt cpy_ GUF_ASSERT_RELEASE(GUFCAT(GUF_CNT_NAME, _valid_and_not_empty)(dbuf)); GUF_CNT_T *popped = dbuf->data + --dbuf->size; GUF_CNT_T popped_val; - GUF_CNT_T *success = GUF_CNT_T_OPS_CPY(&popped_val, popped, &GUF_CNT_T_OPS, cpy_opt); + bool success = false; + GUF_OBJ_CPY(GUF_CNT_T, GUF_CNT_T_OPS, &popped_val, popped, cpy_opt, &success); GUF_ASSERT_RELEASE(success); if (cpy_opt == GUF_CPY_DEEP && GUF_CNT_T_OPS.free) { diff --git a/src/guf_int.c b/src/guf_int.c new file mode 100644 index 0000000..8e442ef --- /dev/null +++ b/src/guf_int.c @@ -0,0 +1,65 @@ +#include "guf_int.h" + +#define GUF_DEFINE_INTEGER_CMP(int_type, fn_name) \ + int fn_name(const int_type *a, const int_type *b) {GUF_ASSERT(a && b); return (*a == *b ? 0 : *a < *b ? -1 : 1);} \ + GUF_OBJ_OPS_DEFINE_CMP_VOID(int_type, fn_name) \ + GUF_OBJ_OPS_DEFINE_CMP_VOID_INV(int_type, fn_name) + +#define GUF_DEFINE_INTEGER_OPS(int_type)\ + const GUFCAT(int_type, _ops_type) GUFCAT(int_type, _ops) = {\ + .cmp = GUFCAT(int_type, _cmp),\ + .cmp_void = GUFCAT(int_type, _cmp_void), \ + .cmp_void_inv = GUFCAT(int_type, _cmp_void_inv), \ + .eq = NULL, \ + .copy_init = NULL,\ + .move_init = NULL,\ + .free = NULL\ + };\ + +GUF_DEFINE_INTEGER_CMP(int, guf_int_cmp) +GUF_DEFINE_INTEGER_CMP(short, guf_short_cmp) +GUF_DEFINE_INTEGER_CMP(long, guf_long_cmp) +GUF_DEFINE_INTEGER_CMP(long long, guf_long_long_cmp) +GUF_DEFINE_INTEGER_CMP(int8_t, guf_int8_t_cmp) +GUF_DEFINE_INTEGER_CMP(int16_t, guf_int16_t_cmp) +GUF_DEFINE_INTEGER_CMP(int32_t, guf_int32_t_cmp) +GUF_DEFINE_INTEGER_CMP(int64_t, guf_int64_t_cmp) +GUF_DEFINE_INTEGER_CMP(ptrdiff_t, guf_ptrdiff_t_cmp) + +GUF_DEFINE_INTEGER_CMP(unsigned, guf_unsigned_cmp) +GUF_DEFINE_INTEGER_CMP(unsigned short, guf_unsigned_short_cmp) +GUF_DEFINE_INTEGER_CMP(unsigned long, guf_unsigned_long_cmp) +GUF_DEFINE_INTEGER_CMP(unsigned long long, guf_unsigned_long_long_cmp) +GUF_DEFINE_INTEGER_CMP(uint8_t, guf_uint8_t_cmp) +GUF_DEFINE_INTEGER_CMP(uint16_t, guf_uint16_t_cmp) +GUF_DEFINE_INTEGER_CMP(uint32_t, guf_uint32_t_cmp) +GUF_DEFINE_INTEGER_CMP(uint64_t, guf_uint64_t_cmp) +GUF_DEFINE_INTEGER_CMP(size_t, guf_size_t_cmp) + +GUF_DEFINE_INTEGER_CMP(char, guf_char_cmp) +GUF_DEFINE_INTEGER_CMP(unsigned char, guf_unsigned_char_cmp) + +GUF_DEFINE_INTEGER_CMP(float, guf_float_cmp) +GUF_DEFINE_INTEGER_CMP(double, guf_double_cmp) + +GUF_DEFINE_INTEGER_OPS(guf_int) +GUF_DEFINE_INTEGER_OPS(guf_short) +GUF_DEFINE_INTEGER_OPS(guf_long_long) +GUF_DEFINE_INTEGER_OPS(guf_int8_t) +GUF_DEFINE_INTEGER_OPS(guf_int16_t) +GUF_DEFINE_INTEGER_OPS(guf_int32_t) +GUF_DEFINE_INTEGER_OPS(guf_int64_t) + +GUF_DEFINE_INTEGER_OPS(guf_unsigned) +GUF_DEFINE_INTEGER_OPS(guf_unsigned_short) +GUF_DEFINE_INTEGER_OPS(guf_unsigned_long_long) +GUF_DEFINE_INTEGER_OPS(guf_uint8_t) +GUF_DEFINE_INTEGER_OPS(guf_uint16_t) +GUF_DEFINE_INTEGER_OPS(guf_uint32_t) +GUF_DEFINE_INTEGER_OPS(guf_uint64_t) + +GUF_DEFINE_INTEGER_OPS(guf_char) +GUF_DEFINE_INTEGER_OPS(guf_unsigned_char) + +GUF_DEFINE_INTEGER_OPS(guf_float) +GUF_DEFINE_INTEGER_OPS(guf_double) \ No newline at end of file diff --git a/src/guf_int.h b/src/guf_int.h new file mode 100644 index 0000000..9574a38 --- /dev/null +++ b/src/guf_int.h @@ -0,0 +1,202 @@ +#ifndef GUF_INT_H +#define GUF_INT_H +#include "guf_common.h" + +// Signed integer types: + +#define GUF_OBJ_TYPE int +#define GUF_OBJ_OPS_TYPENAME guf_int_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE short +#define GUF_OBJ_OPS_TYPENAME guf_short_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE long +#define GUF_OBJ_OPS_TYPENAME guf_long_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE long long +#define GUF_OBJ_OPS_TYPENAME guf_long_long_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE int8_t +#define GUF_OBJ_OPS_TYPENAME guf_int8_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE int16_t +#define GUF_OBJ_OPS_TYPENAME guf_int16_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE int32_t +#define GUF_OBJ_OPS_TYPENAME guf_int32_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE int64_t +#define GUF_OBJ_OPS_TYPENAME guf_int64_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE ptrdiff_t +#define GUF_OBJ_OPS_TYPENAME guf_ptrdiff_t_ops_type +#include "guf_obj.h" + +// Unsigned integer types: + +#define GUF_OBJ_TYPE unsigned +#define GUF_OBJ_OPS_TYPENAME guf_unsigned_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE unsigned short +#define GUF_OBJ_OPS_TYPENAME guf_unsigned_short_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE unsigned long +#define GUF_OBJ_OPS_TYPENAME guf_unsigned_long_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE unsigned long long +#define GUF_OBJ_OPS_TYPENAME guf_unsigned_long_long_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE uint8_t +#define GUF_OBJ_OPS_TYPENAME guf_uint8_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE uint16_t +#define GUF_OBJ_OPS_TYPENAME guf_uint16_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE uint32_t +#define GUF_OBJ_OPS_TYPENAME guf_uint32_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE uint64_t +#define GUF_OBJ_OPS_TYPENAME guf_uint64_t_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE size_t +#define GUF_OBJ_OPS_TYPENAME guf_size_t_ops_type +#include "guf_obj.h" + +// Signed/Unsigned character types: + +#define GUF_OBJ_TYPE char +#define GUF_OBJ_OPS_TYPENAME guf_char_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE unsigned char +#define GUF_OBJ_OPS_TYPENAME guf_unsigned_char_ops_type +#include "guf_obj.h" + +// Floating point: + +#define GUF_OBJ_TYPE float +#define GUF_OBJ_OPS_TYPENAME guf_float_ops_type +#include "guf_obj.h" + +#define GUF_OBJ_TYPE double +#define GUF_OBJ_OPS_TYPENAME guf_double_ops_type +#include "guf_obj.h" + +extern const guf_int_ops_type guf_int_ops; +extern const guf_short_ops_type guf_short_ops; +extern const guf_long_ops_type guf_long_ops; +extern const guf_long_long_ops_type guf_long_long_ops; +extern const guf_ptrdiff_t_ops_type guf_ptrdiff_t_ops; +extern const guf_int8_t_ops_type guf_int8_t_ops; +extern const guf_int16_t_ops_type guf_int16_t_ops; +extern const guf_int32_t_ops_type guf_int32_t_ops; +extern const guf_int64_t_ops_type guf_int64_t_ops; + +extern const guf_unsigned_ops_type guf_unsigned_ops; +extern const guf_unsigned_short_ops_type guf_unsigned_short_ops; +extern const guf_unsigned_long_ops_type guf_unsigned_long_ops; +extern const guf_unsigned_long_long_ops_type guf_unsigned_long_long_ops; +extern const guf_size_t_ops_type guf_size_t_ops; +extern const guf_uint8_t_ops_type guf_uint8_t_ops; +extern const guf_uint16_t_ops_type guf_uint16_t_ops; +extern const guf_uint32_t_ops_type guf_uint32_t_ops; +extern const guf_uint64_t_ops_type guf_uint64_t_ops; + +extern const guf_char_ops_type guf_char_ops; +extern const guf_unsigned_char_ops_type guf_unsigned_char_ops; + +extern const guf_float_ops_type guf_float_ops; +extern const guf_double_ops_type guf_double_ops; + +// #define GUF_ABS(X) ((X) >= 0 ? (X) : -(X)) +// #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_DEFINE_MIN_MAX_CLAMP(int_type, int_type_name)\ + static inline int_type GUFCAT(int_type_name, _min)(int_type a, int_type b) {return a >= b ? a : b;}\ + static inline int_type GUFCAT(int_type_name, _max)(int_type a, int_type b) {return a >= b ? a : b;}\ + static inline int_type GUFCAT(int_type_name, _clamp)(int_type x, int_type min, int_type max) {return GUFCAT(int_type_name, _max)(GUFCAT(int_type_name, _min)(x, max), min);} + +GUF_DEFINE_MIN_MAX_CLAMP(int, guf_int) +GUF_DEFINE_MIN_MAX_CLAMP(short, guf_short) +GUF_DEFINE_MIN_MAX_CLAMP(long, guf_long) +GUF_DEFINE_MIN_MAX_CLAMP(long long, guf_long_long) +GUF_DEFINE_MIN_MAX_CLAMP(int8_t, guf_int8_t) +GUF_DEFINE_MIN_MAX_CLAMP(int16_t, guf_int16_t) +GUF_DEFINE_MIN_MAX_CLAMP(int32_t, guf_int32_t) +GUF_DEFINE_MIN_MAX_CLAMP(int64_t, guf_int64_t) + +GUF_DEFINE_MIN_MAX_CLAMP(unsigned, guf_unsigned) +GUF_DEFINE_MIN_MAX_CLAMP(unsigned short, guf_unsigned_short) +GUF_DEFINE_MIN_MAX_CLAMP(unsigned long, guf_unsigned_long) +GUF_DEFINE_MIN_MAX_CLAMP(unsigned long long, guf_unsigned_long_long) +GUF_DEFINE_MIN_MAX_CLAMP(uint8_t, guf_uint8_t) +GUF_DEFINE_MIN_MAX_CLAMP(uint16_t, guf_uint16_t) +GUF_DEFINE_MIN_MAX_CLAMP(uint32_t, guf_uint32_t) +GUF_DEFINE_MIN_MAX_CLAMP(uint64_t, guf_uint64_t) + +GUF_DEFINE_MIN_MAX_CLAMP(char, guf_char) +GUF_DEFINE_MIN_MAX_CLAMP(unsigned char, guf_unsigned_char) + +#undef GUF_DEFINE_MIN_MAX_CLAMP + +static inline int guf_int(int x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT_MIN ); return -x;} +static inline long guf_abs_long(long x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > LONG_MIN ); return -x;} +static inline long long guf_abs_long_long(long long x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > LLONG_MIN ); return -x;} +static inline int8_t guf_abs_i8 (int8_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT8_MIN ); return -x;} +static inline int16_t guf_abs_i16(int16_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT16_MIN); return -x;} +static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT32_MIN); return -x;} +static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;} +static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > PTRDIFF_MIN); return -x;} + +static inline bool guf_is_mul_overflow_size_t(size_t a, size_t b) +{ + size_t c = a * b; + return a != 0 && ((c / a) != b); +} + +static inline size_t guf_safe_mul_size_t(size_t a, size_t b) +{ + GUF_ASSERT_RELEASE(!guf_is_mul_overflow_size_t(a, b)); + return a * b; +} + +static inline bool guf_is_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) +{ + if (count < 0 || sizeof_elem <= 0) { + return false; + } + if (guf_is_mul_overflow_size_t(count, sizeof_elem)) { + return false; + } + size_t size = (size_t)count * (size_t)sizeof_elem; + return size <= PTRDIFF_MAX; +} + +static inline ptrdiff_t guf_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) +{ + GUF_ASSERT_RELEASE(count >= 0); + GUF_ASSERT_RELEASE(sizeof_elem > 0); + size_t size = guf_safe_mul_size_t(count, sizeof_elem); + GUF_ASSERT_RELEASE(size <= PTRDIFF_MAX); + return size; +} + +#endif \ No newline at end of file diff --git a/src/guf_obj.h b/src/guf_obj.h index e04c6a5..f40e620 100644 --- a/src/guf_obj.h +++ b/src/guf_obj.h @@ -3,16 +3,28 @@ #include #include "guf_common.h" - // #define GUF_OBJ_OPS_VALUE_TYPE(obj_ops_type, eq, cmp, cmp_void, cmp_void_inv) (obj_ops_type){.copy_init = NULL, .move_init = NULL, .free = NULL, .eq = eq, .cmp = cmp, .cmp_void = cmp_void, .cmp_void_inv = cmp_void_inv} - #define GUF_OBJ_OPS_EMPTY(obj_ops_type) (obj_ops_type){.copy_init = NULL, .move_init = NULL, .free = NULL, .eq = NULL, .cmp = NULL, .cmp_void = NULL, .cmp_void_inv = NULL} + #define GUF_OBJ_OPS_INTEGRAL_TYPE(obj_ops_type, eq, cmp, cmp_void, cmp_void_inv) (obj_ops_type){.copy_init = NULL, .move_init = NULL, .free = NULL, .eq = eq, .cmp = cmp, .cmp_void = cmp_void, .cmp_void_inv = cmp_void_inv} + #define GUF_OBJ_OPS_EMPTY(obj_ops_type) (obj_ops_type){.copy_init = NULL, .move_init = NULL, .free = NULL, .eq = NULL, .cmp = NULL, .cmp_void = NULL, .cmp_void_inv = NULL} #define GUF_OBJ_OPS_DEFINE_CMP_VOID(obj_type, cmp_fn) int GUFCAT(cmp_fn, _void)(const void *a, const void *b) {return cmp_fn((const obj_type*)a, (const obj_type*)b);} #define GUF_OBJ_OPS_DEFINE_CMP_VOID_INV(obj_type, cmp_fn) int GUFCAT(cmp_fn, _void_inv)(const void *a, const void *b) {return -cmp_fn((const obj_type*)a, (const obj_type*)b);} - // #define GUF_OBJ_OPS_DEFINE_CMP_INVERSE(obj_type, cmp_fn) int GUFCAT(cmp_fn, _inv)(const obj_type *a, const obj_type *b) {return -cmp_fn(a, b);} - // #define GUF_OBJ_OPS_DEFINE_COPY_INIT_VOID(obj_type, copy_init_fn) void *GUFCAT(copy_init_fn, _void)(void *dst, const void *src) {return copy_init_fn((obj_type*)dst, (const obj_type*)src);} - // #define GUF_OBJ_OPS_DEFINE_MOVE_INIT_VOID(obj_type, move_init_fn) void *GUFCAT(move_init_fn, _void)(void *dst, const void *src) {return move_init_fn((obj_type*)dst, (const obj_type*)src);} - // #define GUF_OBJ_OPS_DEFINE_FREE_VOID(obj_type, free_fn) void GUFCAT(free_fn, _void)(void *a) {free_fn((obj_type*)a);} - // #define GUF_OBJ_OPS_DEFINE_EQ_VOID(obj_type, eq_fn) int GUFCAT(eq_fn, _void)(const void *a, const void *b) {return eq_fn((const obj_type*)a, (const obj_type*)b);} + + #define GUF_OBJ_CPY(obj_type, obj_ops, dst_ptr, src_ptr, cpy_opts, success_bool_ptr) do { \ + obj_type *obj_cpy_dst_ptr = dst_ptr;\ + obj_type *obj_cpy_src_ptr = src_ptr;\ + if (cpy_opt == GUF_CPY_VALUE) {\ + *obj_cpy_dst_ptr = *obj_cpy_src_ptr;\ + *success_bool_ptr = true;\ + } else if (cpy_opt == GUF_CPY_DEEP) {\ + GUF_ASSERT_RELEASE(obj_ops.copy_init);\ + if (obj_ops.copy_init(obj_cpy_dst_ptr, obj_cpy_src_ptr)) {*success_bool_ptr = true;} else {*success_bool_ptr = false;}\ + } else if (cpy_opt == GUF_CPY_MOVE) {\ + GUF_ASSERT_RELEASE(obj_ops.move_init);\ + if (obj_ops.move_init(obj_cpy_dst_ptr, obj_cpy_src_ptr)) {*success_bool_ptr = true;} else {*success_bool_ptr = false;}\ + } else {\ + GUF_ASSERT_RELEASE(false);\ + }\ + } while (0);\ #endif @@ -32,7 +44,12 @@ #define GUF_OBJ_OPS_TYPENAME GUFCAT(GUF_OBJ_TYPE, _ops_type) #endif +// #ifndef GUF_OBJ_OPS_NAME +// #define GUF_OBJ_OPS_TYPENAME GUFCAT(GUF_OBJ_TYPE, _ops) +// #endif + typedef struct GUF_OBJ_OPS_TYPENAME { + // GUF_OBJ_TYPE *(*init_from)(GUF_OBJ_TYPE *dst, GUF_OBJ_TYPE *src, guf_obj_cpy_opt cpy_opt); GUF_OBJ_TYPE *(*copy_init)(GUF_OBJ_TYPE *dst, const GUF_OBJ_TYPE *src); GUF_OBJ_TYPE *(*move_init)(GUF_OBJ_TYPE *dst, GUF_OBJ_TYPE *src); void (*free)(GUF_OBJ_TYPE *obj); @@ -42,24 +59,24 @@ typedef struct GUF_OBJ_OPS_TYPENAME { int (*cmp_void_inv)(const void *a, const void *b); } GUF_OBJ_OPS_TYPENAME; -static inline GUF_OBJ_TYPE *GUFCAT(GUF_OBJ_OPS_TYPENAME, _cpy) (GUF_OBJ_TYPE *dst, GUF_OBJ_TYPE *src, const GUF_OBJ_OPS_TYPENAME *ops, guf_obj_cpy_opt cpy_opt) -{ - GUF_ASSERT_RELEASE(dst); - GUF_ASSERT_RELEASE(src); - GUF_ASSERT_RELEASE(ops); - if (cpy_opt == GUF_CPY_VALUE) { - dst = memcpy(dst, src, sizeof(GUF_OBJ_TYPE)); - GUF_ASSERT_RELEASE(dst); // Should never fail. - } else if (cpy_opt == GUF_CPY_DEEP) { - GUF_ASSERT_RELEASE(ops->copy_init); - dst = ops->copy_init(dst, src); - } else if (cpy_opt == GUF_CPY_MOVE) { - GUF_ASSERT_RELEASE(ops->move_init); - dst = ops->move_init(dst, src); - } - GUF_ASSERT(dst); - return dst; -} +// static inline GUF_OBJ_TYPE *GUFCAT(GUF_OBJ_OPS_TYPENAME, _cpy) (GUF_OBJ_TYPE *dst, GUF_OBJ_TYPE *src, const GUF_OBJ_OPS_TYPENAME *ops, guf_obj_cpy_opt cpy_opt) +// { +// GUF_ASSERT_RELEASE(dst); +// GUF_ASSERT_RELEASE(src); +// GUF_ASSERT_RELEASE(ops); +// if (cpy_opt == GUF_CPY_VALUE) { +// dst = memcpy(dst, src, sizeof(GUF_OBJ_TYPE)); +// GUF_ASSERT_RELEASE(dst); // Should never fail. +// } else if (cpy_opt == GUF_CPY_DEEP) { +// GUF_ASSERT_RELEASE(ops->copy_init); +// dst = ops->copy_init(dst, src); +// } else if (cpy_opt == GUF_CPY_MOVE) { +// GUF_ASSERT_RELEASE(ops->move_init); +// dst = ops->move_init(dst, src); +// } +// GUF_ASSERT(dst); +// return dst; +// } #undef GUF_OBJ_TYPE #undef GUF_OBJ_OPS_TYPENAME \ No newline at end of file diff --git a/src/guf_test.c b/src/guf_test.c index d5d8ea6..633c952 100644 --- a/src/guf_test.c +++ b/src/guf_test.c @@ -1,11 +1,22 @@ #include #include #include +#include "guf_common.h" #include "guf_cstr.h" -#define GUF_DBUF_INITIAL_CAP 128 #define GUF_CNT_NAME dbuf_int #define GUF_CNT_T int +#define GUF_CNT_T_OPS guf_int_ops +#include "guf_dbuf.h" + +#define GUF_CNT_NAME dbuf_char +#define GUF_CNT_T char +#define GUF_CNT_T_OPS guf_char_ops +#include "guf_dbuf.h" + +#define GUF_CNT_NAME dbuf_float +#define GUF_CNT_T float +#define GUF_CNT_T_OPS guf_float_ops #include "guf_dbuf.h" #define GUF_CNT_NAME dbuf_const_cstr @@ -18,18 +29,42 @@ #define GUF_CNT_T_OPS guf_heap_cstr_ops #include "guf_dbuf.h" -typedef struct guf_test { - const char *name, *expected_output; - char *output; - void (*test_fn)(struct guf_test *test); - uint64_t runtime_ms; - bool passed; -} guf_test; +// typedef struct guf_test { +// const char *name, *expected_output; +// char *output; +// void (*test_fn)(struct guf_test *test); +// uint64_t runtime_ms; +// bool passed; +// } guf_test; int main(void) { bool success = true; + GUF_LIFETIME_BLOCK(dbuf_float floats = dbuf_float_new(), floats, dbuf_float_free, { + for (int i = 0; i < 16; ++i) { + dbuf_float_push_val(&floats, i % 2 ? i * 2.718f : i * -2.718f); + } + + GUF_FOREACH(&floats, dbuf_float, it) { + printf("float: %f\n", *it.cur); + } + + dbuf_float_sort(&floats, GUF_SORT_DESCENDING); + printf("Sorted.\n"); + GUF_FOREACH(&floats, dbuf_float, it) { + printf("float: %f\n", *it.cur); + } + }) + + dbuf_char str = dbuf_char_new(); + dbuf_char_push_val(&str, 'H'); + dbuf_char_push_val(&str, 'e'); + dbuf_char_push_val(&str, 'j'); + dbuf_char_push_val(&str, '\0'); + printf("str.data = %s\n", str.data); + dbuf_char_free(&str); + dbuf_int integers = dbuf_int_new(); dbuf_int_push_val(&integers, 420); printf("initial cap %td\n", integers.capacity);