Compare commits
30 Commits
abandoned_
...
map
| Author | SHA1 | Date | |
|---|---|---|---|
| b1b99cb224 | |||
| 2ccfad3875 | |||
| e45152d20f | |||
| 0ee9771976 | |||
| ca8403112d | |||
| 6ae093c721 | |||
| 14935c3b74 | |||
| 89fd3a7af9 | |||
| daf5914a51 | |||
| df24bf2940 | |||
| ad569f5ed8 | |||
| 2c5a988001 | |||
| 3e3967c1ce | |||
| 7ea2195fcb | |||
| 7f8d34504a | |||
| 5d2b212d48 | |||
| fdc7ccc94d | |||
| 3382a51ad3 | |||
| 137a6e66fd | |||
| aba3f20e41 | |||
| c644b34b19 | |||
| abc9d87820 | |||
| b29b2fc46c | |||
| e7a184c538 | |||
| 0f8b624508 | |||
| 47d5d79538 | |||
| f0253c8fc2 | |||
| d8981dbb49 | |||
| 8e0bce6a53 | |||
| 376bdf151e |
12
README.md
12
README.md
@@ -1 +1,11 @@
|
||||
# evol-headers
|
||||
# evol headers
|
||||
|
||||
Project Initialization
|
||||
```
|
||||
meson setup --native-file=meson-native-clang --wipe build
|
||||
```
|
||||
|
||||
Build:
|
||||
```
|
||||
meson compile -C build
|
||||
```
|
||||
|
||||
2
buildfiles/ev_helpers.c
Normal file
2
buildfiles/ev_helpers.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#define EV_HELPERS_IMPLEMENTATION
|
||||
#include "../ev_helpers.h"
|
||||
@@ -78,6 +78,10 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(EV_BUILDTYPE_DEBUG) && !defined(EV_BUILDTYPE_DEBUG_OPT) && !defined(EV_BUILDTYPE_RELEASE)
|
||||
#define EV_BUILDTYPE_RELEASE 1
|
||||
#endif
|
||||
|
||||
#ifndef EV_BUILDTYPE_DEBUG
|
||||
# define EV_BUILDTYPE_DEBUG 0
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,6 @@ static inline u64 rotl64 ( u64 x, i8 r )
|
||||
|
||||
#endif // EV_CC_MSVC
|
||||
|
||||
#include "ev_macros.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Block read - if your platform needs to do endian-swapping or can only
|
||||
|
||||
47
ev_helpers.h
Normal file
47
ev_helpers.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
* \file ev_helpers.h
|
||||
*/
|
||||
#ifndef EV_HELPERS_HEADER
|
||||
#define EV_HELPERS_HEADER
|
||||
|
||||
#include "ev_macros.h"
|
||||
#include "ev_str.h"
|
||||
#if defined(EV_HELPERS_SHARED)
|
||||
# if defined (EV_HELPERS_IMPL)
|
||||
# define EV_HELPERS_API EV_EXPORT
|
||||
# else
|
||||
# define EV_HELPERS_API EV_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define EV_HELPERS_API
|
||||
#endif
|
||||
|
||||
EV_HELPERS_API evstring
|
||||
evstring_readFile(
|
||||
evstring filePath);
|
||||
|
||||
#ifdef EV_HELPERS_IMPLEMENTATION
|
||||
#undef EV_HELPERS_IMPLEMENTATION
|
||||
|
||||
evstring
|
||||
evstring_readFile(
|
||||
evstring filePath)
|
||||
{
|
||||
FILE* f = fopen(filePath, "rb");
|
||||
if(f == NULL) return EV_INVALID(evstring);
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 buflen = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
evstring res = evstring_new("");
|
||||
evstring_setLength(&res, buflen);
|
||||
fread(res, 1, buflen, f);
|
||||
fclose(f);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,9 +14,11 @@ typedef unsigned long long int u64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#if !defined(__cplusplus) && __STDC_VERSION__ < 202311L
|
||||
typedef _Bool bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define i8_const(v) (i8){v}
|
||||
#define i16_const(v) (i16){v}
|
||||
|
||||
208
ev_macros.h
208
ev_macros.h
@@ -11,6 +11,7 @@
|
||||
#define __EV_MACRO_IF_0_ELSE(...) __VA_ARGS__
|
||||
|
||||
#define __EV_MACRO_SECOND(a,b,...) b
|
||||
#define __EV_MACRO_SECOND_INDIRECT() __EV_MACRO_SECOND
|
||||
|
||||
#define __EV_MACRO_IS_PROBE(...) __EV_MACRO_SECOND(__VA_ARGS__,0)
|
||||
#define __EV_MACRO_PROBE() ~,1
|
||||
@@ -19,6 +20,9 @@
|
||||
#define __EV_MACRO_NOT_0 __EV_MACRO_PROBE()
|
||||
|
||||
#define __EV_MACRO_BOOL(x) __EV_MACRO_NOT(__EV_MACRO_NOT(x))
|
||||
|
||||
#define __EV_MACRO_NOP(...)
|
||||
#define __EV_MACRO_NOP_INDIRECT() __EV_MACRO_NOP
|
||||
// End Of: Internal Usage
|
||||
|
||||
/*!
|
||||
@@ -49,11 +53,13 @@
|
||||
# define EV_IMPORT __declspec(dllimport)
|
||||
# define EV_UNUSED
|
||||
# define EV_FORCEINLINE __forceinline
|
||||
# define EV_ALIGN(x) __declspec(align(x))
|
||||
#elif ( EV_CC_GCC || EV_CC_CLANG )
|
||||
# define EV_EXPORT __attribute__((visibility("default")))
|
||||
# define EV_IMPORT
|
||||
# define EV_UNUSED __attribute__((unused))
|
||||
# define EV_FORCEINLINE inline __attribute__((always_inline))
|
||||
# define EV_ALIGN(x) __attribute__((aligned(x)))
|
||||
# if ( EV_CC_GCC )
|
||||
# define EV_PRAGMA_CC_NAME GCC
|
||||
# define EV_WARNING_DISABLE_GCC(w) EV_PRAGMA(EV_PRAGMA_CC_NAME diagnostic ignored "-W"w)
|
||||
@@ -98,6 +104,7 @@
|
||||
* \brief Macro to get the size of a compile-time array.
|
||||
*/
|
||||
#define EV_ARRSIZE(...) (sizeof(__VA_ARGS__)/sizeof((__VA_ARGS__)[0]))
|
||||
#define EV_ARRSIZE_LITERAL(...) EV_EXPAND(EV_DEFER(EV_VA_ARGS_NARG)(EV_FILTER_EMPTY(__VA_ARGS__)))
|
||||
|
||||
/*!
|
||||
* \brief Macro to concatenate two tokens together.
|
||||
@@ -105,6 +112,11 @@
|
||||
#define EV_CAT(a, ...) EV_CAT_IMPL(a, __VA_ARGS__)
|
||||
#define EV_CAT_IMPL(a, ...) a##__VA_ARGS__
|
||||
|
||||
/*!
|
||||
* \brief Macro to concatenate multiple tokens together
|
||||
*/
|
||||
#define EV_CATN(...) EV_REDUCE(EV_CAT, __VA_ARGS__)
|
||||
|
||||
/*!
|
||||
* \brief Macro to wrap tokens in double quotations. (")
|
||||
*/
|
||||
@@ -136,6 +148,27 @@
|
||||
#define EV_VA_ARGS_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, N, ...) N
|
||||
#define EV_VA_ARGS_RSEQ_N() 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
#define EV_EVAL(...) __EV_INTERNAL_EVAL1(__EV_INTERNAL_EVAL1(__EV_INTERNAL_EVAL1(__EV_INTERNAL_EVAL1(__VA_ARGS__))))
|
||||
#define __EV_INTERNAL_EVAL1(...) __EV_INTERNAL_EVAL2(__EV_INTERNAL_EVAL2(__EV_INTERNAL_EVAL2(__EV_INTERNAL_EVAL2(__VA_ARGS__))))
|
||||
#define __EV_INTERNAL_EVAL2(...) __EV_INTERNAL_EVAL3(__EV_INTERNAL_EVAL3(__EV_INTERNAL_EVAL3(__EV_INTERNAL_EVAL3(__VA_ARGS__))))
|
||||
#define __EV_INTERNAL_EVAL3(...) __EV_INTERNAL_EVAL4(__EV_INTERNAL_EVAL4(__EV_INTERNAL_EVAL4(__EV_INTERNAL_EVAL4(__VA_ARGS__))))
|
||||
#define __EV_INTERNAL_EVAL4(...) __VA_ARGS__
|
||||
// #define __EV_INTERNAL_EVAL4(...) __EV_INTERNAL_EVAL5(__EV_INTERNAL_EVAL5(__EV_INTERNAL_EVAL5(__EV_INTERNAL_EVAL5(__VA_ARGS__))))
|
||||
// #define __EV_INTERNAL_EVAL5(...) __EV_INTERNAL_EVAL6(__EV_INTERNAL_EVAL6(__EV_INTERNAL_EVAL6(__EV_INTERNAL_EVAL6(__VA_ARGS__))))
|
||||
// #define __EV_INTERNAL_EVAL6(...) __VA_ARGS__
|
||||
|
||||
#define EV_INDIRECT_OP_ELSE_NOP(OP_INDIRECT,...) \
|
||||
EV_DEFER \
|
||||
( \
|
||||
EV_VA_OPT_ELSE(__VA_ARGS__) \
|
||||
( \
|
||||
OP_INDIRECT \
|
||||
) \
|
||||
( \
|
||||
__EV_MACRO_NOP_INDIRECT \
|
||||
) \
|
||||
)()
|
||||
|
||||
/*!
|
||||
* \brief Similar functionality to `__VA_OPT__`
|
||||
* Used as follows:
|
||||
@@ -148,142 +181,53 @@
|
||||
|
||||
/*!
|
||||
* \brief Calls the passed macro for each element.
|
||||
* \note Maximum number of elements to iterate over is 64 elements.
|
||||
*/
|
||||
#define EV_FOREACH(OP, ...) EV_CAT(__EV_INTERNAL_FOREACH, EV_VA_ARGS_NARG(__VA_ARGS__))(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH1( OP, a ) OP(a)
|
||||
#define __EV_INTERNAL_FOREACH2( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH1( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH3( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH2( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH4( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH3( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH5( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH4( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH6( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH5( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH7( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH6( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH8( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH7( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH9( OP, a, ...) OP(a) __EV_INTERNAL_FOREACH8( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH10(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH9( OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH11(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH10(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH12(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH11(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH13(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH12(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH14(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH13(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH15(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH14(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH16(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH15(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH17(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH16(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH18(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH17(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH19(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH18(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH20(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH19(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH21(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH20(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH22(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH21(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH23(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH22(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH24(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH23(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH25(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH24(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH26(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH25(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH27(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH26(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH28(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH27(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH29(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH28(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH30(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH29(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH31(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH30(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH32(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH31(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH33(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH32(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH34(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH33(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH35(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH34(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH36(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH35(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH37(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH36(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH38(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH37(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH39(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH38(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH40(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH39(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH41(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH40(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH42(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH41(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH43(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH42(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH44(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH43(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH45(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH44(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH46(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH45(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH47(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH46(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH48(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH47(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH49(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH48(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH50(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH49(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH51(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH50(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH52(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH51(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH53(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH52(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH54(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH53(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH55(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH54(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH56(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH55(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH57(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH56(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH58(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH57(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH59(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH58(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH60(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH59(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH61(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH60(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH62(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH61(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH63(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH62(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH64(OP, a, ...) OP(a) __EV_INTERNAL_FOREACH63(OP, __VA_ARGS__)
|
||||
#define EV_FOREACH(OP, ...) \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_EVAL(__EV_INTERNAL_FOREACH_IMPL(OP, __VA_ARGS__)))
|
||||
#define __EV_INTERNAL_FOREACH_IMPL(OP, a, ...) \
|
||||
OP(a) EV_INDIRECT_OP_ELSE_NOP(__EV_INTERNAL_FOREACH_IMPL_INDIRECT, __VA_ARGS__)(OP, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH_IMPL_INDIRECT() __EV_INTERNAL_FOREACH_IMPL
|
||||
|
||||
/*!
|
||||
* \brief Same as EV_FOREACH but allows passing a UDATA token
|
||||
* \note Maximum number of elements to iterate over is 64 elements.
|
||||
*/
|
||||
#define EV_FOREACH_UDATA(OP, UDATA, ...) EV_CAT(EV_CAT(__EV_INTERNAL_FOREACH, EV_VA_ARGS_NARG(__VA_ARGS__)),_UDATA)(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH1_UDATA( OP, UDATA, a ) OP(UDATA, a)
|
||||
#define __EV_INTERNAL_FOREACH2_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH1_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH3_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH2_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH4_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH3_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH5_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH4_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH6_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH5_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH7_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH6_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH8_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH7_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH9_UDATA( OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH8_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH10_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH9_UDATA( OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH11_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH10_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH12_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH11_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH13_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH12_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH14_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH13_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH15_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH14_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH16_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH15_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH17_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH16_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH18_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH17_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH19_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH18_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH20_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH19_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH21_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH20_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH22_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH21_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH23_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH22_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH24_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH23_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH25_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH24_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH26_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH25_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH27_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH26_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH28_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH27_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH29_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH28_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH30_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH29_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH31_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH30_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH32_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH31_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH33_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH32_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH34_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH33_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH35_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH34_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH36_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH35_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH37_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH36_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH38_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH37_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH39_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH38_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH40_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH39_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH41_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH40_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH42_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH41_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH43_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH42_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH44_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH43_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH45_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH44_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH46_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH45_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH47_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH46_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH48_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH47_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH49_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH48_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH50_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH49_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH51_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH50_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH52_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH51_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH53_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH52_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH54_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH53_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH55_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH54_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH56_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH55_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH57_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH56_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH58_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH57_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH59_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH58_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH60_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH59_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH61_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH60_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH62_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH61_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH63_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH62_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH64_UDATA(OP, UDATA, a, ...) OP(UDATA, a) __EV_INTERNAL_FOREACH63_UDATA(OP, UDATA, __VA_ARGS__)
|
||||
#define EV_FOREACH_UDATA(OP, UDATA,...) \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_EVAL(__EV_INTERNAL_FOREACH_UDATA_IMPL(OP, UDATA, __VA_ARGS__)))
|
||||
#define __EV_INTERNAL_FOREACH_UDATA_IMPL(OP, UDATA, a, ...) \
|
||||
OP(UDATA, a) EV_INDIRECT_OP_ELSE_NOP(__EV_INTERNAL_FOREACH_UDATA_IMPL_INDIRECT, __VA_ARGS__)(OP, UDATA, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_FOREACH_UDATA_IMPL_INDIRECT() __EV_INTERNAL_FOREACH_UDATA_IMPL
|
||||
|
||||
#define EV_JOIN(...) \
|
||||
EV_JOIN_W_DELIM((,),__VA_ARGS__)
|
||||
|
||||
#define EV_JOIN_W_DELIM(delim, ...) \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_EVAL(__EV_INTERNAL_JOIN_W_DELIM_IMPL(delim, __VA_ARGS__)))
|
||||
#define __EV_INTERNAL_JOIN_W_DELIM_IMPL(delim, a, ...) \
|
||||
a EV_INDIRECT_OP_ELSE_NOP(EV_EXPAND delim __EV_INTERNAL_JOIN_W_DELIM_IMPL_INDIRECT, __VA_ARGS__)(delim, __VA_ARGS__)
|
||||
#define __EV_INTERNAL_JOIN_W_DELIM_IMPL_INDIRECT() __EV_INTERNAL_JOIN_W_DELIM_IMPL
|
||||
|
||||
#define DEFAULT_ZIP_OP(a, b) (a, b)
|
||||
#define EV_ZIP(list1, list2) \
|
||||
EV_ZIP_W_OP(DEFAULT_ZIP_OP, list1, list2)
|
||||
|
||||
#define EV_ZIP_W_OP(OP, list1, list2) \
|
||||
EV_VA_OPT(EV_EXPAND list1)(EV_EVAL(__EV_INTERNAL_ZIP_W_OP_IMPL(OP, list1, list2)))
|
||||
#define __EV_INTERNAL_ZIP_W_OP_IMPL(OP, list1, list2) \
|
||||
OP(EV_HEAD list1, EV_HEAD list2) EV_INDIRECT_OP_ELSE_NOP(__EV_INTERNAL_ZIP_W_OP_IMPL_INDIRECT, EV_TAIL list1)(OP, (EV_TAIL list1), (EV_TAIL list2))
|
||||
#define __EV_INTERNAL_ZIP_W_OP_IMPL_INDIRECT() , __EV_INTERNAL_ZIP_W_OP_IMPL
|
||||
|
||||
#define EV_REDUCE(OP, ...) \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_EVAL(EV_INDIRECT_OP_ELSE_NOP(__EV_INTERNAL_REDUCE_IMPL_INDIRECT, __VA_ARGS__)(OP, EV_HEAD(__VA_ARGS__), EV_TAIL(__VA_ARGS__))))
|
||||
#define __EV_INTERNAL_REDUCE_IMPL(OP, last, ...) \
|
||||
EV_DEFER(EV_VA_OPT_ELSE(__VA_ARGS__)(__EV_INTERNAL_REDUCE_IMPL_INDIRECT)(__EV_MACRO_SECOND_INDIRECT))()(OP, EV_VA_OPT_ELSE(__VA_ARGS__)(OP(last, EV_HEAD(__VA_ARGS__)))(last) EV_VA_OPT(__VA_ARGS__)(,EV_TAIL(__VA_ARGS__)))
|
||||
#define __EV_INTERNAL_REDUCE_IMPL_INDIRECT() __EV_INTERNAL_REDUCE_IMPL
|
||||
|
||||
/*!
|
||||
* \brief Macro to get a the hex value of a 4-number as a character
|
||||
*/
|
||||
#define EV_TOHEX_CHAR(c) (("0123456789abcdef")[c])
|
||||
|
||||
#define __EV_FILTER_EMPTY_OP(x) EV_VA_OPT_ELSE(x)(,x)()
|
||||
#define EV_FILTER_EMPTY(x,...) x EV_FOREACH(__EV_FILTER_EMPTY_OP, __VA_ARGS__)
|
||||
|
||||
#endif // EV_HEADERS_MACROS_H
|
||||
|
||||
248
ev_map.h
Normal file
248
ev_map.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*!
|
||||
* \file ev_map.h
|
||||
*/
|
||||
#ifndef EV_MAP_HEADER
|
||||
#define EV_MAP_HEADER
|
||||
#include "ev_internal.h"
|
||||
#include "ev_types.h"
|
||||
#include "ev_numeric.h"
|
||||
#include "ev_vec.h"
|
||||
|
||||
#define EV_MAP_MAGIC (0x65765F6D61705F74)
|
||||
|
||||
#if defined(EV_MAP_SHARED)
|
||||
# if defined (EV_MAP_IMPL)
|
||||
# define EV_MAP_API EV_EXPORT
|
||||
# else
|
||||
# define EV_MAP_API EV_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define EV_MAP_API
|
||||
#endif
|
||||
|
||||
#ifndef EV_MAP_INIT_CAP
|
||||
/*!
|
||||
* \brief Initial capacity that is first reserved when a map is initialized
|
||||
*/
|
||||
#define EV_MAP_INIT_CAP 32
|
||||
#endif
|
||||
|
||||
#ifndef EV_MAP_GROWTH_RATE
|
||||
/*!
|
||||
* \brief Rate at which a map grows whenever a resize is needed
|
||||
*/
|
||||
#define EV_MAP_GROWTH_RATE 3 / 2
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
u64 _magic;
|
||||
u64 length;
|
||||
u64 capacity;
|
||||
u64 seed;
|
||||
EvTypeData keyTypeData;
|
||||
EvTypeData valTypeData;
|
||||
ev_vec_t keys;
|
||||
ev_vec_t vals;
|
||||
} ev_map_t;
|
||||
|
||||
typedef enum {
|
||||
EV_MAP_ERR_NONE = 0,
|
||||
EV_MAP_ERR_OOM = 1
|
||||
} ev_map_error_t;
|
||||
TYPEDATA_GEN(ev_map_error_t, DEFAULT(EV_MAP_ERR_NONE));
|
||||
|
||||
#if defined(EV_MAP_SHORTNAMES)
|
||||
# define map_t ev_map_t
|
||||
|
||||
# define map_error_t ev_map_error_t
|
||||
|
||||
# define map(K,V) ev_map(K,V)
|
||||
|
||||
# define map_init ev_map_init
|
||||
/* # define vec_iter_begin ev_vec_iter_begin */
|
||||
/* # define vec_iter_end ev_vec_iter_end */
|
||||
/* # define vec_iter_next ev_vec_iter_next */
|
||||
/* # define vec_fini ev_vec_fini */
|
||||
/* # define vec_push ev_vec_push */
|
||||
/* # define vec_append ev_vec_append */
|
||||
/* # define vec_last ev_vec_last */
|
||||
/* # define vec_len ev_vec_len */
|
||||
/* # define vec_capacity ev_vec_capacity */
|
||||
/* # define vec_clear ev_vec_clear */
|
||||
/* # define vec_setlen ev_vec_setlen */
|
||||
/* # define vec_setcapacity ev_vec_setcapacity */
|
||||
/* # define vec_grow ev_vec_grow */
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief For the sake of readability
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_map(int,int) v = ev_map_init(int,int);
|
||||
* ```
|
||||
*/
|
||||
#define ev_map(K,V) struct { \
|
||||
u64 _magic; \
|
||||
u64 length; \
|
||||
u64 capacity; \
|
||||
u64 seed; \
|
||||
EvTypeData keyTypeData; \
|
||||
EvTypeData valTypeData; \
|
||||
ev_vec(K) keys; \
|
||||
ev_vec(V) vals; \
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param typeData The EvTypeData for the element that the vector will contain
|
||||
*
|
||||
* \returns A vector object
|
||||
*/
|
||||
EV_MAP_API ev_map_t*
|
||||
ev_map_init_impl(
|
||||
EvTypeData keyTypeData,
|
||||
EvTypeData valTypeData);
|
||||
|
||||
/*!
|
||||
* \brief Syntactic sugar for `ev_map_init_impl()`
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_map_init(i32,i64); // ev_map_init_impl(TypeData(i32),TypeData(i64));
|
||||
* ```
|
||||
*/
|
||||
#define ev_map_init(K,V) (void*)ev_map_init_impl(TypeData(K), TypeData(V))
|
||||
|
||||
/*!
|
||||
* \brief Syntactic sugar for `ev_vec_push_impl()` that allows multiple pushed in the same statement.
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_vec_t v;
|
||||
* i32 x = 1;
|
||||
* i32 y = 2;
|
||||
* ev_vec_push(&v, &x); // ev_vec_push_impl(&v, &x);
|
||||
* ev_vec_push(&v, &x, &y); // ev_vec_push_impl(&v, &x); ev_vec_push_impl(&v, &y);
|
||||
* ```
|
||||
*
|
||||
* *Note* This is possibly replaceable with a variadic function.
|
||||
*/
|
||||
#define ev_map_add(m, ...) \
|
||||
EV_FOREACH_UDATA(__ev_map_internal_add, m, __VA_ARGS__);
|
||||
#define __ev_map_internal_add(m, entry) ev_map_add_impl((ev_map_t*)m, EV_HEAD entry, EV_TAIL entry);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief A function that destroys a vector object. If the element type has a
|
||||
* destructor function, then this function is called on every element before
|
||||
* all reserved memory is freed.
|
||||
*
|
||||
* *Note*: For stack-allocated vectors (`svec`), destructors are called for
|
||||
* elements but no memory is freed.
|
||||
*
|
||||
* \param v A pointer to the vector that is being destroyed
|
||||
*/
|
||||
EV_MAP_API void
|
||||
ev_map_fini(
|
||||
ev_map_t* m);
|
||||
|
||||
EV_MAP_API void
|
||||
ev_map_add_impl(
|
||||
ev_map_t* m,
|
||||
void* key,
|
||||
void* val
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Calls the free operation (if exists) on every entry, then sets
|
||||
* the length to 0.
|
||||
*
|
||||
* \param v A pointer to the map object
|
||||
*
|
||||
* \returns 0 on success
|
||||
*/
|
||||
EV_MAP_API u32
|
||||
ev_map_clear(
|
||||
ev_map_t* m);
|
||||
|
||||
TYPEDATA_GEN(
|
||||
ev_map_t,
|
||||
INVALID(
|
||||
._magic = ~0ULL
|
||||
),
|
||||
);
|
||||
|
||||
#define EV_MAP_IMPLEMENTATION
|
||||
|
||||
#ifdef EV_MAP_IMPLEMENTATION
|
||||
#undef EV_MAP_IMPLEMENTATION
|
||||
|
||||
#ifdef EV_MAP_API_CHECK
|
||||
#define EV_VEC_CHECK(x) do { x; } while (0)
|
||||
#else
|
||||
#define EV_MAP_CHECK(x)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ev_map_t*
|
||||
ev_map_init_impl(
|
||||
EvTypeData keyTypeData,
|
||||
EvTypeData valTypeData)
|
||||
{
|
||||
ev_map_t* m = malloc(sizeof(ev_map_t));
|
||||
if(!m) return &EV_INVALID(ev_map_t);
|
||||
|
||||
m->_magic = EV_MAP_MAGIC;
|
||||
m->keyTypeData = keyTypeData;
|
||||
m->valTypeData = valTypeData;
|
||||
m->keys = ev_vec_init_impl(keyTypeData, EV_DEFAULT(ev_vec_overrides_t));
|
||||
m->vals = ev_vec_init_impl(valTypeData, EV_DEFAULT(ev_vec_overrides_t));
|
||||
|
||||
m->length = 0;
|
||||
|
||||
assert(ev_vec_capacity(&m->keys) == ev_vec_capacity(&m->vals));
|
||||
|
||||
m->capacity = ev_vec_capacity(&m->keys);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
ev_map_fini(
|
||||
ev_map_t* m)
|
||||
{
|
||||
ev_vec_fini(&m->keys);
|
||||
ev_vec_fini(&m->vals);
|
||||
free(m);
|
||||
}
|
||||
|
||||
u64
|
||||
_ev_map_hash(
|
||||
ev_map_t* m,
|
||||
void* key)
|
||||
{
|
||||
u64 clipMask = 0xFFFFFFFFFFFF;
|
||||
if(m->keyTypeData.hash_fn != NULL)
|
||||
return m->keyTypeData.hash_fn(key, m->seed) & clipMask;
|
||||
return ev_hash_murmur3(key, m->keyTypeData.size, m->seed) & clipMask;
|
||||
}
|
||||
|
||||
void
|
||||
ev_map_add_impl(
|
||||
ev_map_t* m,
|
||||
void* key,
|
||||
void* val)
|
||||
{
|
||||
u64 hash = _ev_map_hash(m, key);
|
||||
}
|
||||
|
||||
u32
|
||||
ev_map_clear(
|
||||
ev_map_t* m)
|
||||
{
|
||||
m->length = 0;
|
||||
return ev_vec_clear(m->keys) | ev_vec_clear(m->vals);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
15
ev_str.h
15
ev_str.h
@@ -44,7 +44,6 @@
|
||||
#endif
|
||||
|
||||
typedef char *evstring;
|
||||
TYPEDATA_GEN(evstring);
|
||||
|
||||
typedef enum {
|
||||
EV_STR_ERR_NONE = 0,
|
||||
@@ -193,6 +192,16 @@ evstring_findLastChar(
|
||||
const evstring text,
|
||||
const char c);
|
||||
|
||||
DEFINE_EQUAL_FUNCTION(evstring, Default)
|
||||
{
|
||||
return evstring_cmp(*(evstring*)self, *(evstring*)other) == 0;
|
||||
}
|
||||
|
||||
TYPEDATA_GEN(evstring,
|
||||
EQUAL(Default)
|
||||
);
|
||||
|
||||
|
||||
#if defined(EV_STR_IMPLEMENTATION)
|
||||
|
||||
#if EV_OS_WINDOWS
|
||||
@@ -429,7 +438,7 @@ evstring_push_impl(
|
||||
}
|
||||
|
||||
memcpy((*s) + meta->length, data, sz);
|
||||
printf("Memcpy: dst = (*s {%p}) + meta->length {%llu}, src = data {%p}, size = sz {%llu}\n", *s, meta->length, data, sz);
|
||||
// printf("Memcpy: dst = (*s {%p}) + meta->length {%llu}, src = data {%p}, size = sz {%llu}\n", *s, meta->length, data, sz);
|
||||
meta->length += sz;
|
||||
|
||||
(*s)[meta->length] = '\0';
|
||||
@@ -606,7 +615,7 @@ evstring_pushFmt_v(
|
||||
size_t old_len = evstring_getLength(*s);
|
||||
evstring_error_t res = evstring_setLength(s, old_len + fmt_len);
|
||||
if(res == EV_STR_ERR_NONE) {
|
||||
int write_res = vsnprintf((*s) + old_len, fmt_len, fmt, args);
|
||||
int write_res = vsnprintf((*s) + old_len, fmt_len+1, fmt, args);
|
||||
assert(write_res > 0);
|
||||
assert(write_res == fmt_len);
|
||||
}
|
||||
|
||||
156
ev_types.h
156
ev_types.h
@@ -8,7 +8,10 @@
|
||||
typedef void(*ev_copy_fn)(void *dst, void *src);
|
||||
typedef void(*ev_free_fn)(void *self);
|
||||
typedef u64(*ev_hash_fn)(void *self, u64 seed);
|
||||
typedef i32(*ev_cmp_fn)(void *self, void *other);
|
||||
typedef bool(*ev_equal_fn)(void *self, void *other);
|
||||
|
||||
typedef void(*ev_tostr_fn)(void *self, char *out);
|
||||
typedef u32(*ev_tostrlen_fn)();
|
||||
|
||||
typedef struct {
|
||||
EV_DEBUG(const char *name;)
|
||||
@@ -19,108 +22,108 @@ typedef struct {
|
||||
ev_copy_fn copy_fn;
|
||||
ev_free_fn free_fn;
|
||||
ev_hash_fn hash_fn;
|
||||
ev_cmp_fn cmp_fn;
|
||||
ev_equal_fn equal_fn;
|
||||
ev_tostr_fn tostr_fn;
|
||||
ev_tostrlen_fn tostrlen_fn;
|
||||
|
||||
void *default_val;
|
||||
void *invalid_val;
|
||||
} EvTypeData;
|
||||
|
||||
#define COPY_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_COPY_FUNCTION_,T),_),name)
|
||||
#define FREE_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_FREE_FUNCTION_,T),_),name)
|
||||
#define HASH_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_HASH_FUNCTION_,T),_),name)
|
||||
#define CMP_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_CMP_FUNCTION_ ,T),_),name)
|
||||
#define COPY_FUNCTION(T,name) EV_CATN(EV_COPY_FUNCTION_,T,_,name)
|
||||
#define FREE_FUNCTION(T,name) EV_CATN(EV_FREE_FUNCTION_,T,_,name)
|
||||
#define HASH_FUNCTION(T,name) EV_CATN(EV_HASH_FUNCTION_,T,_,name)
|
||||
#define EQUAL_FUNCTION(T,name) EV_CATN(EV_EQUAL_FUNCTION_,T,_,name)
|
||||
#define TOSTR_FUNCTION(T,name) EV_CATN(EV_TOSTR_FUNCTION_,T,_,name)
|
||||
#define TOSTRLEN_FUNCTION(T,name) EV_CATN(EV_TOSTRLEN_FUNCTION_,T,_,name)
|
||||
|
||||
#include <string.h>
|
||||
#define DEFINE_COPY_FUNCTION(T,name) void COPY_FUNCTION(T,name)(T *dst, T *src)
|
||||
#define DEFINE_DEFAULT_INTERNAL_COPY_FUNCTION(T) \
|
||||
static inline DEFINE_COPY_FUNCTION(T,__EV_INTERNAL) { memcpy(dst, src, sizeof(T)); }
|
||||
#define DEFINE_COPY_FUNCTION(T,name) static inline void COPY_FUNCTION(T,name)(T *dst, T *src)
|
||||
#define DEFINE_DEFAULT_COPY_FUNCTION(T) \
|
||||
DEFINE_COPY_FUNCTION(T,DEFAULT) { *dst = *src; }
|
||||
|
||||
#define DEFINE_FREE_FUNCTION(T,name) void FREE_FUNCTION(T,name)(T *self)
|
||||
#define DEFINE_DEFAULT_INTERNAL_FREE_FUNCTION(T) \
|
||||
static inline DEFINE_FREE_FUNCTION(T,__EV_INTERNAL) { (void)self; }
|
||||
#define DEFINE_FREE_FUNCTION(T,name) static inline void FREE_FUNCTION(T,name)(T *self)
|
||||
#define DEFINE_DEFAULT_FREE_FUNCTION(T) \
|
||||
DEFINE_FREE_FUNCTION(T,DEFAULT) { (void)self; }
|
||||
|
||||
#define DEFINE_HASH_FUNCTION(T,name) u64 HASH_FUNCTION(T,name)(T *self, u64 seed)
|
||||
#define DEFINE_DEFAULT_INTERNAL_HASH_FUNCTION(T) \
|
||||
static inline DEFINE_HASH_FUNCTION(T,__EV_INTERNAL) { return ev_hash_murmur3(self, sizeof(T), seed); }
|
||||
#define DEFINE_HASH_FUNCTION(T,name) static inline void HASH_FUNCTION(T,name)(T *self, u64 seed)
|
||||
#define DEFINE_DEFAULT_HASH_FUNCTION(T) \
|
||||
DEFINE_HASH_FUNCTION(T,DEFAULT) { ev_hash_murmur3(self, sizeof(T), seed); }
|
||||
|
||||
#define DEFINE_CMP_FUNCTION(T,name) i32 CMP_FUNCTION(T,name)(T *self, T *other)
|
||||
#define DEFINE_DEFAULT_INTERNAL_CMP_FUNCTION(T) \
|
||||
static inline DEFINE_CMP_FUNCTION(T,__EV_INTERNAL) { return memcmp(self, other, sizeof(T)); }
|
||||
#define DEFINE_EQUAL_FUNCTION(T,name) static inline bool EQUAL_FUNCTION(T,name)(T *self, T *other)
|
||||
// NOTE: This shouldn't be used for non-arithmetic types.
|
||||
#define DEFINE_DEFAULT_EQUAL_FUNCTION(T) \
|
||||
DEFINE_EQUAL_FUNCTION(T,DEFAULT) { return memcmp(self, other, sizeof(T)) == 0; }
|
||||
|
||||
#define DEFINE_TOSTR_FUNCTION(T,name) static inline void TOSTR_FUNCTION(T,name)(T *self, char* out)
|
||||
#define DEFINE_DEFAULT_TOSTR_FUNCTION(T) \
|
||||
DEFINE_TOSTR_FUNCTION(T,DEFAULT) \
|
||||
{ \
|
||||
for(int i = 0; i < sizeof(T); i++) \
|
||||
{ \
|
||||
u8 byte = ((u8*)self)[i];\
|
||||
out[i*2] = EV_TOHEX_CHAR((u32)(byte >> 4) & 0xf); \
|
||||
out[i*2+1] = EV_TOHEX_CHAR((u32)byte & 0xf); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_TOSTRLEN_FUNCTION(T,name) static inline u32 TOSTRLEN_FUNCTION(T,name)()
|
||||
#define DEFINE_DEFAULT_TOSTRLEN_FUNCTION(T) \
|
||||
DEFINE_TOSTRLEN_FUNCTION(T,DEFAULT) { return sizeof(T) * 2; }
|
||||
|
||||
#define DECLARE_COPY_FUNCTION(T,name) DEFINE_COPY_FUNCTION(T,name);
|
||||
#define DECLARE_FREE_FUNCTION(T,name) DEFINE_FREE_FUNCTION(T,name);
|
||||
#define DECLARE_HASH_FUNCTION(T,name) DEFINE_HASH_FUNCTION(T,name);
|
||||
#define DECLARE_CMP_FUNCTION(T,name) DEFINE_CMP_FUNCTION(T,name);
|
||||
|
||||
#define ACTIVE_COPY_FUNCTION(T) __EV_TYPE_INTERNAL_##T##_ACTIVE_COPY_FN
|
||||
#define ACTIVE_FREE_FUNCTION(T) __EV_TYPE_INTERNAL_##T##_ACTIVE_FREE_FN
|
||||
#define ACTIVE_HASH_FUNCTION(T) __EV_TYPE_INTERNAL_##T##_ACTIVE_HASH_FN
|
||||
#define ACTIVE_CMP_FUNCTION(T) __EV_TYPE_INTERNAL_##T##_ACTIVE_CMP_FN
|
||||
|
||||
#define COPY_FUNCTION_TYPE(T) __EV_TYPE_INTERNAL_##T##_COPY_FN_TYPE
|
||||
#define FREE_FUNCTION_TYPE(T) __EV_TYPE_INTERNAL_##T##_FREE_FN_TYPE
|
||||
#define HASH_FUNCTION_TYPE(T) __EV_TYPE_INTERNAL_##T##_HASH_FN_TYPE
|
||||
#define CMP_FUNCTION_TYPE(T) __EV_TYPE_INTERNAL_##T##_CMP_FN_TYPE
|
||||
|
||||
#define DEFINE_FUNCTION_TYPES(T) \
|
||||
typedef void(*COPY_FUNCTION_TYPE(T))(T*,T*); \
|
||||
typedef void(*FREE_FUNCTION_TYPE(T))(T*); \
|
||||
typedef u64(*HASH_FUNCTION_TYPE(T))(T*,u64); \
|
||||
typedef i32(*CMP_FUNCTION_TYPE(T))(T*,T*)
|
||||
|
||||
#define DEFINE_DEFAULT_INTERNAL_FUNCTIONS(T) \
|
||||
DEFINE_DEFAULT_INTERNAL_COPY_FUNCTION(T) \
|
||||
DEFINE_DEFAULT_INTERNAL_FREE_FUNCTION(T) \
|
||||
DEFINE_DEFAULT_INTERNAL_HASH_FUNCTION(T) \
|
||||
DEFINE_DEFAULT_INTERNAL_CMP_FUNCTION(T)
|
||||
#define DECLARE_EQUAL_FUNCTION(T,name) DEFINE_EQUAL_FUNCTION(T,name);
|
||||
#define DECLARE_TOSTR_FUNCTION(T,name) DEFINE_TOSTR_FUNCTION(T,name);
|
||||
#define DECLARE_TOSTRLEN_FUNCTION(T,name) DEFINE_TOSTRLEN_FUNCTION(T,name);
|
||||
|
||||
#define EV_OVERRIDE_VAR(T) EV_CAT(__ev_internal_override_var_,T)
|
||||
#define TypeData(T) EV_CAT(EV_TYPEDATA_,T)
|
||||
#define TYPEDATA_GEN(T, ...) \
|
||||
DEFINE_FUNCTION_TYPES(T); \
|
||||
DEFINE_DEFAULT_INTERNAL_FUNCTIONS(T); \
|
||||
static const COPY_FUNCTION_TYPE(T) ACTIVE_COPY_FUNCTION(T) = COPY_FUNCTION(T,__EV_INTERNAL); \
|
||||
static const FREE_FUNCTION_TYPE(T) ACTIVE_FREE_FUNCTION(T) = FREE_FUNCTION(T,__EV_INTERNAL); \
|
||||
static const HASH_FUNCTION_TYPE(T) ACTIVE_HASH_FUNCTION(T) = HASH_FUNCTION(T,__EV_INTERNAL); \
|
||||
static const CMP_FUNCTION_TYPE(T) ACTIVE_CMP_FUNCTION(T) = CMP_FUNCTION(T,__EV_INTERNAL); \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_FOREACH_UDATA(__EV_STRUCT_METHOD_DEF, T, __VA_ARGS__)) \
|
||||
EV_WARNING_PUSH(); \
|
||||
EV_WARNING_DISABLE_GCC("override-init"); \
|
||||
EV_WARNING_DISABLE_CLANG("override-init"); \
|
||||
EV_WARNING_DISABLE_CLANG("initializer-overrides"); \
|
||||
EV_UNUSED static const EvTypeData TypeData(T) = { \
|
||||
EV_DEBUG(.name = EV_STRINGIZE(T),) \
|
||||
.size = sizeof(T), \
|
||||
.alignment = EV_ALIGNOF(T), \
|
||||
.default_val = (void*)&(T){0}, \
|
||||
.invalid_val = (void*)&(T){0}, \
|
||||
.copy_fn = (ev_copy_fn)ACTIVE_COPY_FUNCTION(T), \
|
||||
.free_fn = (ev_free_fn)ACTIVE_FREE_FUNCTION(T), \
|
||||
.hash_fn = (ev_hash_fn)ACTIVE_HASH_FUNCTION(T), \
|
||||
.cmp_fn = (ev_cmp_fn) ACTIVE_CMP_FUNCTION(T) \
|
||||
EV_VA_OPT(__VA_ARGS__)(EV_FOREACH_UDATA(__EV_STRUCT_METHOD_DEF, T, __VA_ARGS__)) \
|
||||
}; \
|
||||
EV_WARNING_POP(); \
|
||||
EV_UNUSED static T EV_OVERRIDE_VAR(T)
|
||||
|
||||
#define __EV_STRUCT_METHOD_DEF(T, ...) EV_CATN(__EV_,EV_HEAD __VA_ARGS__,_FN)(T, EV_TAIL __VA_ARGS__)
|
||||
|
||||
#define COPY(...) (COPY , __VA_ARGS__)
|
||||
#define FREE(...) (FREE , __VA_ARGS__)
|
||||
#define HASH(...) (HASH , __VA_ARGS__)
|
||||
#define CMP(...) (CMP , __VA_ARGS__)
|
||||
#define DEFAULT(...) (DEFAULT, __VA_ARGS__)
|
||||
#define INVALID(...) (INVALID, __VA_ARGS__)
|
||||
#define EQUAL(...) (EQUAL , __VA_ARGS__)
|
||||
#define TOSTR(...) (TOSTR , __VA_ARGS__)
|
||||
#define TOSTRLEN(...) (TOSTRLEN , __VA_ARGS__)
|
||||
#define DEFAULT(...) (DEFAULT , __VA_ARGS__)
|
||||
#define INVALID(...) (INVALID , __VA_ARGS__)
|
||||
|
||||
#define __EV_STRUCT_METHOD_DEF(T, ...) EV_CAT(__EV_,EV_CAT(EV_HEAD __VA_ARGS__,_FN))(T, EV_TAIL __VA_ARGS__)
|
||||
#define __EV_COPY_FN(T,name) ACTIVE_COPY_FUNCTION(T) = (COPY_FUNCTION_TYPE(T)) COPY_FUNCTION(T,name);
|
||||
#define __EV_FREE_FN(T,name) ACTIVE_FREE_FUNCTION(T) = (FREE_FUNCTION_TYPE(T)) FREE_FUNCTION(T,name);
|
||||
#define __EV_HASH_FN(T,name) ACTIVE_HASH_FUNCTION(T) = (HASH_FUNCTION_TYPE(T)) HASH_FUNCTION(T,name);
|
||||
#define __EV_CMP_FN(T,name) ACTIVE_CMP_FUNCTION(T) = (CMP_FUNCTION_TYPE(T)) CMP_FUNCTION(T,name);
|
||||
#define __EV_COPY_FN(T,name) .copy_fn = (ev_copy_fn) COPY_FUNCTION(T,name),
|
||||
#define __EV_FREE_FN(T,name) .free_fn = (ev_free_fn) FREE_FUNCTION(T,name),
|
||||
#define __EV_HASH_FN(T,name) .hash_fn = (ev_hash_fn) HASH_FUNCTION(T,name),
|
||||
#define __EV_EQUAL_FN(T,name) .equal_fn = (ev_equal_fn) EQUAL_FUNCTION(T,name),
|
||||
#define __EV_TOSTR_FN(T,name) .tostr_fn = (ev_tostr_fn) TOSTR_FUNCTION(T,name),
|
||||
#define __EV_TOSTRLEN_FN(T,name) .tostrlen_fn = (ev_tostrlen_fn) TOSTRLEN_FUNCTION(T,name),
|
||||
#define __EV_DEFAULT_FN(T, ...) .default_val = (void*)&(T){ __VA_ARGS__ },
|
||||
#define __EV_INVALID_FN(T, ...) .invalid_val = (void*)&(T){ __VA_ARGS__ },
|
||||
|
||||
#define EV_COPY(T) TypeData(T).copy_fn
|
||||
#define EV_FREE(T) TypeData(T).free_fn
|
||||
#define EV_HASH(T) TypeData(T).hash_fn
|
||||
#define EV_CMP(T) TypeData(T).cmp_fn
|
||||
[[maybe_unused]]
|
||||
static void nop() {}
|
||||
#define METHOD_CHECK(T, ...) (__VA_ARGS__ EV_DEBUG(?__VA_ARGS__:(assert(!EV_STRINGIZE(__VA_ARGS__)"not defined"),(T)nop)))
|
||||
|
||||
#define EV_COPY(T) METHOD_CHECK(ev_copy_fn, TypeData(T).copy_fn)
|
||||
#define EV_FREE(T) METHOD_CHECK(ev_free_fn, TypeData(T).free_fn)
|
||||
#define EV_HASH(T) METHOD_CHECK(ev_hash_fn, TypeData(T).hash_fn)
|
||||
#define EV_EQUAL(T) METHOD_CHECK(ev_equal_fn, TypeData(T).equal_fn)
|
||||
#define EV_TOSTR(T) METHOD_CHECK(ev_tostr_fn, TypeData(T).tostr_fn)
|
||||
#define EV_TOSTRLEN(T) METHOD_CHECK(ev_tostrlen_fn, TypeData(T).tostrlen_fn)
|
||||
#define __EV_OVERRIDE_DEFAULT(T, ...) EV_OVERRIDE_VAR(T).__VA_ARGS__,
|
||||
#define __EV_DEFAULT_INTERNAL(T) (*(T*)TypeData(T).default_val)
|
||||
#define EV_DEFAULT(T, ...) EV_VA_OPT_ELSE(__VA_ARGS__) \
|
||||
@@ -130,4 +133,25 @@ typedef struct {
|
||||
(__EV_DEFAULT_INTERNAL(T))
|
||||
#define EV_INVALID(T) (*(T*)TypeData(T).invalid_val)
|
||||
|
||||
#if defined(EV_BUILDTYPE_DEBUG) || defined(EV_BUILDTYPE_DEBUGOPT)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
DEFINE_TOSTR_FUNCTION(EvTypeData, EvTypeDataStringize)
|
||||
{
|
||||
EV_DEBUG(
|
||||
sprintf(out,
|
||||
"TypeData:\n"
|
||||
EV_DEBUG("\t name: %s\n")
|
||||
"\t size: %u\n"
|
||||
"\t alig: %u\n",
|
||||
EV_DEBUG(self->name),
|
||||
self->size,
|
||||
self->alignment
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
TYPEDATA_GEN(EvTypeData,
|
||||
TOSTR(EvTypeDataStringize));
|
||||
|
||||
#endif // EV_HEADERS_TYPES_H
|
||||
|
||||
258
ev_vec.h
258
ev_vec.h
@@ -37,9 +37,7 @@
|
||||
#endif
|
||||
|
||||
typedef void *ev_vec_t;
|
||||
TYPEDATA_GEN(ev_vec_t);
|
||||
typedef void *ev_svec_t;
|
||||
TYPEDATA_GEN(ev_svec_t);
|
||||
|
||||
typedef enum {
|
||||
EV_VEC_ERR_NONE = 0,
|
||||
@@ -47,11 +45,19 @@ typedef enum {
|
||||
} ev_vec_error_t;
|
||||
TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE));
|
||||
|
||||
#if defined(EV_VEC_SHORTNAMES)
|
||||
#define vec_t ev_vec_t
|
||||
#define svec_t ev_svec_t
|
||||
typedef struct {
|
||||
ev_copy_fn copy;
|
||||
ev_equal_fn equal;
|
||||
ev_free_fn free;
|
||||
ev_tostr_fn tostr;
|
||||
} ev_vec_overrides_t;
|
||||
TYPEDATA_GEN(ev_vec_overrides_t);
|
||||
|
||||
#define vec_error_t ev_vec_error_t
|
||||
#if defined(EV_VEC_SHORTNAMES)
|
||||
# define vec_t ev_vec_t
|
||||
# define svec_t ev_svec_t
|
||||
|
||||
# define vec_error_t ev_vec_error_t
|
||||
|
||||
# define vec(T) ev_vec(T)
|
||||
# define svec(T) ev_svec(T)
|
||||
@@ -59,10 +65,10 @@ TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE));
|
||||
# define vec_init ev_vec_init
|
||||
# define svec_init ev_svec_init
|
||||
# define svec_init_w_cap ev_svec_init_w_cap
|
||||
# define svec_init_w_len ev_svec_init_w_len
|
||||
# define vec_iter_begin ev_vec_iter_begin
|
||||
# define vec_iter_end ev_vec_iter_end
|
||||
# define vec_iter_next ev_vec_iter_next
|
||||
# define vec_foreach ev_vec_foreach
|
||||
# define vec_fini ev_vec_fini
|
||||
# define vec_push ev_vec_push
|
||||
# define vec_append ev_vec_append
|
||||
@@ -79,7 +85,7 @@ TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE));
|
||||
* \brief For the sake of readability
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_vec(int) v = ev_vec_init(int, 0, 0);
|
||||
* ev_vec(int) v = ev_vec_init(int);
|
||||
* ```
|
||||
*/
|
||||
#define ev_vec(T) T*
|
||||
@@ -116,100 +122,115 @@ struct ev_vec_meta_t {
|
||||
*/
|
||||
EV_VEC_API ev_vec_t
|
||||
ev_vec_init_impl(
|
||||
EvTypeData typeData);
|
||||
EvTypeData typeData,
|
||||
ev_vec_overrides_t overrides);
|
||||
|
||||
/*!
|
||||
* \brief Syntactic sugar for `ev_vec_init_impl()`
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_vec_init(int); // ev_vec_init_impl(sizeof(int), NULL, NULL);
|
||||
* ev_vec_init(int, fn_destr); // ev_vec_init_impl(sizeof(int), NULL, fn_destr);
|
||||
* ev_vec_init(int, fn_cpy, fn_destr); // ev_vec_init_impl(sizeof(int), fn_cpy, fn_destr);
|
||||
* ev_vec_init(i32); // ev_vec_init_impl(TypeData(i32));
|
||||
* ```
|
||||
*/
|
||||
#define ev_vec_init(T) ev_vec_init_impl(TypeData(T))
|
||||
#define ev_vec_init(T, ...) ev_vec_init_impl(TypeData(T), EV_DEFAULT(ev_vec_overrides_t,__VA_ARGS__))
|
||||
|
||||
#define ev_svec_init(T, ...) __ev_svec_init_impl(T, EV_ARRSIZE((T[])__VA_ARGS__), __VA_ARGS__)
|
||||
#define ev_svec_init_w_cap(T, cap) __ev_svec_init_w_cap_impl(T, cap)
|
||||
#define ev_svec_init(T, ...) __ev_svec_init_impl(T, EV_ARRSIZE((T[])__VA_ARGS__), EV_ARRSIZE((T[])__VA_ARGS__), __VA_ARGS__)
|
||||
#define ev_svec_init_w_cap(T, cap) __ev_svec_init_impl(T, 0, cap)
|
||||
#define ev_svec_init_w_len(T, len) __ev_svec_init_impl(T, len, len)
|
||||
|
||||
#define __ev_svec_init_impl(T, len, ...) \
|
||||
(ev_svec(T))&((struct { \
|
||||
struct ev_vec_meta_t meta; \
|
||||
EV_ALIGNAS(EV_ALIGNOF(T)) T data[len]; \
|
||||
}) { \
|
||||
.meta.length = len, \
|
||||
.meta.capacity = len, \
|
||||
.meta.typeData.size = sizeof(T), \
|
||||
.meta.typeData.alignment = EV_ALIGNOF(T), \
|
||||
.meta.allocationType = EV_VEC_ALLOCATION_TYPE_STACK, \
|
||||
.data = __VA_ARGS__ \
|
||||
}).data
|
||||
|
||||
#define __ev_svec_init_w_cap_impl(T, cap) \
|
||||
(ev_svec(T))&((struct { \
|
||||
struct ev_vec_meta_t meta; \
|
||||
EV_ALIGNAS(EV_ALIGNOF(T)) T data[cap]; \
|
||||
}) { \
|
||||
.meta.length = 0, \
|
||||
.meta.capacity = cap, \
|
||||
.meta.typeData.size = sizeof(T), \
|
||||
.meta.typeData.alignment = EV_ALIGNOF(T), \
|
||||
.meta.allocationType = EV_VEC_ALLOCATION_TYPE_STACK, \
|
||||
.data = __EV_VEC_EMPTY_ARRAY \
|
||||
}).data
|
||||
|
||||
#define ev_vec_push(v, x) ev_vec_push_impl((ev_vec_t*)&v,&x);
|
||||
static struct ev_vec_meta_t *__svec_interm_md;
|
||||
#define __ev_svec_init_impl(T, len, cap, ...) ( \
|
||||
__svec_interm_md = (u8[sizeof(T)*cap + sizeof(struct ev_vec_meta_t)]){}, \
|
||||
*__svec_interm_md = (struct ev_vec_meta_t){ \
|
||||
.length = len, \
|
||||
.capacity = cap, \
|
||||
.typeData = TypeData(T), \
|
||||
.allocationType = EV_VEC_ALLOCATION_TYPE_STACK, \
|
||||
}, \
|
||||
EV_VA_OPT(__VA_ARGS__)(memcpy(&__svec_interm_md[1], (T[])__VA_ARGS__, sizeof((T[])__VA_ARGS__)),) \
|
||||
&(__svec_interm_md[1]) \
|
||||
)
|
||||
|
||||
/*!
|
||||
* \param v The vector that we want an iterator for
|
||||
* \brief Syntactic sugar for `ev_vec_push_impl()` that allows multiple pushed in the same statement.
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_vec_t v;
|
||||
* i32 x = 1;
|
||||
* i32 y = 2;
|
||||
* ev_vec_push(&v, &x); // ev_vec_push_impl(&v, &x);
|
||||
* ev_vec_push(&v, &x, &y); // ev_vec_push_impl(&v, &x); ev_vec_push_impl(&v, &y);
|
||||
* ```
|
||||
*
|
||||
* *Note* This is possibly replaceable with a variadic function.
|
||||
*/
|
||||
#define ev_vec_push(v, ...) \
|
||||
EV_FOREACH_UDATA(__ev_vec_internal_push, v, __VA_ARGS__);
|
||||
#define __ev_vec_internal_push(v, var) ev_vec_push_impl((ev_vec_t*)v, var);
|
||||
|
||||
/*!
|
||||
* \param v A pointer to the vector that we want an iterator for
|
||||
*
|
||||
* \returns A pointer to the first element in a vector
|
||||
*/
|
||||
EV_VEC_API void *
|
||||
ev_vec_iter_begin(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \param v The vector that we want an iterator for
|
||||
* \param v A pointer to the vector that we want an iterator for
|
||||
*
|
||||
* \returns A pointer to the memory block right after the last element in the vector
|
||||
*/
|
||||
EV_VEC_API void *
|
||||
ev_vec_iter_end(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief A function that increments an iterator to make it point to the next
|
||||
* element in the vector
|
||||
*
|
||||
* \param v The vector that is being iterated over
|
||||
* \param v A pointer to the vector that is being iterated over
|
||||
* \param iter Reference to the iterator that is being incremented
|
||||
*/
|
||||
EV_VEC_API void
|
||||
ev_vec_iter_next(
|
||||
ev_vec_t v,
|
||||
const ev_vec_t* v,
|
||||
void **iter);
|
||||
|
||||
/*!
|
||||
* \brief A function that destroys a vector object. If a destructor function was
|
||||
* passed while initializing the vector, then this function is called on every
|
||||
* element before all reserved memory is freed.
|
||||
* \brief A function that looks for the index of `val` in `v`
|
||||
*
|
||||
* \param v A pointer to the vector that is being iterated over
|
||||
* \param val A pointer to the object that will be compared with vector elements
|
||||
*
|
||||
* \returns If found, index of element in vector. Otherwise, -1.
|
||||
*/
|
||||
EV_VEC_API i32
|
||||
ev_vec_find(
|
||||
const ev_vec_t* v,
|
||||
void* val);
|
||||
|
||||
/*!
|
||||
* \brief A function that destroys a vector object. If the element type has a
|
||||
* destructor function, then this function is called on every element before
|
||||
* all reserved memory is freed.
|
||||
*
|
||||
* *Note*: For stack-allocated vectors (`svec`), destructors are called for
|
||||
* elements but no memory is freed.
|
||||
*
|
||||
* \param v The vector that is being destroyed
|
||||
* \param v A pointer to the vector that is being destroyed
|
||||
*/
|
||||
EV_VEC_API void
|
||||
ev_vec_fini(
|
||||
ev_vec_t v);
|
||||
ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief A function that copies a value to the end of a vector. If a copy
|
||||
* function was passed while initializing the vector, then this function is
|
||||
* called to copy the new element into the vector. Otherwise, memcpy is used
|
||||
* with a length of `vec_meta.elemsize`. If a resize is needed but fails due to
|
||||
* 'OOM' issues, then the vector is left unchanged and VEC_ERR_OOM is returned.
|
||||
* \brief A function that copies a value to the end of a vector. If the element
|
||||
* type has a copy function, then this function is called to copy the new element
|
||||
* into the vector. Otherwise, memcpy is used with a the element type size as a
|
||||
* copy length. If a resize is needed but fails due to 'OOM' issues, then the
|
||||
* vector is left unchanged and VEC_ERR_OOM is returned.
|
||||
*
|
||||
* For `svec`, as long as the capacity is more than the current size, a push
|
||||
* operation is permitted. Otherwise, the operation is treated as an OOM.
|
||||
@@ -235,7 +256,7 @@ ev_vec_push_impl(
|
||||
* desired amount, an append operation is permitted. Otherwise, the operation
|
||||
* is treated as an OOM.
|
||||
*
|
||||
* *NOTE* The vector's copy function is not used; this is merely a memcpy
|
||||
* *NOTE* The type's copy function is not used; this is merely a memcpy
|
||||
* operation. If a deep copy is needed, individually pushing the elements of
|
||||
* the array is the way to go.
|
||||
*
|
||||
@@ -276,48 +297,48 @@ ev_vec_pop(
|
||||
/*!
|
||||
* \brief A function that returns the last element in the vector.
|
||||
*
|
||||
* \param v Reference to the vector object
|
||||
* \param v A pointer to the vector object
|
||||
*
|
||||
* \returns Pointer to the last element in the vector. NULL if the vector is
|
||||
* empty.
|
||||
*/
|
||||
EV_VEC_API void *
|
||||
ev_vec_last(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief A function that returns the length of a vector
|
||||
*
|
||||
* \param v The vector object
|
||||
* \param v A pointer to the vector object
|
||||
*
|
||||
* \returns Current length of the vector
|
||||
*/
|
||||
EV_VEC_API u64
|
||||
ev_vec_len(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief A function that returns the capacity of a vector
|
||||
*
|
||||
* \param v The vector object
|
||||
* \param v A pointer to the vector object
|
||||
*
|
||||
* \returns Current capacity of the vector
|
||||
*/
|
||||
EV_VEC_API u64
|
||||
ev_vec_capacity(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief Calls the free operation (if exists) on every element, then sets
|
||||
* the length to 0.
|
||||
*
|
||||
* \param v The vector object
|
||||
* \param v A pointer to the vector object
|
||||
*
|
||||
* \returns 0 on success
|
||||
*/
|
||||
EV_VEC_API u32
|
||||
ev_vec_clear(
|
||||
ev_vec_t v);
|
||||
const ev_vec_t* v);
|
||||
|
||||
/*!
|
||||
* \brief Sets the length of the vector to `len`.
|
||||
@@ -365,11 +386,34 @@ EV_VEC_API ev_vec_error_t
|
||||
ev_vec_grow(
|
||||
ev_vec_t *v);
|
||||
|
||||
static const ev_vec_t EV_VEC_EMPTY =
|
||||
(ev_vec(i32))&((struct {
|
||||
struct ev_vec_meta_t meta;
|
||||
EV_ALIGNAS(EV_ALIGNOF(i32)) i32 data[0];
|
||||
}) {
|
||||
.meta.length = 0,
|
||||
.meta.capacity = 0,
|
||||
.meta.typeData = TypeData(i32),
|
||||
.meta.allocationType = EV_VEC_ALLOCATION_TYPE_STACK,
|
||||
.data = __EV_VEC_EMPTY_ARRAY
|
||||
}).data;
|
||||
|
||||
TYPEDATA_GEN(
|
||||
ev_vec_t,
|
||||
INVALID(EV_VEC_EMPTY)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(
|
||||
ev_svec_t,
|
||||
INVALID(EV_VEC_EMPTY)
|
||||
);
|
||||
|
||||
|
||||
#ifdef EV_VEC_IMPLEMENTATION
|
||||
#undef EV_VEC_IMPLEMENTATION
|
||||
|
||||
#ifdef EV_VEC_API_CHECK
|
||||
#define EV_VEC_CHECK(x) do { x; } while(0)
|
||||
#define EV_VEC_CHECK(x) do { x; } while (0)
|
||||
#else
|
||||
#define EV_VEC_CHECK(x)
|
||||
#endif
|
||||
@@ -388,12 +432,22 @@ ev_vec_grow(
|
||||
|
||||
ev_vec_t
|
||||
ev_vec_init_impl(
|
||||
EvTypeData typeData)
|
||||
EvTypeData typeData,
|
||||
ev_vec_overrides_t overrides)
|
||||
{
|
||||
void *v = malloc(sizeof(struct ev_vec_meta_t) + (EV_VEC_INIT_CAP * typeData.size));
|
||||
if (!v)
|
||||
return NULL;
|
||||
|
||||
if(overrides.copy)
|
||||
typeData.copy_fn = overrides.copy;
|
||||
if(overrides.equal)
|
||||
typeData.equal_fn = overrides.equal;
|
||||
if(overrides.free)
|
||||
typeData.free_fn = overrides.free;
|
||||
if(overrides.tostr)
|
||||
typeData.tostr_fn = overrides.tostr;
|
||||
|
||||
struct ev_vec_meta_t *metadata = (struct ev_vec_meta_t *)v;
|
||||
*metadata = (struct ev_vec_meta_t){
|
||||
.length = 0,
|
||||
@@ -405,11 +459,36 @@ ev_vec_init_impl(
|
||||
return metadata + 1;
|
||||
}
|
||||
|
||||
i32
|
||||
ev_vec_find(
|
||||
const ev_vec_t* v,
|
||||
void *val)
|
||||
{
|
||||
__ev_vec_getmeta(*v)
|
||||
if(metadata->typeData.equal_fn) {
|
||||
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v); ev_vec_iter_next(v, &elem)) {
|
||||
if(metadata->typeData.equal_fn(elem, val))
|
||||
{
|
||||
return (elem - *v) / metadata->typeData.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v); ev_vec_iter_next(v, &elem)) {
|
||||
if(memcmp(elem, val, metadata->typeData.size) == 0)
|
||||
{
|
||||
return (elem - *v) / metadata->typeData.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
ev_vec_fini(
|
||||
ev_vec_t v)
|
||||
ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
|
||||
if (metadata->typeData.free_fn) {
|
||||
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v);
|
||||
@@ -420,6 +499,8 @@ ev_vec_fini(
|
||||
if(metadata->allocationType == EV_VEC_ALLOCATION_TYPE_HEAP) {
|
||||
free(metadata);
|
||||
}
|
||||
|
||||
*v = EV_INVALID(ev_vec_t);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -450,26 +531,26 @@ ev_vec_push_impl(
|
||||
|
||||
void *
|
||||
ev_vec_iter_begin(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
return v;
|
||||
return *v;
|
||||
}
|
||||
|
||||
void *
|
||||
ev_vec_iter_end(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
|
||||
return ((char *)v) + (metadata->typeData.size * metadata->length);
|
||||
return ((char *)*v) + (metadata->typeData.size * metadata->length);
|
||||
}
|
||||
|
||||
void
|
||||
ev_vec_iter_next(
|
||||
ev_vec_t v,
|
||||
const ev_vec_t* v,
|
||||
void **iter)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
*iter = ((char*)*iter) + metadata->typeData.size;
|
||||
}
|
||||
|
||||
@@ -523,38 +604,38 @@ ev_vec_pop(
|
||||
|
||||
void *
|
||||
ev_vec_last(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
|
||||
if(metadata->length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((char *)v) + ((metadata->length-1) * metadata->typeData.size);
|
||||
return ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
|
||||
}
|
||||
|
||||
u64
|
||||
ev_vec_len(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
return metadata->length;
|
||||
}
|
||||
|
||||
u64
|
||||
ev_vec_capacity(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
return metadata->capacity;
|
||||
}
|
||||
|
||||
u32
|
||||
ev_vec_clear(
|
||||
ev_vec_t v)
|
||||
const ev_vec_t* v)
|
||||
{
|
||||
__ev_vec_getmeta(v)
|
||||
__ev_vec_getmeta(*v)
|
||||
|
||||
if (metadata->typeData.free_fn) {
|
||||
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v);
|
||||
@@ -582,9 +663,6 @@ ev_vec_setlen(
|
||||
__ev_vec_syncmeta(*v)
|
||||
}
|
||||
|
||||
// TODO if new_len < old_len:
|
||||
// vec_pop(old_len - new_len)
|
||||
|
||||
metadata->length = len;
|
||||
return EV_VEC_ERR_NONE;
|
||||
}
|
||||
|
||||
22
map_test.c
Normal file
22
map_test.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define EV_MAP_IMPLEMENTATION
|
||||
#include "ev_map.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 10;
|
||||
int y = 100;
|
||||
int x2 = 300;
|
||||
int y2 = 123;
|
||||
|
||||
ev_map(i32, i32)* m = ev_map_init(i32, i32);
|
||||
ev_map_add(m, (&x, &y), (&x2, &y2));
|
||||
|
||||
i32 out;
|
||||
ev_map_get(m, &x, &out);
|
||||
|
||||
ev_map_fini(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
4
meson-native-clang
Normal file
4
meson-native-clang
Normal file
@@ -0,0 +1,4 @@
|
||||
[binaries]
|
||||
c = 'clang.exe'
|
||||
c_ld = 'lld'
|
||||
cpp = 'clang++.exe'
|
||||
12
meson.build
12
meson.build
@@ -1,5 +1,5 @@
|
||||
project('evol-headers', 'c',
|
||||
default_options : [ 'c_std=gnu17' ])
|
||||
default_options : [ 'c_std=gnu23' ])
|
||||
|
||||
headers_include = include_directories('.')
|
||||
|
||||
@@ -16,24 +16,34 @@ endif
|
||||
cc = meson.get_compiler('c')
|
||||
if cc.get_id() == 'msvc'
|
||||
evh_c_args += '/Zc:preprocessor'
|
||||
elif cc.get_id() == 'clang'
|
||||
evh_c_args += '-DEV_CC_CLANG=1'
|
||||
endif
|
||||
|
||||
# All other targets should follow the same template
|
||||
str_lib = static_library('ev_str', files('buildfiles/ev_str.c'), c_args: evh_c_args)
|
||||
vec_lib = static_library('ev_vec', files('buildfiles/ev_vec.c'), c_args: evh_c_args)
|
||||
helpers_lib = static_library('ev_helpers', files('buildfiles/ev_helpers.c'), c_args: evh_c_args)
|
||||
|
||||
str_dep = declare_dependency(link_with: str_lib, include_directories: headers_include)
|
||||
vec_dep = declare_dependency(link_with: vec_lib, include_directories: headers_include)
|
||||
helpers_dep = declare_dependency(link_with: helpers_lib, include_directories: headers_include)
|
||||
|
||||
headers_dep = declare_dependency(
|
||||
dependencies: [
|
||||
str_dep,
|
||||
vec_dep,
|
||||
helpers_dep,
|
||||
]
|
||||
)
|
||||
|
||||
# Tests
|
||||
str_test = executable('str_test', 'str_test.c', dependencies: [str_dep], c_args: evh_c_args)
|
||||
test('evstr', str_test)
|
||||
|
||||
if meson.version().version_compare('>= 0.54.0')
|
||||
meson.override_dependency('ev_vec', vec_dep)
|
||||
meson.override_dependency('ev_str', str_dep)
|
||||
meson.override_dependency('ev_helpers', helpers_dep)
|
||||
meson.override_dependency('evol-headers', headers_dep)
|
||||
endif
|
||||
|
||||
21
str_test.c
21
str_test.c
@@ -56,5 +56,26 @@ int main()
|
||||
assert(search_results[1].offset == 26);
|
||||
assert(search_results[2].offset == 56);
|
||||
|
||||
{ // PushFmt Bug
|
||||
printf("PushFmt Bug");
|
||||
evstring heap_str = evstring_new("Heap 'Hello, World!'");
|
||||
printf("Heap String: %s, Length: %llu\n", heap_str, evstring_getLength(heap_str));
|
||||
|
||||
evstring_error_t res = evstring_push(&heap_str, "%.05f", 1.0f);
|
||||
printf("Push Fmt #1: %s, New Length: %llu\n", heap_str, evstring_getLength(heap_str));
|
||||
assert(evstring_getLength(heap_str) == 27);
|
||||
assert(strcmp(heap_str, "Heap 'Hello, World!'1.00000") == 0);
|
||||
assert(res == EV_STR_ERR_NONE);
|
||||
|
||||
/*evstring_push(&heap_str, "%.05f, %.05f, %.05f", 1.0f, 2.0f, 3.0f);*/
|
||||
res = evstring_push(&heap_str, "Something");
|
||||
printf("Push Fmt #2: %s, New Length: %llu\n", heap_str, evstring_getLength(heap_str));
|
||||
assert(evstring_getLength(heap_str) == 36);
|
||||
assert(strcmp(heap_str, "Heap 'Hello, World!'1.00000Something") == 0);
|
||||
assert(res == EV_STR_ERR_NONE);
|
||||
|
||||
evstring_free(heap_str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
40
tostr_test.c
Normal file
40
tostr_test.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include "ev_types.h"
|
||||
#include "ev_numeric.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int age;
|
||||
char *desc;
|
||||
} Person;
|
||||
|
||||
DEFINE_TOSTR_FUNCTION(Person, PERSON_PRINT)
|
||||
{
|
||||
sprintf(out, "%s:\n\tage: %d\n\tdesc: %s", self->name, self->age, self->desc);
|
||||
}
|
||||
|
||||
TYPEDATA_GEN(Person,
|
||||
TOSTR(PERSON_PRINT),
|
||||
DEFAULT(
|
||||
.name = "sisyphus",
|
||||
.age = 9999,
|
||||
.desc = "One can only imagine him happy"
|
||||
),
|
||||
INVALID(
|
||||
.name = NULL,
|
||||
.age = -1,
|
||||
.desc = NULL
|
||||
)
|
||||
);
|
||||
|
||||
int main()
|
||||
{
|
||||
puts("");
|
||||
char out[256] = {};
|
||||
|
||||
Person sisyphue = EV_DEFAULT(Person);
|
||||
EV_TOSTR(Person)(&sisyphue, out);
|
||||
|
||||
puts(out);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user