87 Commits

Author SHA1 Message Date
ea9d45625d Added ev_log
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 16:36:29 +03:00
2dcc69e692 Updated meson native files
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 16:36:20 +03:00
eb271ae2a8 Added .gitignore file
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 16:35:57 +03:00
d3bbc155af [ev_vec] Added ev_vec_dup
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 10:46:20 +03:00
77a594b36b [ev_types] Temporarily removed EV_CATN usage to fix TYPEDATA_GEN issues
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 10:46:00 +03:00
8410e66eb5 [ev_str] Added COPY and FREE to type data
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 10:45:09 +03:00
2daeb8652c Fixed compilation on linux
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-07 10:44:29 +03:00
fe5b9a131f Fixed warnings + add vec magic number
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-01-27 14:46:36 +02:00
2ccfad3875 Added a couple of new macros
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-12-06 17:30:56 +02:00
e45152d20f svec improvements
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-11-13 15:39:41 +02:00
0ee9771976 Fixed issue with incorrect open-mode being passed to fopen
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-11-08 16:26:12 +02:00
ca8403112d Added optional typedata overrides to ev_vec_init
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-28 14:37:24 +03:00
6ae093c721 Re-exposed ev_vec_pop
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-28 12:09:16 +03:00
14935c3b74 Added ev_helpers.h
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-20 14:53:59 +03:00
89fd3a7af9 ev_vec improvements
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 17:18:51 +03:00
daf5914a51 Changed equal_fn to return 'true' on equality
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 16:43:04 +03:00
df24bf2940 Added equal_fn to evstring TypeData
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 14:45:17 +03:00
ad569f5ed8 Added ev_vec_find
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 14:37:39 +03:00
2c5a988001 Reduced EV_EVAL depth for now
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 00:55:12 +03:00
3e3967c1ce Switched to clang and C23
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-13 00:48:40 +03:00
7ea2195fcb Added test case for pushFmt and added str_test as a meson unit test
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-06 23:43:56 +03:00
7f8d34504a Fixed issue with pushFmt producing incorrect output
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-06 23:43:07 +03:00
5d2b212d48 Fixed compilation error when ev_internal.h is included in a cpp file
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-06 23:42:25 +03:00
fdc7ccc94d Added default build type to not break linting
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2024-10-06 23:41:56 +03:00
3382a51ad3 ev_vec EV_INVALID added
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-06-27 21:18:08 +02:00
137a6e66fd ev_vec API changes
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-06-27 21:11:03 +02:00
aba3f20e41 Updated ev_vec documentation
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-06-27 19:21:42 +02:00
c644b34b19 Replaced nested EV_CATs with EV_CATN in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-06-03 23:17:01 +02:00
abc9d87820 Added EV_ALIGN
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-06-03 23:13:51 +02:00
b29b2fc46c Added more recursive macros
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-24 18:32:58 +02:00
e7a184c538 Reimplemented loops with recursion
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-23 17:08:06 +02:00
0f8b624508 Generated typedata for EvTypeData
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-18 22:06:43 +02:00
47d5d79538 Made type methods static for typedata generation in headers
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-18 22:06:08 +02:00
f0253c8fc2 Removed forgotten debug printf
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-18 22:05:43 +02:00
d8981dbb49 Added EV_TOSTR and EV_TOSTRLEN
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-17 22:53:43 +02:00
8e0bce6a53 Fixed ev_vec_push not supporting anonymous variables
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-05-17 20:41:30 +02:00
376bdf151e Update README.md 2022-02-23 09:28:04 +02:00
0d169433a4 Added default overrides in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-02-01 20:20:43 +02:00
f78561ab59 Fixed EV_WARNING_* for non-MSVC
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:53:40 +02:00
1455b26558 Fixed svec for non-MSVC
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:53:22 +02:00
66c00f6d6f Fixed MSVC compilation issues
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:53:05 +02:00
c49ab87286 Fixed svec warnings on MSVC
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:20:52 +02:00
40017d2ad0 Updated EV_WARNING_* usage in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:20:24 +02:00
0c35487ab3 Fixed double initialization of Float32
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:20:04 +02:00
9772bf6c43 Updated EV_WARNING_*
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 19:19:41 +02:00
7d8159d194 Added a meson build file
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 16:16:34 +02:00
0f91f5373c Fixed multiple shortnames in ev_vec
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-31 16:16:02 +02:00
94d6c4d8be Added some limitations on ev_svec_t so that it can be used in global scope
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 16:18:39 +00:00
757d9d5ae8 Fixed ev_vec_setlen bug
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 16:18:02 +00:00
7ec5d242aa Moved EV_STR_evstring_MAGIC to header part so that evstr(...) can use it
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 16:17:21 +00:00
34450de16d Parenthesized EV_INVALID and EV_DEFAULT macro expansions
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 16:16:34 +00:00
e0acb5b08a Disabled -Woverride-init in TYPEDATA_GEN
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 15:26:57 +00:00
88e2393000 Added EV_PRAGMA and EV_WARNING_* macros
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 15:23:32 +00:00
c373f03490 Fixed unused-const-variable in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-30 14:33:34 +00:00
32dc1e1a81 Added a simple str_test.c
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-29 20:01:57 +00:00
3fae966f63 Added EV_VA_OPT_ELSE to ev_macros
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-29 20:01:25 +00:00
b0be90cbba Added initial ev_str implementaiton
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-29 20:00:59 +00:00
9af63bac9c Fixed void pointer dereferencing in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-23 18:42:11 +00:00
b6e1fdc6fc Removed useless DEFAULT/INVALID
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-07 22:00:36 +00:00
82ad4b4bfb Changed how types are registered
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 23:11:20 +02:00
5b22053ff3 Number types changes
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 22:14:29 +02:00
140a0b4d34 Added EV_REGISTER_TYPE
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 21:42:19 +02:00
2d02e4cc66 Added EV_EQUAL function
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:55:17 +02:00
57f0533f84 Added bool to ev_internal
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:37:23 +02:00
af1ab56872 Changed ev_hash_fn signature and added default murmur3
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:26:03 +02:00
b68f56840e Changed murmur3 to take a 64-bit seed
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:25:38 +02:00
025acf4c97 Added ev_hash for hash functions
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:18:15 +02:00
0557a45481 Added EV_FORCEINLINE
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-05 03:18:01 +02:00
450ba063cf Added ev_vec.h
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 23:04:40 +02:00
2cf3f76e70 Fixed typo in ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 23:04:25 +02:00
aecab5e5d7 Added const macros for numeric types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 23:04:09 +02:00
e0cb295f65 Updated ev_types
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 13:56:27 +02:00
bd2b3acec6 Added EV_VA_OPT
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 00:02:16 +02:00
e199c69315 Added some macros for internal usage
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-03 00:01:59 +02:00
811f644dec Fixed EV_VA_ARGS_NARG for zero-size
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-02 22:12:30 +02:00
4080e7299b Started using ev_types in ev_numeric, added ev_internal
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-02 15:13:17 +02:00
2ce705baee Added ev_types for type metadata management
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-02 14:53:00 +02:00
30e40047c5 Merged ev_types and ev_limits to ev_numeric
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-02 14:51:59 +02:00
c5b6d7ba15 Fixed EV_FOREACH's UDATA variant
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2022-01-02 14:51:08 +02:00
632cdd8765 Added EV_FOREACH_UDATA
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-30 18:39:08 +02:00
f25acf244d Added EV_HEAD and EV_TAIL
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-30 18:34:28 +02:00
d60b2ebdb3 Added EV_DBGBREAK_IF to ev_macros
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-29 16:58:19 +02:00
dbbea40bc3 Added EV_BUILDTYPE_{DEBUG,DEBUGOPT,RELEASE} to defines.h
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-29 16:55:24 +02:00
b2a1f3bc1c Merge branch 'master' of https://github.com/evol3d/evol-headers 2021-12-29 16:48:15 +02:00
7f9c0691c0 Updated ev_macros.h use of defines
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-29 16:47:44 +02:00
e85e4ee46e Updated defines.h
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2021-12-29 16:47:15 +02:00
350c8ebcbe Merge pull request #5 from evol3D/types
Adding numeric types and limits
2021-12-28 15:22:37 +02:00
22 changed files with 2674 additions and 193 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.cache
build

View File

@@ -1 +1,11 @@
# evol-headers
# evol headers
Project Initialization
```
meson setup --native-file=meson-native-clang --wipe build
```
Build:
```
meson compile -C build
```

View File

@@ -0,0 +1,11 @@
[binaries]
c = 'clang-19'
c_ld = 'lld-19'
cpp = 'clang++-19'
cpp_ld = 'lld-19'
[properties]
c_args = ['-DEV_CC_CLANG=1','-fcolor-diagnostics', '-fansi-escape-codes', '-fms-extensions']
[cmake]
CMAKE_C_COMPILER = 'clang-19'

View File

@@ -0,0 +1,11 @@
[binaries]
c = 'clang.exe'
c_ld = 'lld'
cpp = 'clang++.exe'
cpp_ld = 'lld'
[properties]
c_args = ['-DEV_CC_CLANG=1','-fcolor-diagnostics', '-fansi-escape-codes']
[cmake]
CMAKE_C_COMPILER = 'clang.exe'

2
buildfiles/ev_helpers.c Normal file
View File

@@ -0,0 +1,2 @@
#define EV_HELPERS_IMPLEMENTATION
#include "../ev_helpers.h"

2
buildfiles/ev_log.c Normal file
View File

@@ -0,0 +1,2 @@
#define EV_LOG_IMPLEMENTATION
#include "../ev_log.h"

2
buildfiles/ev_str.c Normal file
View File

@@ -0,0 +1,2 @@
#define EV_STR_IMPLEMENTATION
#include "../ev_str.h"

2
buildfiles/ev_vec.c Normal file
View File

@@ -0,0 +1,2 @@
#define EV_VEC_IMPLEMENTATION
#include "../ev_vec.h"

120
defines.h
View File

@@ -1,30 +1,104 @@
#pragma once
#ifndef EV_HEADERS_DEFINES_H
#define EV_HEADERS_DEFINES_H
#ifndef EV_OS_WINDOWS
# define EV_OS_WINDOWS 0
#endif
#ifndef EV_OS_LINUX
# define EV_OS_LINUX 0
#endif
#ifndef EV_OS_IOS
# define EV_OS_IOS 0
#endif
#ifndef EV_OS_MACOS
# define EV_OS_MACOS 0
#endif
#ifndef EV_OS_ANDROID
# define EV_OS_ANDROID 0
#endif
#if (EV_OS_WINDOWS || EV_OS_LINUX || EV_OS_IOS || EV_OS_MACOS || EV_OS_ANDROID)
# define EV_OS_DEFINED 1
#else
# define EV_OS_DEFINED 0
#endif
#ifndef EV_CC_MSVC
# define EV_CC_MSVC 0
#endif
#ifndef EV_CC_GCC
# define EV_CC_GCC 0
#endif
#ifndef EV_CC_CLANG
# define EV_CC_CLANG 0
#endif
#if (EV_CC_MSVC || EV_CC_GCC || EV_CC_CLANG)
# define EV_CC_DEFINED 1
#else
# define EV_CC_DEFINED 0
#endif
// Operating System Detection
#if defined(_WIN32)
# define EV_OS_WINDOWS
#elif defined(__linux__)
# define EV_OS_LINUX
#elif defined(__APPLE__)
# include "TargetConditionals.h"
# if defined(TARGET_OS_IPHONE)
# define EV_OS_IOS
# elif defined(TARGET_OS_MAC)
# define EV_OS_MACOS
# elif defined(__ANDROID__)
# define EV_OS_ANDROID
#if !EV_OS_DEFINED
# if defined(_WIN32)
# undef EV_OS_WINDOWS
# define EV_OS_WINDOWS 1
# elif defined(__linux__)
# undef EV_OS_LINUX
# define EV_OS_LINUX 1
# elif defined(__APPLE__)
# include "TargetConditionals.h"
# if defined(TARGET_OS_IPHONE)
# undef EV_OS_IOS
# define EV_OS_IOS 1
# elif defined(TARGET_OS_MAC)
# undef EV_OS_MACOS
# define EV_OS_MACOS 1
# elif defined(__ANDROID__)
# undef EV_OS_ANDROID
# define EV_OS_ANDROID 1
# endif
# else
# error EV_OS_UNKNOWN
# endif
#else
# error EV_OS_UNKNOWN
#endif
// Compiler Detection
#if defined(_MSC_VER)
# define EV_CC_MSVC
#elif defined(__GNUC__)
# define EV_CC_GCC
#elif defined(__clang)
# define EV_CC_CLANG
#else
# error EV_CC_UNKNOWN
#if !EV_CC_DEFINED
# if defined(_MSC_VER)
# undef EV_CC_MSVC
# define EV_CC_MSVC 1
# elif defined(__GNUC__)
# undef EV_CC_GCC
# define EV_CC_GCC 1
# elif defined(__clang)
# undef EV_CC_CLANG
# define EV_CC_CLANG 1
# else
# error EV_CC_UNKNOWN
# 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
#ifndef EV_BUILDTYPE_DEBUGOPT
# define EV_BUILDTYPE_DEBUGOPT 0
#endif
#ifndef EV_BUILDTYPE_RELEASE
# define EV_BUILDTYPE_RELEASE 0
#endif
#if (EV_BUILDTYPE_DEBUG || EV_BUILDTYPE_DEBUGOPT || EV_BUILDTYPE_RELEASE)
# define EV_BUILDTYPE_DEFINED 1
#else
# define EV_BUILDTYPE_DEFINED 0
#endif
#if !EV_BUILDTYPE_DEFINED
# error "Buildtype not defined. Please define one of `EV_BUILDTYPE_{DEBUG,DEBUGOPT,RELEASE}`"
#endif
#endif // EV_HEADERS_DEFINES_H

163
ev_hash.h Normal file
View File

@@ -0,0 +1,163 @@
#ifndef EV_HEADERS_HASH_H
#define EV_HEADERS_HASH_H
#include "ev_internal.h"
/*!
* \brief MurmurHash3 64-bit version. Returns 64-bit hash instead of 128
*/
u64 ev_hash_murmur3(const void *data, u32 len, u64 seed);
#ifdef EV_HASH_IMPLEMENTATION
#undef EV_HASH_IMPLEMENTATION
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if EV_CC_MSVC
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // EV_CC_MSVC
static inline u64 rotl64 ( u64 x, i8 r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // EV_CC_MSVC
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
EV_FORCEINLINE u64 getblock64 ( const u64 * p, u32 i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
EV_FORCEINLINE u64 fmix64 ( u64 k )
{
k ^= k >> 33;
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void * key, const u32 len,
const u32 seed, void * out )
{
const u8 * data = (const u8*)key;
const u32 nblocks = len / 16;
u64 h1 = seed;
u64 h2 = seed;
const u64 c1 = BIG_CONSTANT(0x87c37b91114253d5);
const u64 c2 = BIG_CONSTANT(0x4cf5ad432745937f);
//----------
// body
const u64 * blocks = (const u64 *)(data);
for(u32 i = 0; i < nblocks; i++)
{
u64 k1 = getblock64(blocks,i*2+0);
u64 k2 = getblock64(blocks,i*2+1);
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
//----------
// tail
const u8 * tail = (const u8*)(data + nblocks*16);
u64 k1 = 0;
u64 k2 = 0;
switch(len & 15)
{
case 15: k2 ^= ((u64)tail[14]) << 48;
case 14: k2 ^= ((u64)tail[13]) << 40;
case 13: k2 ^= ((u64)tail[12]) << 32;
case 12: k2 ^= ((u64)tail[11]) << 24;
case 11: k2 ^= ((u64)tail[10]) << 16;
case 10: k2 ^= ((u64)tail[ 9]) << 8;
case 9: k2 ^= ((u64)tail[ 8]) << 0;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((u64)tail[ 7]) << 56;
case 7: k1 ^= ((u64)tail[ 6]) << 48;
case 6: k1 ^= ((u64)tail[ 5]) << 40;
case 5: k1 ^= ((u64)tail[ 4]) << 32;
case 4: k1 ^= ((u64)tail[ 3]) << 24;
case 3: k1 ^= ((u64)tail[ 2]) << 16;
case 2: k1 ^= ((u64)tail[ 1]) << 8;
case 1: k1 ^= ((u64)tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
((u64*)out)[0] = h1;
((u64*)out)[1] = h2;
}
//-----------------------------------------------------------------------------
u64 ev_hash_murmur3(const void *data, u32 len, u64 seed)
{
u64 out[2];
MurmurHash3_x64_128(data, len, (u32)seed, out);
return *out;
}
#endif // EV_HASH_IMPLEMENTATION
#endif // EV_HEADERS_HASH_H

52
ev_helpers.h Normal file
View File

@@ -0,0 +1,52 @@
/*!
* \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 = NULL;
#if EV_OS_WINDOWS
if(fopen_s(&f,filePath,"rb")) return EV_INVALID(evstring);
#else
f = fopen(filePath, "rb");
#endif
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

36
ev_internal.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef EV_HEADERS_INTERNAL_H
#define EV_HEADERS_INTERNAL_H
typedef signed char i8;
typedef short int i16;
typedef int i32;
typedef long long int i64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
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}
#define i32_const(v) (i32){v}
#define i64_const(v) (i64){v}
#define u8_const(v) (u8){v}
#define u16_const(v) (u16){v}
#define u32_const(v) (u32){v}
#define u64_const(v) (u64){v}
#define f32_const(v) (f32){v}
#define f64_const(v) (f64){v}
#endif // EV_HEADERS_INTERNAL_H

202
ev_log.h Normal file
View File

@@ -0,0 +1,202 @@
#ifndef EV_HEADERS_LOG_H
#define EV_HEADERS_LOG_H
#define EV_LOG_USE_COLOR
#include "ev_internal.h"
#include "stdarg.h"
#include "stdbool.h"
#include "stdio.h"
#include "time.h"
typedef struct {
va_list ap;
const char* fmt;
const char* file;
struct tm* time;
void* udata;
int line;
int level;
} ev_log_event_t;
typedef void (*ev_log_log_fn)(ev_log_event_t* ev);
typedef void (*ev_log_lock_fn)(bool lock, void* udata);
typedef enum {
EV_LOG_TRACE,
EV_LOG_DEBUG,
EV_LOG_INFO ,
EV_LOG_WARN ,
EV_LOG_ERROR,
EV_LOG_FATAL,
} ev_log_level;
#define ev_log_trace(...) ev_log(EV_LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define ev_log_debug(...) ev_log(EV_LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define ev_log_info(...) ev_log(EV_LOG_INFO , __FILE__, __LINE__, __VA_ARGS__)
#define ev_log_warn(...) ev_log(EV_LOG_WARN , __FILE__, __LINE__, __VA_ARGS__)
#define ev_log_error(...) ev_log(EV_LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define ev_log_fatal(...) ev_log(EV_LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
const char* ev_log_level_string(ev_log_level level);
void ev_log_set_lock(ev_log_lock_fn fn, void* udata);
void ev_log_set_level(ev_log_level level);
void ev_log_set_quiet(bool enable);
i32 ev_log_add_callback(ev_log_log_fn fn, void* udata, ev_log_level level);
i32 ev_log_add_fp(FILE *fp, ev_log_level level);
void ev_log(ev_log_level level, const char* file, u32 line, const char* fmt, ...);
#ifdef EV_LOG_IMPLEMENTATION
#undef EV_LOG_IMPLEMENTATION
#define MAX_CALLBACKS 32
typedef struct {
ev_log_log_fn fn;
void* udata;
ev_log_level level;
} ev_log_callback_t;
struct {
void* udata;
ev_log_lock_fn lock;
ev_log_level level;
bool quiet;
ev_log_callback_t callbacks[MAX_CALLBACKS];
} G;
static const char* level_strings[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};
static const char* level_colors[] = {
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
};
static void ev_log_stdout_callback(ev_log_event_t* ev)
{
char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
#ifdef EV_LOG_USE_COLOR
fprintf(
ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
buf, level_colors[ev->level], level_strings[ev->level],
ev->file, ev->line);
#else
fprintf(
ev->udata, "%s %-5s %s:%d: ",
buf, level_strings[ev->level], ev->file, ev->line);
#endif
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
static void ev_log_file_callback(ev_log_event_t* ev)
{
char buf[64];
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
fprintf(
ev->udata, "%s %-5s %s:%d: ",
buf, level_strings[ev->level], ev->file, ev->line);
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
static void lock(void)
{
if(G.lock)
G.lock(true, G.udata);
}
static void unlock(void)
{
if(G.lock)
G.lock(false, G.udata);
}
const char* ev_log_level_string(ev_log_level level)
{
return level_strings[level];
}
void ev_log_set_lock(ev_log_lock_fn fn, void* udata)
{
G.lock = fn;
G.udata = udata;
}
void ev_log_set_level(ev_log_level level)
{
G.level = level;
}
void ev_log_set_quiet(bool enable)
{
G.quiet = enable;
}
i32 ev_log_add_callback(ev_log_log_fn fn, void* udata, ev_log_level level)
{
for (i32 i = 0; i < MAX_CALLBACKS; i++) {
if (!G.callbacks[i].fn) {
G.callbacks[i] = (ev_log_callback_t) { fn, udata, level };
return 0;
}
}
return -1;
}
i32 log_add_fp(FILE *fp, ev_log_level level)
{
return ev_log_add_callback(ev_log_file_callback, fp, level);
}
static void init_event(ev_log_event_t* ev, void* udata)
{
if (!ev->time) {
time_t t = time(NULL);
ev->time = localtime(&t);
}
ev->udata = udata;
}
void ev_log(ev_log_level level, const char* file, u32 line, const char* fmt, ...)
{
ev_log_event_t ev = {
.fmt = fmt,
.file = file,
.line = line,
.level = level,
};
lock();
if (!G.quiet && level >= G.level) {
init_event(&ev, stderr);
va_start(ev.ap, fmt);
ev_log_stdout_callback(&ev);
va_end(ev.ap);
}
for (i32 i = 0; i < MAX_CALLBACKS && G.callbacks[i].fn; i++) {
ev_log_callback_t* cb = &G.callbacks[i];
if (level >= cb->level) {
init_event(&ev, cb->udata);
va_start(ev.ap, fmt);
cb->fn(&ev);
va_end(ev.ap);
}
}
unlock();
}
#endif
#endif

View File

@@ -1,7 +1,30 @@
#pragma once
#ifndef EV_HEADERS_MACROS_H
#define EV_HEADERS_MACROS_H
#include "defines.h"
// Internal Usage
#define __EV_MACRO_IF_ELSE(cond) EV_CAT(__EV_MACRO_IF_,cond)
#define __EV_MACRO_IF_1(...) __VA_ARGS__ __EV_MACRO_IF_1_ELSE
#define __EV_MACRO_IF_0(...) __EV_MACRO_IF_0_ELSE
#define __EV_MACRO_IF_1_ELSE(...)
#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
#define __EV_MACRO_NOT(x) __EV_MACRO_IS_PROBE(EV_CAT(__EV_MACRO_NOT_,x))
#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
/*!
* \brief Macro to get a type's alignment
*/
@@ -18,21 +41,44 @@
*/
#define EV_UNALIGNED
#if defined(EV_CC_MSVC)
#define EV_PRAGMA(...) _Pragma(EV_STRINGIZE(__VA_ARGS__))
#if ( EV_CC_MSVC )
# define EV_WARNING_DISABLE_MSVC(w) EV_PRAGMA(warning(disable:w))
# define EV_WARNING_DISABLE_CLANG(...)
# define EV_WARNING_DISABLE_GCC(...)
# define EV_WARNING_PUSH() EV_PRAGMA(warning(push))
# define EV_WARNING_POP() EV_PRAGMA(warning(pop))
# define EV_EXPORT __declspec(dllexport)
# define EV_IMPORT __declspec(dllimport)
# define EV_UNUSED
#elif defined(EV_CC_GCC) || defined(EV_CC_CLANG)
# 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)
# define EV_WARNING_DISABLE_CLANG(...)
# elif ( EV_CC_CLANG )
# define EV_PRAGMA_CC_NAME clang
# define EV_WARNING_DISABLE_CLANG(w) EV_PRAGMA(EV_PRAGMA_CC_NAME diagnostic ignored "-W"w)
# define EV_WARNING_DISABLE_GCC(...)
# endif
# define EV_WARNING_PUSH() EV_PRAGMA(EV_PRAGMA_CC_NAME diagnostic push)
# define EV_WARNING_POP() EV_PRAGMA(EV_PRAGMA_CC_NAME diagnostic pop)
# define EV_WARNING_DISABLE_MSVC(...)
#else
# error "Unknown Compiler"
#endif
#if defined(EV_CC_MSVC)
#if ( EV_CC_MSVC )
# define _EV_BREAK_IF(cond) cond ? __debugbreak():0
#elif defined(EV_CC_GCC) || defined(EV_CC_CLANG)
#elif ( EV_CC_GCC || EV_CC_CLANG )
# include <signal.h>
# define _EV_BREAK_IF(cond) cond ? raise(SIGTRAP):0
#else
@@ -43,10 +89,22 @@
# define _EV_BREAK_IF(cond)
#endif
#if ( EV_BUILDTYPE_DEBUG || EV_BUILDTYPE_DEBUGOPT )
# define EV_DBGBREAK_IF(...) _EV_BREAK_IF(__VA_ARGS__)
# define EV_DEBUG(...) __VA_ARGS__
#include <assert.h>
# define EV_UNIMPLEMENTED() assert(!"Hit an unimplemented path")
#else
# define EV_DBGBREAK_IF(...)
# define EV_DEBUG(...)
# define EV_UNIMPLEMENTED()
#endif
/*!
* \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.
@@ -54,12 +112,27 @@
#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. (")
*/
#define EV_STRINGIZE(...) EV_STRINGIZE_IMPL(__VA_ARGS__)
#define EV_STRINGIZE_IMPL(...) #__VA_ARGS__
/*!
* \brief Returns head of list (a,b,c) -> a
*/
#define EV_HEAD(h,...) h
/*!
* \brief Returns tail of list (a,b,c) -> b,c
*/
#define EV_TAIL(h,...) __VA_ARGS__
// Used for the removal of parenthesis around tokens
#define EV_EXPAND(...) __VA_ARGS__
@@ -70,77 +143,91 @@
/*!
* \brief Macro that returns the number of arguments passed to it.
*/
#define EV_VA_ARGS_NARG(...) EV_VA_ARGS_NARG_IMPL(__VA_ARGS__, EV_VA_ARGS_RSEQ_N())
#define EV_VA_ARGS_NARG(...) EV_VA_ARGS_NARG_IMPL(_, ## __VA_ARGS__, EV_VA_ARGS_RSEQ_N())
#define EV_VA_ARGS_NARG_IMPL(...) EV_VA_ARGS_ARG_N(__VA_ARGS__)
#define EV_VA_ARGS_ARG_N(_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_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:
* ```c
* #define TEST(...) EV_VA_OPT(__VA_ARGS__)("Not ")"Empty"
* ```
*/
#define EV_VA_OPT(...) __EV_MACRO_IF_ELSE(__EV_MACRO_NOT(EV_VA_ARGS_NARG(__VA_ARGS__)))()
#define EV_VA_OPT_ELSE(...) __EV_MACRO_IF_ELSE(__EV_MACRO_BOOL(EV_VA_ARGS_NARG(__VA_ARGS__)))
/*!
* \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
*/
#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

View File

@@ -1,83 +1,111 @@
#ifndef EV_HEADERS_LIMITS_H
#define EV_HEADERS_LIMITS_H
#include "ev_types.h"
struct Int8Data { i8 MIN; i8 MAX; };
struct Int16Data { i16 MIN; i16 MAX; };
struct Int32Data { i32 MIN; i32 MAX; };
struct Int64Data { i64 MIN; i64 MAX; };
struct UInt8Data { u8 MIN; u8 MAX; };
struct UInt16Data { u16 MIN; u16 MAX; };
struct UInt32Data { u32 MIN; u32 MAX; };
struct UInt64Data { u64 MIN; u64 MAX; };
struct Float32Data { f32 MIN; f32 MAX; f32 MIN_POS; f32 EPS; };
struct Float64Data { f64 MIN; f64 MAX; f64 MIN_POS; f64 EPS; };
static const struct Int8Data Int8 =
{
.MIN = -128,
.MAX = 127
};
static const struct Int16Data Int16 =
{
.MIN = -32767-1,
.MAX = 32767
};
static const struct Int32Data Int32 =
{
.MIN = -2147483647-1,
.MAX = 2147483647
};
static const struct Int64Data Int64 =
{
.MIN = -(9223372036854775807LL)-1,
.MAX = 9223372036854775807LL
};
static const struct UInt8Data UInt8 =
{
.MIN = 0,
.MAX = 255
};
static const struct UInt16Data UInt16 =
{
.MIN = 0,
.MAX = 65535
};
static const struct UInt32Data UInt32 =
{
.MIN = 0,
.MAX = 4294967295U
};
static const struct UInt64Data UInt64 =
{
.MIN = 0,
.MAX = 18446744073709551615ULL
};
static const struct Float32Data Float32 =
{
.MIN_POS = 1.175494351e-38,
.MIN = -3.402823466e+38,
.MAX = 3.402823466e+38,
.EPS = 1.192093e-07
};
static const struct Float64Data Float64 =
{
.MIN_POS = 2.2250738585072014e-308,
.MIN = -1.7976931348623158e+308,
.MAX = 1.7976931348623158e+308,
.EPS = 2.2204460492503131e-016
};
#endif // EV_HEADERS_LIMITS_H
#ifndef EV_HEADERS_NUMERIC_H
#define EV_HEADERS_NUMERIC_H
#include "ev_internal.h"
#include "ev_types.h"
// Signed integers
TYPEDATA_GEN(i8);
TYPEDATA_GEN(i16);
TYPEDATA_GEN(i32);
TYPEDATA_GEN(i64);
// Unsigned integers
TYPEDATA_GEN(u8 );
TYPEDATA_GEN(u16);
TYPEDATA_GEN(u32);
TYPEDATA_GEN(u64);
// Floating-Point Numbers
TYPEDATA_GEN(f32);
TYPEDATA_GEN(f64);
struct Int8Data { i8 MIN; i8 MAX; };
struct Int16Data { i16 MIN; i16 MAX; };
struct Int32Data { i32 MIN; i32 MAX; };
struct Int64Data { i64 MIN; i64 MAX; };
struct UInt8Data { u8 MIN; u8 MAX; };
struct UInt16Data { u16 MIN; u16 MAX; };
struct UInt32Data { u32 MIN; u32 MAX; };
struct UInt64Data { u64 MIN; u64 MAX; };
struct Float32Data { f32 MIN; f32 MAX; f32 MIN_POS; f32 EPS; };
struct Float64Data { f64 MIN; f64 MAX; f64 MIN_POS; f64 EPS; };
static const struct Int8Data Int8 =
{
.MIN = -128,
.MAX = 127
};
static const struct Int16Data Int16 =
{
.MIN = -32767-1,
.MAX = 32767
};
static const struct Int32Data Int32 =
{
.MIN = -2147483647-1,
.MAX = 2147483647
};
static const struct Int64Data Int64 =
{
.MIN = -(9223372036854775807LL)-1,
.MAX = 9223372036854775807LL
};
static const struct UInt8Data UInt8 =
{
.MIN = 0,
.MAX = 255
};
static const struct UInt16Data UInt16 =
{
.MIN = 0,
.MAX = 65535
};
static const struct UInt32Data UInt32 =
{
.MIN = 0,
.MAX = 4294967295U
};
static const struct UInt64Data UInt64 =
{
.MIN = 0,
.MAX = 18446744073709551615ULL
};
static const struct Float32Data Float32 =
{
.MIN_POS = 1.175494351e-38f,
.MIN = -3.402823466e+38f,
.MAX = 3.402823466e+38f,
.EPS = 1.192093e-07f
};
static const struct Float64Data Float64 =
{
.MIN_POS = 2.2250738585072014e-308,
.MIN = -1.7976931348623158e+308,
.MAX = 1.7976931348623158e+308,
.EPS = 2.2204460492503131e-016
};
#if !EV_OS_WINDOWS
#define max(a,b) \
({ __typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a > _b ? _a : _b; })
#define min(a,b) \
({ __typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#endif // EV_HEADERS_NUMERIC_H

699
ev_str.h Normal file
View File

@@ -0,0 +1,699 @@
/*!
* \file ev_str.h
*/
#ifndef EV_STR_HEADER
#define EV_STR_HEADER
#include "ev_types.h"
#include "ev_numeric.h"
#include <stddef.h>
#include <stdarg.h>
#define EV_STR_evstring_MAGIC (0x65767374)
#ifdef EV_STR_SHARED
#if defined (EV_STR_IMPL)
#define EV_STR_API EV_EXPORT
#else
#define EV_STR_API EV_IMPORT
#endif
#else
#define EV_STR_API
#endif
#if !defined(ev_str_malloc) && !defined(ev_str_free) && !defined(ev_str_realloc)
#include <stdlib.h>
#ifndef ev_str_malloc
#define ev_str_malloc malloc
#endif
#ifndef ev_str_free
#define ev_str_free free
#endif
#ifndef ev_str_realloc
#define ev_str_realloc realloc
#endif
#endif
#ifndef EV_STR_GROWTH_FACTOR
/*!
* \brief Rate at which an evstring grows whenever a resize is needed
*/
#define EV_STR_GROWTH_FACTOR 3 / 2
#endif
typedef char *evstring;
typedef enum {
EV_STR_ERR_NONE = 0,
EV_STR_ERR_OOM = -1,
} evstring_error_t;
TYPEDATA_GEN(evstring_error_t, DEFAULT(EV_STR_ERR_NONE));
struct evstr_meta_t {
EV_DEBUG(u64 magic;)
u64 length;
u64 size;
enum {
EV_STR_ALLOCATION_TYPE_STACK,
EV_STR_ALLOCATION_TYPE_HEAP
} allocationType;
};
#define __ev_strlen_const sizeof
#define evstr(str) __evstr_impl(str, __ev_strlen_const(str))
#define __evstr_impl(str, len) \
(( struct { struct evstr_meta_t meta; char data[len]; } ) { \
EV_DEBUG(.meta.magic = EV_STR_evstring_MAGIC,) \
.meta.length = len-1, \
.meta.size = len, \
.meta.allocationType = EV_STR_ALLOCATION_TYPE_STACK, \
.data = str \
}).data
typedef struct evstring_view {
evstring data;
u64 offset;
u64 len;
} evstring_view;
#define evstring_newGeneric(str) _Generic((str), \
evstring_view: evstring_newFromView, \
default: evstring_newFromStr\
)(str)
#define evstring_new(str, ...) EV_VA_OPT_ELSE(__VA_ARGS__)(evstring_newFmt(str, __VA_ARGS__))(evstring_newGeneric(str))
#define evstring_pushGeneric(str, push) _Generic((push), \
char: evstring_pushChar, \
evstring_view: evstring_pushView, \
default: evstring_pushStr \
)(str, push)
#define evstring_push(str, push, ...) \
EV_VA_OPT_ELSE(__VA_ARGS__)(evstring_pushFmt(str, push, __VA_ARGS__))(evstring_pushGeneric(str, push))
EV_STR_API evstring
evstring_newFromStr(
const char *str);
EV_STR_API evstring
evstring_newFromView(
evstring_view v);
EV_STR_API void
evstring_free(
evstring s);
EV_STR_API u64
evstring_getLength(
const evstring s);
EV_STR_API evstring_error_t
evstring_setLength(
evstring *s,
size_t newLength);
EV_STR_API i32
evstring_cmp(
const evstring s1,
const evstring s2);
EV_STR_API evstring_error_t
evstring_pushChar(
evstring *s,
char c);
EV_STR_API evstring_error_t
evstring_pushStr(
evstring *s,
const char *data);
EV_STR_API evstring_error_t
evstring_pushFmt(
evstring *s,
const char *fmt,
...);
EV_STR_API evstring
evstring_newFromView(
evstring_view view);
EV_STR_API evstring_view
evstring_slice(
const evstring s,
i64 begin,
i64 end);
EV_STR_API i32
evstring_pushView(
evstring *s,
evstring_view ref);
EV_STR_API void
evstring_clear(
evstring *s);
EV_STR_API evstring
evstring_newFmt(
const char *fmt,
...);
EV_STR_API u64
evstring_findAll(
const evstring text,
const evstring query,
evstring_view *results);
EV_STR_API evstring_view
evstring_findFirst(
const evstring text,
const evstring query);
evstring_view
__evstring_findFirst_impl(
evstring_view text,
evstring_view query);
EV_STR_API evstring
evstring_replaceFirst(
const evstring text,
const evstring query,
const evstring replacement);
EV_STR_API i64
evstring_findFirstChar(
const evstring text,
const char c);
EV_STR_API i64
evstring_findLastChar(
const evstring text,
const char c);
DEFINE_EQUAL_FUNCTION(evstring, Default)
{
return evstring_cmp(*(evstring*)self, *(evstring*)other) == 0;
}
DEFINE_COPY_FUNCTION(evstring, Default)
{
*(evstring*)dst = evstring_newFromStr(*src);
}
DEFINE_FREE_FUNCTION(evstring, Default)
{
evstring_free(*self);
}
TYPEDATA_GEN(evstring,
EQUAL(Default),
COPY(Default),
FREE(Default)
);
#if defined(EV_STR_IMPLEMENTATION)
#if EV_OS_WINDOWS
#pragma comment(lib, "legacy_stdio_definitions.lib")
#endif
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define META(s) (((struct evstr_meta_t *)(s)) - 1)
#if EV_BUILDTYPE_DEBUG || EV_BUILDTYPE_DEBUGOPT
#define evstr_asserttype(str) \
assert(META(str)->magic == EV_STR_evstring_MAGIC)
#else
#define evstr_asserttype(str)
#endif
evstring_error_t
evstring_addSpace(
evstring *s,
u64 space);
evstring_error_t
evstring_pushFmt_v(
evstring *s,
const char *fmt,
va_list args);
evstring
evstring_new_impl(
const char *data,
u64 len)
{
u64 size = sizeof(struct evstr_meta_t) + len + 1;
void *p = ev_str_malloc(size);
assert(p); // Raised if malloc fails
struct evstr_meta_t *meta = (struct evstr_meta_t *)p;
EV_DEBUG
(
meta->magic = EV_STR_evstring_MAGIC;
)
meta->length = len;
meta->size = size;
meta->allocationType = EV_STR_ALLOCATION_TYPE_HEAP;
evstring s = (evstring)(meta + 1);
if(len > 0) {
memcpy(s, data, len);
}
s[len] = '\0';
return s;
}
#include <stdio.h>
evstring
evstring_newFmt_v(
const char *fmt,
va_list args)
{
va_list test;
va_copy(test, args);
i32 len = vsnprintf(NULL, 0, fmt, test);
if(len < 0) {
return EV_INVALID(evstring);
}
evstring res = evstring_new_impl(NULL, 0);
evstring_setLength(&res, len);
vsnprintf(res, len + 1, fmt, args);
va_end(test);
return res;
}
evstring
evstring_newFmt(
const char *fmt,
...)
{
va_list ap;
va_start(ap, fmt);
evstring res = evstring_newFmt_v(fmt, ap);
va_end(ap);
return res;
}
evstring
evstring_newFromStr(
const char *str)
{
u64 len = strlen(str);
return evstring_new_impl(str, len);
}
evstring
evstring_newFromView(
evstring_view v)
{
return evstring_new_impl(v.data + v.offset, v.len);
}
void
evstring_free(
evstring s)
{
evstr_asserttype(s);
if(META(s)->allocationType == EV_STR_ALLOCATION_TYPE_HEAP) {
free(META(s));
}
}
u64
evstring_getLength(
const evstring s)
{
evstr_asserttype(s);
return META(s)->length;
}
evstring_error_t
evstring_setSize(
evstring *s,
size_t newsize)
{
evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s);
if(meta->allocationType == EV_STR_ALLOCATION_TYPE_STACK) {
return EV_STR_ERR_OOM;
}
if(meta->size == newsize) {
return EV_STR_ERR_NONE;
}
void *buf = (void*)meta;
void *tmp = ev_str_realloc(buf, sizeof(struct evstr_meta_t) + newsize);
if (!tmp) {
return EV_STR_ERR_OOM;
}
if(buf != tmp) { // Reallocation caused memory to be moved
buf = tmp;
meta = (struct evstr_meta_t *)buf;
*s = (evstring)(meta+1);
}
meta->size = newsize;
return EV_STR_ERR_NONE;
}
evstring_error_t
evstring_grow(
evstring *s)
{
evstr_asserttype(*s);
return evstring_setSize(s, META(*s)->size * EV_STR_GROWTH_FACTOR);
}
evstring_error_t
evstring_setLength(
evstring *s,
size_t newlen)
{
evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s);
if(newlen == meta->length) {
return EV_STR_ERR_NONE;
}
u64 required_size = sizeof(struct evstr_meta_t) + newlen + 1;
while(required_size > meta->size) {
evstring_error_t grow_err = evstring_grow(s);
if(grow_err) {
return grow_err;
}
meta = META(*s);
}
meta->length = newlen;
return EV_STR_ERR_NONE;
}
void
evstring_clear(
evstring *s)
{
evstr_asserttype(*s);
evstring_setLength(s, 0);
}
i32
evstring_cmp(
const evstring s1,
const evstring s2)
{
evstr_asserttype(s1);
evstr_asserttype(s2);
u64 len1 = evstring_getLength(s1);
u64 len2 = evstring_getLength(s2);
if(len1 != len2) {
return 1;
}
return memcmp(s1, s2, len1);
}
evstring_error_t
evstring_push_impl(
evstring *s,
u64 sz,
const char *data)
{
evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s);
// TODO Find a more efficient approach?
u64 required_size = sizeof(struct evstr_meta_t) + meta->length + sz + 1;
while(required_size > meta->size) { // `<=` because of the null terminator
evstring_error_t grow_err = evstring_grow(s);
if(grow_err != EV_STR_ERR_NONE) {
return grow_err;
}
meta = META(*s);
}
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);
meta->length += sz;
(*s)[meta->length] = '\0';
return EV_STR_ERR_NONE;
}
evstring_error_t
evstring_pushChar(
evstring *s,
char c)
{
evstr_asserttype(*s);
return evstring_push_impl(s, 1, &c);
}
evstring_error_t
evstring_pushStr(
evstring *s,
const char *data)
{
evstr_asserttype(*s);
// TODO: Check that data is not within the range of *s
return evstring_push_impl(s,strlen(data),data);
}
evstring_error_t
evstring_pushView(
evstring *s,
evstring_view v)
{
evstr_asserttype(*s);
assert(*s != v.data && " *s might be realloc'ed in a push operation. This would lead to the view pointing to a free'd block of memory.");
return evstring_push_impl(s,v.len,v.data + v.offset);
}
evstring_view
evstring_slice(
const evstring s,
i64 begin,
i64 end)
{
evstr_asserttype(s);
u64 string_len = evstring_getLength(s);
u64 wrapped_begin = begin < 0 ? string_len + 1 + begin : begin;
u64 wrapped_end = end < 0 ? string_len + 1 + end : end;
assert(wrapped_begin >= 0 && wrapped_begin < string_len);
assert(wrapped_end > 0 && wrapped_end <= string_len);
assert(wrapped_begin < wrapped_end);
return (evstring_view) {
.data = s,
.offset = wrapped_begin,
.len = wrapped_end - wrapped_begin
};
}
u64
evstring_getSpace(
const evstring s)
{
evstr_asserttype(s);
struct evstr_meta_t *meta = META(s);
return meta->size - meta->length - 1 - sizeof(struct evstr_meta_t);
}
evstring_error_t
evstring_addSpace(
evstring *s,
u64 space)
{
evstr_asserttype(*s);
return evstring_setSize(s, META(*s)->size + space);
}
evstring_view
__evstring_findFirst_impl(
evstring_view text,
evstring_view query)
{
u64 found_progress = 0;
evstring_view result = {
.data = text.data,
.len = 0,
.offset = ~0ull
};
for(u64 i = text.offset; i < text.offset + text.len; i++) {
if(text.data[i] == query.data[query.offset + found_progress]) {
found_progress++;
}
if(found_progress == query.len) {
result.offset = (i+1) - query.len;
result.len = query.len;
break;
}
}
return result;
}
evstring_view
evstring_findFirst(
const evstring text,
const evstring query)
{
evstr_asserttype(text);
evstr_asserttype(query);
return __evstring_findFirst_impl(evstring_slice(text, 0, -1), evstring_slice(query, 0, -1));
}
evstring
evstring_replaceFirst(
const evstring text,
const evstring query,
const evstring replacement)
{
evstr_asserttype(text);
evstr_asserttype(query);
evstr_asserttype(replacement);
evstring result = NULL;
evstring_view query_slice = evstring_findFirst(text, query);
// If the query doesn't actually exist, then we're returning a clone of
// the original string.
if(query_slice.len == 0) {
result = evstring_new_impl(text, evstring_getLength(text));
} else {
result = evstring_new_impl(NULL,0);
// If the query doesn't match at the beginning of the string,
// then we need to copy the data before it first.
if(query_slice.offset != 0) {
evstring_push(&result, evstring_slice(text, 0, query_slice.offset));
}
// Then, we simply push the replacement
evstring_push_impl(&result, evstring_getLength(replacement), replacement);
// Followed by the rest of the string
evstring_push(&result,
evstring_slice(text, query_slice.offset + query_slice.len, -1));
}
return result;
}
evstring_error_t
evstring_pushFmt(
evstring *s,
const char *fmt,
...)
{
evstr_asserttype(*s);
va_list ap;
va_start(ap, fmt);
evstring_error_t res = evstring_pushFmt_v(s, fmt, ap);
va_end(ap);
return res;
}
evstring_error_t
evstring_pushFmt_v(
evstring *s,
const char *fmt,
va_list args)
{
evstr_asserttype(*s);
va_list test;
va_copy(test, args);
int fmt_len = vsnprintf(NULL, 0, fmt, test);
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+1, fmt, args);
assert(write_res > 0);
assert(write_res == fmt_len);
}
va_end(test);
return res;
}
i64
evstring_findFirstChar(
const evstring text,
const char c)
{
evstr_asserttype(text);
struct evstr_meta_t *meta = META(text);
for(int i = 0; i < meta->length; i++) {
if(text[i] == c) {
return i;
}
}
return -1;
}
i64
evstring_findLastChar(
const evstring text,
const char c)
{
evstr_asserttype(text);
struct evstr_meta_t *meta = META(text);
int i;
for(i = meta->length - 1; i >= 0; i--) {
if(text[i] == c) {
break;
}
}
return i;
}
u64
evstring_findAll(
const evstring text,
const evstring query,
evstring_view *results)
{
evstr_asserttype(text);
evstr_asserttype(query);
u64 text_len = evstring_getLength(text);
u64 query_len = evstring_getLength(query);
if(text_len == 0 || query_len == 0 || query_len > text_len) {
return 0;
}
bool check_run = (results == NULL);
u64 count = 0;
for(evstring_view v = evstring_findFirst(text, query);
v.len != 0;
v = __evstring_findFirst_impl(
evstring_slice(text, v.offset + v.len, -1),
evstring_slice(query, 0, -1))) {
if(!check_run) {
results[count++] = v;
}
}
return count;
}
#endif
#endif

View File

@@ -1,20 +1,157 @@
#ifndef EV_HEADERS_TYPES_H
#define EV_HEADERS_TYPES_H
// Signed integers
typedef signed char i8;
typedef short int i16;
typedef int i32;
typedef long long int i64;
#include "ev_macros.h"
#include "ev_internal.h"
#include "ev_hash.h"
// Unsigned integers
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
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 bool(*ev_equal_fn)(void *self, void *other);
// Floating-Point Numbers
typedef float f32;
typedef double f64;
typedef void(*ev_tostr_fn)(void *self, char *out);
typedef u32(*ev_tostrlen_fn)();
typedef struct {
EV_DEBUG(const char *name;)
u32 size;
u32 alignment;
ev_copy_fn copy_fn;
ev_free_fn free_fn;
ev_hash_fn hash_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 EQUAL_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_EQUAL_FUNCTION_ ,T),_),name)
#define TOSTR_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_TOSTR_FUNCTION_ ,T),_),name)
#define TOSTRLEN_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_TOSTRLEN_FUNCTION_,T),_),name)
#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) 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) 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_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_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, ...) \
EV_WARNING_PUSH(); \
EV_WARNING_DISABLE_GCC("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}, \
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_CAT(EV_CAT(__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 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_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__ },
[[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__) \
((EV_OVERRIDE_VAR(T)=__EV_DEFAULT_INTERNAL(T), \
EV_FOREACH_UDATA(__EV_OVERRIDE_DEFAULT, T, __VA_ARGS__) \
EV_OVERRIDE_VAR(T))) \
(__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

776
ev_vec.h Normal file
View File

@@ -0,0 +1,776 @@
/*!
* \file ev_vec.h
*/
#ifndef EV_VEC_HEADER
#define EV_VEC_HEADER
#include "ev_types.h"
#include "ev_numeric.h"
#if !EV_OS_WINDOWS
#include <string.h>
#endif
#if defined(EV_VEC_SHARED)
# if defined (EV_VEC_IMPL)
# define EV_VEC_API EV_EXPORT
# else
# define EV_VEC_API EV_IMPORT
# endif
#else
# define EV_VEC_API
#endif
#ifndef EV_VEC_INIT_CAP
/*!
* \brief Initial capacity that is first reserved when a vector is initialized
*/
#define EV_VEC_INIT_CAP 32
#endif
#ifndef EV_VEC_GROWTH_RATE
/*!
* \brief Rate at which a vector grows whenever a resize is needed
*/
#define EV_VEC_GROWTH_RATE 3 / 2
#endif
#if EV_CC_MSVC
# define __EV_VEC_EMPTY_ARRAY { 0 }
#else
# define __EV_VEC_EMPTY_ARRAY { }
#endif
typedef void *ev_vec_t;
typedef void *ev_svec_t;
typedef enum {
EV_VEC_ERR_NONE = 0,
EV_VEC_ERR_OOM = 1
} ev_vec_error_t;
TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE));
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);
#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)
# 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_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_vec(int) v = ev_vec_init(int);
* ```
*/
#define ev_vec(T) T*
/*!
* \brief For the sake of readability
* \details Sample usage:
* ```
* ev_svec(int) v = ev_svec_init(int, { 0, 0 });
* ```
*/
#define ev_svec(T) T*
#define EV_VEC_MAGIC (0x65765F7665635F74)
//! Metadata that is stored with a vector. Unique to each vector.
struct ev_vec_meta_t {
u64 _magic;
//! The number of elements in the vector.
u64 length;
//! The maximum length of the vector before it needs to be resized.
u64 capacity;
//! The type data of the elements
EvTypeData typeData;
enum {
EV_VEC_ALLOCATION_TYPE_STACK,
EV_VEC_ALLOCATION_TYPE_HEAP
} allocationType;
};
/*!
* \param typeData The EvTypeData for the element that the vector will contain
*
* \returns A vector object
*/
EV_VEC_API ev_vec_t
ev_vec_init_impl(
EvTypeData typeData,
ev_vec_overrides_t overrides);
/*!
* \brief Syntactic sugar for `ev_vec_init_impl()`
* \details Sample usage:
* ```
* ev_vec_init(i32); // ev_vec_init_impl(TypeData(i32));
* ```
*/
#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__), 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)
static struct ev_vec_meta_t *__svec_interm_md;
#define __ev_svec_init_impl(T, len, cap, ...) ( \
EV_WARNING_PUSH() \
EV_WARNING_DISABLE_CLANG("unsequenced") \
__svec_interm_md = (void*)(u8[sizeof(T)*cap + sizeof(struct ev_vec_meta_t)]){}, \
*__svec_interm_md = (struct ev_vec_meta_t){ \
._magic = EV_VEC_MAGIC, \
.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__)),) \
(void*)&(__svec_interm_md[1]) \
EV_WARNING_POP() \
)
/*!
* \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 vec_p 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(
const void* vec_p);
/*!
* \param vec_p 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(
const void* vec_p);
/*!
* \brief A function that increments an iterator to make it point to the next
* element in the vector
*
* \param vec_p 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(
const void* vec_p,
void **iter);
/*!
* \brief A function that looks for the index of `val` in `v`
*
* \param vec_p 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 void* vec_p,
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 vec_p A pointer to the vector that is being destroyed
*/
EV_VEC_API void
ev_vec_fini(
void* vec_p);
/*!
* \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.
*
* \param vec_p Reference to the vector object
* \param val A pointer to the element that is to be copied to the end of the
* vector
*
* \returns The index of the element that was just pushed. If the operation
* failed, a non-zero (vec_error_t) value is returned.
*/
EV_VEC_API int
ev_vec_push_impl(
void* vec_p,
void *val);
/*!
* \brief A function that appends the elements of an array to the end of a
* vector. If a resize is needed but fails due to 'OOM' issues, then the
* vector is left unchanged and a VEC_ERR_OOM is returned.
*
* For `svec`, as long as the capacity is more than the current size by the
* desired amount, an append operation is permitted. Otherwise, the operation
* is treated as an OOM.
*
* *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.
*
* \param vec_p Reference to the vector object
* \param arr A pointer to the array that is to be copied to the end of the
* vector
* \param size Number of elements in the array
*
* \returns The index of the first element that was appended to the vector. If
* the operation failed, a non-zero (vec_error_t) value is returned.
*/
EV_VEC_API u32
ev_vec_append(
void* vec_p,
void **arr,
u64 size);
/*!
* \brief A function that duplicates the passed vector into a new one and returns it.
*
* \param vec_p Reference to the vector object
*
* \returns The newly created vector.
*/
EV_VEC_API ev_vec_t
ev_vec_dup(
const void* vec_p);
/*!
* \brief A function that copies the value at the end of a vector and removes
* it from the vector. If a copy function was passed while initializing the
* vector, then this function is used. Otherwise, memcpy is used with a length
* of `vec_meta.elemsize`
*
* \param vec_p Reference to the vector object
* \param out A pointer to the memory block at which the popped element will be
* copied. If NULL is passed, then the element is destructed. Otherwise, the
* element is copied to `out` and the receiving code is responsible for its
* destruction.
*
* \returns An error code. If the operation was successful, then `VEC_ERR_NONE`
* is returned.
*/
EV_VEC_API ev_vec_error_t
ev_vec_pop(
void* vec_p,
void *out);
/*!
* \brief A function that returns the last element in the vector.
*
* \param vec_p 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(
const void* v);
/*!
* \brief A function that returns the length of a vector
*
* \param vec_p A pointer to the vector object
*
* \returns Current length of the vector
*/
EV_VEC_API u64
ev_vec_len(
void* vec_p);
/*!
* \brief A function that returns the capacity of a vector
*
* \param vec_p A pointer to the vector object
*
* \returns Current capacity of the vector
*/
EV_VEC_API u64
ev_vec_capacity(
const void* vec_p);
/*!
* \brief Calls the free operation (if exists) on every element, then sets
* the length to 0.
*
* \param vec_p A pointer to the vector object
*
* \returns 0 on success
*/
EV_VEC_API u32
ev_vec_clear(
const void* vec_p);
/*!
* \brief Sets the length of the vector to `len`.
*
* \details If `len` is less than `v`'s current length, then `v`'s length is
* amended. Otherwise, the capacity is checked to make sure that there is enough
* space for the new len.
*
* For `svec`, if the `len` is more than the already allocated capacity, it is
* treated as an OOM.
*
* \param vec_p Reference to the vector object
* \param len The desired new length
*
* \returns `VEC_ERR_NONE` on success
*/
EV_VEC_API ev_vec_error_t
ev_vec_setlen(
void* vec_p,
u64 len);
/*!
* \brief Sets the capacity of the vector to `cap`.
*
* \param vec_p Reference to the vector object
* \param cap The desired new capacity
*
* For stack-allocated vectors, `VEC_ERR_OOM` is returned
*
* \returns `VEC_ERR_NONE` on success, `VEC_ERR_OOM` on OOM
*/
EV_VEC_API ev_vec_error_t
ev_vec_setcapacity(
void* vec_p,
u64 cap);
/*!
* \brief Grows the vector's capacity by a factor of `VEC_GROWTH_RATE`
*
* \param vec_p Reference to the vector object
*
* \returns `VEC_ERR_NONE` on success
*/
EV_VEC_API ev_vec_error_t
ev_vec_grow(
void* vec_p);
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._magic = EV_VEC_MAGIC,
.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)
#else
#define EV_VEC_CHECK(x)
#endif
#include <stdlib.h>
#include <string.h>
#define ev_vec_meta(v) \
((struct ev_vec_meta_t *)v) - 1
#define __ev_vec_getmeta(v) \
struct ev_vec_meta_t *metadata = ((struct ev_vec_meta_t *)(v)) - 1; \
assert(metadata->_magic == EV_VEC_MAGIC);
#define __ev_vec_syncmeta(v) \
metadata = ((struct ev_vec_meta_t *)(v)) - 1;
ev_vec_t
ev_vec_init_impl(
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){
._magic = EV_VEC_MAGIC,
.length = 0,
.capacity = EV_VEC_INIT_CAP,
.allocationType = EV_VEC_ALLOCATION_TYPE_HEAP,
.typeData = typeData
};
return metadata + 1;
}
i32
ev_vec_find(
const void* vec_p,
void *val)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__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(
void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if (metadata->typeData.free_fn) {
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v);
ev_vec_iter_next(v, &elem)) {
metadata->typeData.free_fn(elem);
}
}
if(metadata->allocationType == EV_VEC_ALLOCATION_TYPE_HEAP) {
free(metadata);
}
*v = EV_INVALID(ev_vec_t);
}
int
ev_vec_push_impl(
void* vec_p,
void *val)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if (metadata->length == metadata->capacity) {
ev_vec_error_t grow_err = ev_vec_grow(v);
if(grow_err) {
return grow_err;
} else {
__ev_vec_syncmeta(*v)
}
}
void *dst = ((char *)*v) + (metadata->length * metadata->typeData.size);
if (metadata->typeData.copy_fn) {
metadata->typeData.copy_fn(dst, val);
} else {
memcpy(dst, val, metadata->typeData.size);
}
return (int)metadata->length++;
}
void *
ev_vec_iter_begin(
const void* vec_p)
{
return *(void**)vec_p;
}
void *
ev_vec_iter_end(
const void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
return ((char *)*v) + (metadata->typeData.size * metadata->length);
}
void
ev_vec_iter_next(
const void* vec_p,
void **iter)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
*iter = ((char*)*iter) + metadata->typeData.size;
}
EV_VEC_API u32
ev_vec_append(
void* vec_p,
void **arr,
u64 size)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
size_t old_len = metadata->length;
size_t req_len = old_len + size;
ev_vec_error_t setlen_err = ev_vec_setlen(v, req_len);
if(setlen_err) {
return setlen_err;
}
__ev_vec_syncmeta(*v)
void *dst = ((char *)*v) + (old_len * metadata->typeData.size);
memcpy(dst, *arr, metadata->typeData.size * size);
return (int)old_len;
}
EV_VEC_API ev_vec_t
ev_vec_dup(
const void* vec_p)
{
ev_vec_t v_orig = *(ev_vec_t*)vec_p;
__ev_vec_getmeta(v_orig)
ev_vec_t v_new = ev_vec_init_impl(metadata->typeData, (ev_vec_overrides_t){0});
ev_vec_setcapacity(&v_new, metadata->length);
if(metadata->typeData.copy_fn)
{
for(int i = 0; i < metadata->length; i++)
ev_vec_push_impl(&v_new, (u8*)v_orig + (metadata->typeData.size * i));
}
else
{
ev_vec_setlen(&v_new, metadata->length);
memcpy(v_new, v_orig, metadata->length * metadata->typeData.size);
}
return v_new;
}
ev_vec_error_t
ev_vec_pop(
void* vec_p,
void *out)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if(out != NULL) {
void *src = ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
if (metadata->typeData.copy_fn) {
metadata->typeData.copy_fn(out, src);
} else {
memcpy(out, src, metadata->typeData.size);
}
} else {
void *elem = ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
if (metadata->typeData.free_fn) {
metadata->typeData.free_fn(elem);
}
}
metadata->length--;
return EV_VEC_ERR_NONE;
}
void *
ev_vec_last(
const void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if(metadata->length == 0) {
return NULL;
}
return ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
}
u64
ev_vec_len(
void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
return metadata->length;
}
u64
ev_vec_capacity(
const void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
return metadata->capacity;
}
u32
ev_vec_clear(
const void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if (metadata->typeData.free_fn) {
for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v);
ev_vec_iter_next(v, &elem)) {
metadata->typeData.free_fn(elem);
}
}
metadata->length = 0;
return 0;
}
ev_vec_error_t
ev_vec_setlen(
void* vec_p,
u64 len)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
while(len > metadata->capacity) {
ev_vec_error_t grow_err = ev_vec_grow(v);
if(grow_err) {
return grow_err;
}
__ev_vec_syncmeta(*v)
}
metadata->length = len;
return EV_VEC_ERR_NONE;
}
ev_vec_error_t
ev_vec_setcapacity(
void* vec_p,
u64 cap)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
if(metadata->allocationType == EV_VEC_ALLOCATION_TYPE_STACK) {
return EV_VEC_ERR_OOM;
}
if(metadata->capacity == cap) {
return EV_VEC_ERR_NONE;
}
void *buf = ((char *)(*v) - sizeof(struct ev_vec_meta_t));
void *tmp = realloc(buf, sizeof(struct ev_vec_meta_t) + (cap * metadata->typeData.size));
if (!tmp) {
return EV_VEC_ERR_OOM;
}
if(buf != tmp) {
buf = tmp;
metadata = (struct ev_vec_meta_t *)buf;
*v = (char *)buf + sizeof(struct ev_vec_meta_t);
}
metadata->capacity = cap;
return EV_VEC_ERR_NONE;
}
ev_vec_error_t
ev_vec_grow(
void* vec_p)
{
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v)
return ev_vec_setcapacity(v, metadata->capacity * EV_VEC_GROWTH_RATE);
}
#endif
#endif

9
log_test.c Normal file
View File

@@ -0,0 +1,9 @@
#define EV_LOG_IMPLEMENTATION
#include "ev_log.h"
int main()
{
ev_log_trace("Trace Log");
return 0;
}

55
meson.build Normal file
View File

@@ -0,0 +1,55 @@
project('evol-headers', 'c',
default_options : [ 'c_std=gnu23' ])
headers_include = include_directories('.')
evh_c_args = []
buildtype = get_option('buildtype')
if buildtype == 'debug'
evh_c_args += '-DEV_BUILDTYPE_DEBUG=1'
elif buildtype == 'debugoptimized'
evh_c_args += '-DEV_BUILDTYPE_DEBUGOPT=1'
else
evh_c_args += '-DEV_BUILDTYPE_RELEASE=1'
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)
log_lib = static_library('ev_log', files('buildfiles/ev_log.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)
log_dep = declare_dependency(link_with: log_lib, include_directories: headers_include)
headers_dep = declare_dependency(
dependencies: [
str_dep,
vec_dep,
helpers_dep,
log_dep
]
)
# Tests
str_test = executable('str_test', 'str_test.c', dependencies: [str_dep], c_args: evh_c_args)
test('evstr', str_test)
log_test = executable('log_test', 'log_test.c', dependencies: [log_dep], c_args: evh_c_args)
test('evlog', log_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('ev_log', log_dep)
meson.override_dependency('evol-headers', headers_dep)
endif

81
str_test.c Normal file
View File

@@ -0,0 +1,81 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
evstring global_str = evstr("Global 'Hello, World!'");
int main()
{
const evstring stack_str = evstr("Stack 'Hello, World!'");
printf("Stack String: %s, Length: %llu\n", stack_str, evstring_getLength(stack_str));
printf("Global String: %s, Length: %llu\n", global_str, evstring_getLength(global_str));
evstring heap_str = evstring_new("Heap 'Hello, World!'");
printf("Heap String: %s, Length: %llu\n", heap_str, evstring_getLength(heap_str));
evstring_view view = evstring_slice(stack_str, 0, -1);
printf("String View: %.*s\n", (i32)view.len, view.data + view.offset);
printf("View length: %llu\n", view.len);
evstring heap_str2 = evstring_new(view);
printf("Heap String 2: %s, Length: %llu\n", heap_str2, evstring_getLength(heap_str2));
evstring_free(heap_str2);
evstring_error_t push_str_res = evstring_push(&heap_str, "Hello, Sisyphus! %f", 0.001f);
printf("Push char*: %s, New Length: %llu\n", heap_str, evstring_getLength(heap_str));
assert(push_str_res == EV_STR_ERR_NONE);
evstring_error_t push_char_res = evstring_push(&heap_str, (char)'X');
printf("Push char: %s, New Length: %llu\n", heap_str, evstring_getLength(heap_str));
assert(push_char_res == EV_STR_ERR_NONE);
evstring_error_t push_view_res = evstring_push(&heap_str, view);
printf("Push view: %s, New Length: %llu\n", heap_str, evstring_getLength(heap_str));
assert(push_view_res == EV_STR_ERR_NONE);
evstring str_fmt = evstring_new("%d, %d, %.*s", 1, 0, view.len, view.data + view.offset);
printf("Formatted String: %s\n", str_fmt);
evstring rep_str = evstring_replaceFirst(heap_str, evstr("Hello"), evstr("Bye"));
printf("Replaced String: %s\n", rep_str);
evstring_free(rep_str);
evstring_free(str_fmt);
evstring_free(heap_str);
evstring_view search_results[8];
evstring search_string = evstr("Hello, this is me saying `Hello` like someone who says 'Hello'");
assert(evstring_findAll(search_string, evstr("Hello"), search_results) == 3);
assert(search_results[0].data == search_string);
assert(search_results[1].data == search_string);
assert(search_results[2].data == search_string);
assert(search_results[0].len == 5);
assert(search_results[1].len == 5);
assert(search_results[2].len == 5);
assert(search_results[0].offset == 0);
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
View 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;
}