Add integer functions

This commit is contained in:
jun 2025-01-07 11:40:58 +01:00
parent ad97de47a6
commit e668be2612
8 changed files with 388 additions and 86 deletions

View File

@ -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)

View File

@ -7,6 +7,7 @@
#include <assert.h>
#include "guf_common_utils.h"
#include "guf_int.h"
#include "guf_hash.h"
#include "guf_assert.h"

View File

@ -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)
{

View File

@ -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) {

65
src/guf_int.c Normal file
View File

@ -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)

202
src/guf_int.h Normal file
View File

@ -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

View File

@ -3,16 +3,28 @@
#include <string.h>
#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

View File

@ -1,11 +1,22 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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);