1 Commits

Author SHA1 Message Date
mo7sen b1b99cb224 WIP Map Impl
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
2025-07-02 20:44:34 +03:00
54 changed files with 519 additions and 1237 deletions
-37
View File
@@ -1,37 +0,0 @@
name: Run tests
run-name: Running Tests
on: [push]
jobs:
Run tests:
runs-on: ubuntu-latest
container:
image: git.neosisyphus.com/evol3d/evol-testbed:latest
steps:
- uses: actions/checkout@v4
- name: Configure
run: meson setup build
# run: meson setup -Db_coverage=true build
- name: Run Tests
run: meson test -C build
- name: Run Memory Tests
if: always()
run: meson test -C build --wrapper=valgrind
# - name: Generate coverage report
# if: always()
# run: ninja coverage-html -C build
- name: Upload Logs
if: always()
uses: https://git.neosisyphus.com/mo7sen/upload-artifact-gitea@v7
with:
path: |
build/meson-logs/meson-log.txt
build/meson-logs/meson-setup.txt
build/meson-logs/testlog.txt
archive: false
-2
View File
@@ -1,2 +0,0 @@
.cache
build
-11
View File
@@ -1,11 +0,0 @@
[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']
[cmake]
CMAKE_C_COMPILER = 'clang-19'
-11
View File
@@ -1,11 +0,0 @@
[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
View File
@@ -1,2 +0,0 @@
#define EV_LOG_IMPLEMENTATION
#include "../ev_log.h"
+4 -4
View File
@@ -67,18 +67,18 @@
# if defined(_MSC_VER) # if defined(_MSC_VER)
# undef EV_CC_MSVC # undef EV_CC_MSVC
# define EV_CC_MSVC 1 # define EV_CC_MSVC 1
# elif defined(__clang)
# undef EV_CC_CLANG
# define EV_CC_CLANG 1
# elif defined(__GNUC__) # elif defined(__GNUC__)
# undef EV_CC_GCC # undef EV_CC_GCC
# define EV_CC_GCC 1 # define EV_CC_GCC 1
# elif defined(__clang)
# undef EV_CC_CLANG
# define EV_CC_CLANG 1
# else # else
# error EV_CC_UNKNOWN # error EV_CC_UNKNOWN
# endif # endif
#endif #endif
#if !defined(EV_BUILDTYPE_DEBUG) && !defined(EV_BUILDTYPE_DEBUGOPT) && !defined(EV_BUILDTYPE_RELEASE) #if !defined(EV_BUILDTYPE_DEBUG) && !defined(EV_BUILDTYPE_DEBUG_OPT) && !defined(EV_BUILDTYPE_RELEASE)
#define EV_BUILDTYPE_RELEASE 1 #define EV_BUILDTYPE_RELEASE 1
#endif #endif
+2 -2
View File
@@ -6,7 +6,7 @@
/*! /*!
* \brief MurmurHash3 64-bit version. Returns 64-bit hash instead of 128 * \brief MurmurHash3 64-bit version. Returns 64-bit hash instead of 128
*/ */
u64 ev_hash_murmur3(const void *data, u32 len, u32 seed); u64 ev_hash_murmur3(const void *data, u32 len, u64 seed);
#ifdef EV_HASH_IMPLEMENTATION #ifdef EV_HASH_IMPLEMENTATION
#undef EV_HASH_IMPLEMENTATION #undef EV_HASH_IMPLEMENTATION
@@ -151,7 +151,7 @@ void MurmurHash3_x64_128 ( const void * key, const u32 len,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
u64 ev_hash_murmur3(const void *data, u32 len, u32 seed) u64 ev_hash_murmur3(const void *data, u32 len, u64 seed)
{ {
u64 out[2]; u64 out[2];
MurmurHash3_x64_128(data, len, (u32)seed, out); MurmurHash3_x64_128(data, len, (u32)seed, out);
+1 -7
View File
@@ -23,18 +23,12 @@ evstring_readFile(
#ifdef EV_HELPERS_IMPLEMENTATION #ifdef EV_HELPERS_IMPLEMENTATION
#undef EV_HELPERS_IMPLEMENTATION #undef EV_HELPERS_IMPLEMENTATION
evstring evstring
evstring_readFile( evstring_readFile(
evstring filePath) evstring filePath)
{ {
FILE* f = NULL; FILE* f = fopen(filePath, "rb");
#if EV_OS_WINDOWS
if(fopen_s(&f,filePath,"rb")) return EV_INVALID(evstring);
#else
f = fopen(filePath, "rb");
if(f == NULL) return EV_INVALID(evstring); if(f == NULL) return EV_INVALID(evstring);
#endif
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
u32 buflen = ftell(f); u32 buflen = ftell(f);
+8 -10
View File
@@ -1,17 +1,15 @@
#ifndef EV_HEADERS_INTERNAL_H #ifndef EV_HEADERS_INTERNAL_H
#define EV_HEADERS_INTERNAL_H #define EV_HEADERS_INTERNAL_H
#include <stdint.h> typedef signed char i8;
typedef short int i16;
typedef int i32;
typedef long long int i64;
typedef int8_t i8; typedef unsigned char u8;
typedef int16_t i16; typedef unsigned short int u16;
typedef int32_t i32; typedef unsigned int u32;
typedef int64_t i64; typedef unsigned long long int u64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef float f32; typedef float f32;
typedef double f64; typedef double f64;
-202
View File
@@ -1,202 +0,0 @@
#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 ev_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
+1 -1
View File
@@ -143,7 +143,7 @@
/*! /*!
* \brief Macro that returns the number of arguments passed to it. * \brief Macro that returns the number of arguments passed to it.
*/ */
#define EV_VA_ARGS_NARG(...) EV_VA_ARGS_NARG_IMPL(_ __VA_OPT__(,__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_NARG_IMPL(...) EV_VA_ARGS_ARG_N(__VA_ARGS__)
#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_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_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
+248
View 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
+10 -21
View File
@@ -5,20 +5,20 @@
#include "ev_types.h" #include "ev_types.h"
// Signed integers // Signed integers
TYPEDATA_GEN(i8) TYPEDATA_GEN(i8);
TYPEDATA_GEN(i16) TYPEDATA_GEN(i16);
TYPEDATA_GEN(i32) TYPEDATA_GEN(i32);
TYPEDATA_GEN(i64) TYPEDATA_GEN(i64);
// Unsigned integers // Unsigned integers
TYPEDATA_GEN(u8 ) TYPEDATA_GEN(u8 );
TYPEDATA_GEN(u16) TYPEDATA_GEN(u16);
TYPEDATA_GEN(u32) TYPEDATA_GEN(u32);
TYPEDATA_GEN(u64) TYPEDATA_GEN(u64);
// Floating-Point Numbers // Floating-Point Numbers
TYPEDATA_GEN(f32) TYPEDATA_GEN(f32);
TYPEDATA_GEN(f64) TYPEDATA_GEN(f64);
struct Int8Data { i8 MIN; i8 MAX; }; struct Int8Data { i8 MIN; i8 MAX; };
struct Int16Data { i16 MIN; i16 MAX; }; struct Int16Data { i16 MIN; i16 MAX; };
@@ -97,15 +97,4 @@ static const struct Float64Data Float64 =
.EPS = 2.2204460492503131e-016 .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 #endif // EV_HEADERS_NUMERIC_H
+54 -121
View File
@@ -43,25 +43,18 @@
#define EV_STR_GROWTH_FACTOR 3 / 2 #define EV_STR_GROWTH_FACTOR 3 / 2
#endif #endif
#ifndef EV_STR_MIN_CAPACITY
/*!
* \brief Rate at which an evstring grows whenever a resize is needed
*/
#define EV_STR_MIN_CAPACITY 4
#endif
typedef char *evstring; typedef char *evstring;
typedef enum { typedef enum {
EV_STR_ERR_NONE = 0, EV_STR_ERR_NONE = 0,
EV_STR_ERR_OOM = -1, EV_STR_ERR_OOM = -1,
} evstring_error_t; } evstring_error_t;
TYPEDATA_GEN(evstring_error_t, DEFAULT(EV_STR_ERR_NONE)) TYPEDATA_GEN(evstring_error_t, DEFAULT(EV_STR_ERR_NONE));
struct evstr_meta_t { struct evstr_meta_t {
EV_DEBUG(u64 magic;) EV_DEBUG(u64 magic;)
u64 length; u64 length;
u64 capacity; u64 size;
enum { enum {
EV_STR_ALLOCATION_TYPE_STACK, EV_STR_ALLOCATION_TYPE_STACK,
EV_STR_ALLOCATION_TYPE_HEAP EV_STR_ALLOCATION_TYPE_HEAP
@@ -74,7 +67,7 @@ struct evstr_meta_t {
(( struct { struct evstr_meta_t meta; char data[len]; } ) { \ (( struct { struct evstr_meta_t meta; char data[len]; } ) { \
EV_DEBUG(.meta.magic = EV_STR_evstring_MAGIC,) \ EV_DEBUG(.meta.magic = EV_STR_evstring_MAGIC,) \
.meta.length = len-1, \ .meta.length = len-1, \
.meta.capacity = len, \ .meta.size = len, \
.meta.allocationType = EV_STR_ALLOCATION_TYPE_STACK, \ .meta.allocationType = EV_STR_ALLOCATION_TYPE_STACK, \
.data = str \ .data = str \
}).data }).data
@@ -127,11 +120,6 @@ evstring_cmp(
const evstring s1, const evstring s1,
const evstring s2); const evstring s2);
EV_STR_API i32
evstring_view_cmp(
const evstring_view v1,
const evstring_view v2);
EV_STR_API evstring_error_t EV_STR_API evstring_error_t
evstring_pushChar( evstring_pushChar(
evstring *s, evstring *s,
@@ -158,7 +146,7 @@ evstring_slice(
i64 begin, i64 begin,
i64 end); i64 end);
EV_STR_API evstring_error_t EV_STR_API i32
evstring_pushView( evstring_pushView(
evstring *s, evstring *s,
evstring_view ref); evstring_view ref);
@@ -183,6 +171,11 @@ evstring_findFirst(
const evstring text, const evstring text,
const evstring query); const evstring query);
evstring_view
__evstring_findFirst_impl(
evstring_view text,
evstring_view query);
EV_STR_API evstring EV_STR_API evstring
evstring_replaceFirst( evstring_replaceFirst(
const evstring text, const evstring text,
@@ -204,30 +197,9 @@ DEFINE_EQUAL_FUNCTION(evstring, Default)
return evstring_cmp(*(evstring*)self, *(evstring*)other) == 0; 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, TYPEDATA_GEN(evstring,
EQUAL(Default), EQUAL(Default)
COPY(Default), );
FREE(Default)
)
DEFINE_EQUAL_FUNCTION(evstring_view, Default)
{
return evstring_view_cmp(*self, *other) == 0;
}
TYPEDATA_GEN(evstring_view,
EQUAL(Default),
)
#if defined(EV_STR_IMPLEMENTATION) #if defined(EV_STR_IMPLEMENTATION)
@@ -265,10 +237,9 @@ evstring_new_impl(
const char *data, const char *data,
u64 len) u64 len)
{ {
u64 str_cap = len + 1; u64 size = sizeof(struct evstr_meta_t) + len + 1;
u64 alloc_size = sizeof(struct evstr_meta_t) + str_cap;
void *p = ev_str_malloc(alloc_size); void *p = ev_str_malloc(size);
assert(p); // Raised if malloc fails assert(p); // Raised if malloc fails
struct evstr_meta_t *meta = (struct evstr_meta_t *)p; struct evstr_meta_t *meta = (struct evstr_meta_t *)p;
@@ -277,7 +248,7 @@ EV_DEBUG
meta->magic = EV_STR_evstring_MAGIC; meta->magic = EV_STR_evstring_MAGIC;
) )
meta->length = len; meta->length = len;
meta->capacity = str_cap; meta->size = size;
meta->allocationType = EV_STR_ALLOCATION_TYPE_HEAP; meta->allocationType = EV_STR_ALLOCATION_TYPE_HEAP;
evstring s = (evstring)(meta + 1); evstring s = (evstring)(meta + 1);
@@ -298,11 +269,10 @@ evstring_newFmt_v(
{ {
va_list test; va_list test;
va_copy(test, args); va_copy(test, args);
i32 expected_len = vsnprintf(NULL, 0, fmt, test); i32 len = vsnprintf(NULL, 0, fmt, test);
if(expected_len < 0) { if(len < 0) {
return EV_INVALID(evstring); return EV_INVALID(evstring);
} }
size_t len = (size_t)expected_len;
evstring res = evstring_new_impl(NULL, 0); evstring res = evstring_new_impl(NULL, 0);
evstring_setLength(&res, len); evstring_setLength(&res, len);
vsnprintf(res, len + 1, fmt, args); vsnprintf(res, len + 1, fmt, args);
@@ -348,7 +318,7 @@ evstring_free(
{ {
evstr_asserttype(s); evstr_asserttype(s);
if(META(s)->allocationType == EV_STR_ALLOCATION_TYPE_HEAP) { if(META(s)->allocationType == EV_STR_ALLOCATION_TYPE_HEAP) {
ev_str_free(META(s)); free(META(s));
} }
} }
@@ -361,9 +331,9 @@ evstring_getLength(
} }
evstring_error_t evstring_error_t
evstring_setCapacity( evstring_setSize(
evstring *s, evstring *s,
size_t new_capacity) size_t newsize)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s); struct evstr_meta_t *meta = META(*s);
@@ -371,12 +341,12 @@ evstring_setCapacity(
return EV_STR_ERR_OOM; return EV_STR_ERR_OOM;
} }
if(meta->capacity == new_capacity) { if(meta->size == newsize) {
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
void *buf = (void*)meta; void *buf = (void*)meta;
void *tmp = ev_str_realloc(buf, sizeof(struct evstr_meta_t) + new_capacity); void *tmp = ev_str_realloc(buf, sizeof(struct evstr_meta_t) + newsize);
if (!tmp) { if (!tmp) {
return EV_STR_ERR_OOM; return EV_STR_ERR_OOM;
@@ -388,7 +358,7 @@ evstring_setCapacity(
*s = (evstring)(meta+1); *s = (evstring)(meta+1);
} }
meta->capacity = new_capacity; meta->size = newsize;
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
@@ -397,8 +367,7 @@ evstring_grow(
evstring *s) evstring *s)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
u64 new_cap = max(EV_STR_MIN_CAPACITY, META(*s)->capacity * EV_STR_GROWTH_FACTOR); return evstring_setSize(s, META(*s)->size * EV_STR_GROWTH_FACTOR);
return evstring_setCapacity(s, new_cap);
} }
evstring_error_t evstring_error_t
@@ -412,8 +381,8 @@ evstring_setLength(
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
u64 required_capacity = newlen + 1; u64 required_size = sizeof(struct evstr_meta_t) + newlen + 1;
while(required_capacity > meta->capacity) { while(required_size > meta->size) {
evstring_error_t grow_err = evstring_grow(s); evstring_error_t grow_err = evstring_grow(s);
if(grow_err) { if(grow_err) {
return grow_err; return grow_err;
@@ -421,7 +390,6 @@ evstring_setLength(
meta = META(*s); meta = META(*s);
} }
meta->length = newlen; meta->length = newlen;
(*s)[newlen] = 0;
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
@@ -449,19 +417,6 @@ evstring_cmp(
return memcmp(s1, s2, len1); return memcmp(s1, s2, len1);
} }
i32
evstring_view_cmp(
const evstring_view v1,
const evstring_view v2)
{
evstr_asserttype(v1.data);
evstr_asserttype(v2.data);
if(v1.len != v2.len) {
return 1;
}
return memcmp(v1.data+v1.offset, v2.data+v2.offset, v1.len);
}
evstring_error_t evstring_error_t
evstring_push_impl( evstring_push_impl(
@@ -472,18 +427,9 @@ evstring_push_impl(
evstr_asserttype(*s); evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s); struct evstr_meta_t *meta = META(*s);
// Overlapping ranges, need to copy `data` to keep it alive after growing
if(*s < data + sz && data < *s + meta->length)
{
char *old_data = data;
data = ev_str_malloc(sz);
if(data == NULL) return EV_STR_ERR_OOM;
memcpy(data, old_data, sz);
}
// TODO Find a more efficient approach? // TODO Find a more efficient approach?
u64 required_capacity = meta->length + sz + 1; u64 required_size = sizeof(struct evstr_meta_t) + meta->length + sz + 1;
while(required_capacity > meta->capacity) { // `<=` because of the null terminator while(required_size > meta->size) { // `<=` because of the null terminator
evstring_error_t grow_err = evstring_grow(s); evstring_error_t grow_err = evstring_grow(s);
if(grow_err != EV_STR_ERR_NONE) { if(grow_err != EV_STR_ERR_NONE) {
return grow_err; return grow_err;
@@ -540,13 +486,10 @@ evstring_slice(
u64 wrapped_begin = begin < 0 ? string_len + 1 + begin : begin; u64 wrapped_begin = begin < 0 ? string_len + 1 + begin : begin;
u64 wrapped_end = end < 0 ? string_len + 1 + end : end; u64 wrapped_end = end < 0 ? string_len + 1 + end : end;
// In this case, the assertions don't matter assert(wrapped_begin >= 0 && wrapped_begin < string_len);
if(wrapped_begin != wrapped_end) assert(wrapped_end > 0 && wrapped_end <= string_len);
{
assert(wrapped_begin >= 0 && wrapped_begin < string_len); assert(wrapped_begin < wrapped_end);
assert(wrapped_end > 0 && wrapped_end <= string_len);
assert(wrapped_begin < wrapped_end);
}
return (evstring_view) { return (evstring_view) {
.data = s, .data = s,
@@ -561,7 +504,7 @@ evstring_getSpace(
{ {
evstr_asserttype(s); evstr_asserttype(s);
struct evstr_meta_t *meta = META(s); struct evstr_meta_t *meta = META(s);
return meta->capacity - meta->length - 1; return meta->size - meta->length - 1 - sizeof(struct evstr_meta_t);
} }
evstring_error_t evstring_error_t
@@ -570,34 +513,32 @@ evstring_addSpace(
u64 space) u64 space)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
return evstring_setCapacity(s, META(*s)->capacity + space); return evstring_setSize(s, META(*s)->size + space);
} }
evstring_view evstring_view
evstring_findFirst_impl( __evstring_findFirst_impl(
evstring_view text, evstring_view text,
evstring_view query) evstring_view query)
{ {
u64 found_progress = 0;
evstring_view result = { evstring_view result = {
.data = text.data, .data = text.data,
.len = 0, .len = 0,
.offset = ~0ull .offset = ~0ull
}; };
if(query.len == 0 || query.len > text.len) for(u64 i = text.offset; i < text.offset + text.len; i++) {
return result; if(text.data[i] == query.data[query.offset + found_progress]) {
found_progress++;
for(u64 l = text.offset; l <= text.offset + text.len - query.len; l++) }
{ if(found_progress == query.len) {
evstring_view curr_view = { result.offset = (i+1) - query.len;
.data = text.data, result.len = query.len;
.len = query.len, break;
.offset = l }
};
if(EV_EQUAL(evstring_view)(&curr_view, &query))
return curr_view;
} }
return result; return result;
} }
@@ -608,7 +549,7 @@ evstring_findFirst(
{ {
evstr_asserttype(text); evstr_asserttype(text);
evstr_asserttype(query); evstr_asserttype(query);
return evstring_findFirst_impl(evstring_slice(text, 0, -1), evstring_slice(query, 0, -1)); return __evstring_findFirst_impl(evstring_slice(text, 0, -1), evstring_slice(query, 0, -1));
} }
evstring evstring
@@ -727,25 +668,17 @@ evstring_findAll(
if(text_len == 0 || query_len == 0 || query_len > text_len) { if(text_len == 0 || query_len == 0 || query_len > text_len) {
return 0; return 0;
} }
bool check_run = (results == NULL);
evstring_view query_view = evstring_slice(query, 0, -1);
u64 count = 0; u64 count = 0;
for(evstring_view v = evstring_findFirst(text, query);
for(u64 l = 0; l <= text_len - query_len; l++) v.len != 0;
{ v = __evstring_findFirst_impl(
evstring_view curr_view = { evstring_slice(text, v.offset + v.len, -1),
.data = text, evstring_slice(query, 0, -1))) {
.len = query_len, if(!check_run) {
.offset = l results[count++] = v;
};
if(EV_EQUAL(evstring_view)(&curr_view, &query_view))
{
if(results) results[count] = curr_view;
count++;
} }
} }
return count; return count;
} }
+13 -14
View File
@@ -30,12 +30,12 @@ typedef struct {
void *invalid_val; void *invalid_val;
} EvTypeData; } EvTypeData;
#define COPY_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_COPY_FUNCTION_ ,T),_),name) #define COPY_FUNCTION(T,name) EV_CATN(EV_COPY_FUNCTION_,T,_,name)
#define FREE_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_FREE_FUNCTION_ ,T),_),name) #define FREE_FUNCTION(T,name) EV_CATN(EV_FREE_FUNCTION_,T,_,name)
#define HASH_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_HASH_FUNCTION_ ,T),_),name) #define HASH_FUNCTION(T,name) EV_CATN(EV_HASH_FUNCTION_,T,_,name)
#define EQUAL_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_EQUAL_FUNCTION_ ,T),_),name) #define EQUAL_FUNCTION(T,name) EV_CATN(EV_EQUAL_FUNCTION_,T,_,name)
#define TOSTR_FUNCTION(T ,name) EV_CAT(EV_CAT(EV_CAT(EV_TOSTR_FUNCTION_ ,T),_),name) #define TOSTR_FUNCTION(T,name) EV_CATN(EV_TOSTR_FUNCTION_,T,_,name)
#define TOSTRLEN_FUNCTION(T,name) EV_CAT(EV_CAT(EV_CAT(EV_TOSTRLEN_FUNCTION_,T),_),name) #define TOSTRLEN_FUNCTION(T,name) EV_CATN(EV_TOSTRLEN_FUNCTION_,T,_,name)
#define DEFINE_COPY_FUNCTION(T,name) static inline void COPY_FUNCTION(T,name)(T *dst, T *src) #define DEFINE_COPY_FUNCTION(T,name) static inline void COPY_FUNCTION(T,name)(T *dst, T *src)
#define DEFINE_DEFAULT_COPY_FUNCTION(T) \ #define DEFINE_DEFAULT_COPY_FUNCTION(T) \
@@ -80,10 +80,9 @@ typedef struct {
#define EV_OVERRIDE_VAR(T) EV_CAT(__ev_internal_override_var_,T) #define EV_OVERRIDE_VAR(T) EV_CAT(__ev_internal_override_var_,T)
#define TypeData(T) EV_CAT(EV_TYPEDATA_,T) #define TypeData(T) EV_CAT(EV_TYPEDATA_,T)
#define TYPEDATA_GEN(T, ...) \ #define TYPEDATA_GEN(T, ...) \
EV_WARNING_PUSH() \ EV_WARNING_PUSH(); \
EV_WARNING_DISABLE_GCC("override-init") \ EV_WARNING_DISABLE_GCC("override-init"); \
EV_WARNING_DISABLE_CLANG("initializer-overrides") \ EV_WARNING_DISABLE_CLANG("initializer-overrides"); \
EV_WARNING_DISABLE_CLANG("reserved-identifier") \
EV_UNUSED static const EvTypeData TypeData(T) = { \ EV_UNUSED static const EvTypeData TypeData(T) = { \
EV_DEBUG(.name = EV_STRINGIZE(T),) \ EV_DEBUG(.name = EV_STRINGIZE(T),) \
.size = sizeof(T), \ .size = sizeof(T), \
@@ -92,10 +91,10 @@ typedef struct {
.invalid_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_VA_OPT(__VA_ARGS__)(EV_FOREACH_UDATA(__EV_STRUCT_METHOD_DEF, T, __VA_ARGS__)) \
}; \ }; \
EV_UNUSED static T EV_OVERRIDE_VAR(T); \ EV_WARNING_POP(); \
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 __EV_STRUCT_METHOD_DEF(T, ...) EV_CATN(__EV_,EV_HEAD __VA_ARGS__,_FN)(T, EV_TAIL __VA_ARGS__)
#define COPY(...) (COPY , __VA_ARGS__) #define COPY(...) (COPY , __VA_ARGS__)
#define FREE(...) (FREE , __VA_ARGS__) #define FREE(...) (FREE , __VA_ARGS__)
@@ -153,6 +152,6 @@ DEFINE_TOSTR_FUNCTION(EvTypeData, EvTypeDataStringize)
} }
TYPEDATA_GEN(EvTypeData, TYPEDATA_GEN(EvTypeData,
TOSTR(EvTypeDataStringize)) TOSTR(EvTypeDataStringize));
#endif // EV_HEADERS_TYPES_H #endif // EV_HEADERS_TYPES_H
+62 -148
View File
@@ -6,10 +6,6 @@
#include "ev_types.h" #include "ev_types.h"
#include "ev_numeric.h" #include "ev_numeric.h"
#if !EV_CC_MSVC
#include <string.h>
#endif
#if defined(EV_VEC_SHARED) #if defined(EV_VEC_SHARED)
# if defined (EV_VEC_IMPL) # if defined (EV_VEC_IMPL)
# define EV_VEC_API EV_EXPORT # define EV_VEC_API EV_EXPORT
@@ -34,14 +30,6 @@
#define EV_VEC_GROWTH_RATE 3 / 2 #define EV_VEC_GROWTH_RATE 3 / 2
#endif #endif
#ifndef EV_VEC_MIN_CAPACITY
/*!
* \brief Minimum capacity used by vector when growing
*/
#define EV_VEC_MIN_CAPACITY 4
#endif
#if EV_CC_MSVC #if EV_CC_MSVC
# define __EV_VEC_EMPTY_ARRAY { 0 } # define __EV_VEC_EMPTY_ARRAY { 0 }
#else #else
@@ -53,8 +41,7 @@ typedef void *ev_svec_t;
typedef enum { typedef enum {
EV_VEC_ERR_NONE = 0, EV_VEC_ERR_NONE = 0,
EV_VEC_ERR_OOM = -1, EV_VEC_ERR_OOM = 1
EV_VEC_ERR_INVALID_OP = -2
} ev_vec_error_t; } ev_vec_error_t;
TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE)); TYPEDATA_GEN(ev_vec_error_t, DEFAULT(EV_VEC_ERR_NONE));
@@ -112,12 +99,8 @@ TYPEDATA_GEN(ev_vec_overrides_t);
*/ */
#define ev_svec(T) T* #define ev_svec(T) T*
#define EV_VEC_MAGIC (0x65765F7665635F74)
//! Metadata that is stored with a vector. Unique to each vector. //! Metadata that is stored with a vector. Unique to each vector.
struct ev_vec_meta_t { struct ev_vec_meta_t {
u64 _magic;
//! The number of elements in the vector. //! The number of elements in the vector.
u64 length; u64 length;
//! The maximum length of the vector before it needs to be resized. //! The maximum length of the vector before it needs to be resized.
@@ -157,19 +140,15 @@ ev_vec_init_impl(
static struct ev_vec_meta_t *__svec_interm_md; static struct ev_vec_meta_t *__svec_interm_md;
#define __ev_svec_init_impl(T, len, cap, ...) ( \ #define __ev_svec_init_impl(T, len, cap, ...) ( \
EV_WARNING_PUSH() \ __svec_interm_md = (u8[sizeof(T)*cap + sizeof(struct ev_vec_meta_t)]){}, \
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){ \ *__svec_interm_md = (struct ev_vec_meta_t){ \
._magic = EV_VEC_MAGIC, \
.length = len, \ .length = len, \
.capacity = cap, \ .capacity = cap, \
.typeData = TypeData(T), \ .typeData = TypeData(T), \
.allocationType = EV_VEC_ALLOCATION_TYPE_STACK, \ .allocationType = EV_VEC_ALLOCATION_TYPE_STACK, \
}, \ }, \
EV_VA_OPT(__VA_ARGS__)(memcpy(&__svec_interm_md[1], (T[])__VA_ARGS__, sizeof((T[])__VA_ARGS__)),) \ EV_VA_OPT(__VA_ARGS__)(memcpy(&__svec_interm_md[1], (T[])__VA_ARGS__, sizeof((T[])__VA_ARGS__)),) \
(void*)&(__svec_interm_md[1]) \ &(__svec_interm_md[1]) \
EV_WARNING_POP() \
) )
/*! /*!
@@ -186,50 +165,50 @@ static struct ev_vec_meta_t *__svec_interm_md;
* *Note* This is possibly replaceable with a variadic function. * *Note* This is possibly replaceable with a variadic function.
*/ */
#define ev_vec_push(v, ...) \ #define ev_vec_push(v, ...) \
EV_FOREACH_UDATA(__ev_vec_internal_push, v, __VA_ARGS__) 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) #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 * \param v A pointer to the vector that we want an iterator for
* *
* \returns A pointer to the first element in a vector * \returns A pointer to the first element in a vector
*/ */
EV_VEC_API void * EV_VEC_API void *
ev_vec_iter_begin( ev_vec_iter_begin(
const void* vec_p); const ev_vec_t* v);
/*! /*!
* \param vec_p A pointer to 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 * \returns A pointer to the memory block right after the last element in the vector
*/ */
EV_VEC_API void * EV_VEC_API void *
ev_vec_iter_end( ev_vec_iter_end(
const void* vec_p); const ev_vec_t* v);
/*! /*!
* \brief A function that increments an iterator to make it point to the next * \brief A function that increments an iterator to make it point to the next
* element in the vector * element in the vector
* *
* \param vec_p A pointer to 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 * \param iter Reference to the iterator that is being incremented
*/ */
EV_VEC_API void EV_VEC_API void
ev_vec_iter_next( ev_vec_iter_next(
const void* vec_p, const ev_vec_t* v,
void **iter); void **iter);
/*! /*!
* \brief A function that looks for the index of `val` in `v` * \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 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 * \param val A pointer to the object that will be compared with vector elements
* *
* \returns If found, index of element in vector. Otherwise, -1. * \returns If found, index of element in vector. Otherwise, -1.
*/ */
EV_VEC_API i32 EV_VEC_API i32
ev_vec_find( ev_vec_find(
const void* vec_p, const ev_vec_t* v,
void* val); void* val);
/*! /*!
@@ -240,11 +219,11 @@ ev_vec_find(
* *Note*: For stack-allocated vectors (`svec`), destructors are called for * *Note*: For stack-allocated vectors (`svec`), destructors are called for
* elements but no memory is freed. * elements but no memory is freed.
* *
* \param vec_p A pointer to the vector that is being destroyed * \param v A pointer to the vector that is being destroyed
*/ */
EV_VEC_API void EV_VEC_API void
ev_vec_fini( ev_vec_fini(
void* vec_p); ev_vec_t* v);
/*! /*!
* \brief A function that copies a value to the end of a vector. If the element * \brief A function that copies a value to the end of a vector. If the element
@@ -256,16 +235,16 @@ ev_vec_fini(
* For `svec`, as long as the capacity is more than the current size, a push * 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. * operation is permitted. Otherwise, the operation is treated as an OOM.
* *
* \param vec_p Reference to the vector object * \param v Reference to the vector object
* \param val A pointer to the element that is to be copied to the end of the * \param val A pointer to the element that is to be copied to the end of the
* vector * vector
* *
* \returns The index of the element that was just pushed. If the operation * \returns The index of the element that was just pushed. If the operation
* failed, a less-than-zero (vec_error_t) value is returned. * failed, a non-zero (vec_error_t) value is returned.
*/ */
EV_VEC_API int EV_VEC_API int
ev_vec_push_impl( ev_vec_push_impl(
void* vec_p, ev_vec_t *v,
void *val); void *val);
/*! /*!
@@ -281,7 +260,7 @@ ev_vec_push_impl(
* operation. If a deep copy is needed, individually pushing the elements of * operation. If a deep copy is needed, individually pushing the elements of
* the array is the way to go. * the array is the way to go.
* *
* \param vec_p Reference to the vector object * \param v Reference to the vector object
* \param arr A pointer to the array that is to be copied to the end of the * \param arr A pointer to the array that is to be copied to the end of the
* vector * vector
* \param size Number of elements in the array * \param size Number of elements in the array
@@ -291,32 +270,17 @@ ev_vec_push_impl(
*/ */
EV_VEC_API u32 EV_VEC_API u32
ev_vec_append( ev_vec_append(
void* vec_p, ev_vec_t *v,
void **arr, void **arr,
u64 size); 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 * \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 * 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 * vector, then this function is used. Otherwise, memcpy is used with a length
* of `vec_meta.elemsize` * of `vec_meta.elemsize`
* *
* \warning Having a free_fn defined for the elemtype but no copy_fn could have some * \param v Reference to the vector object
* unwanted side effects as the free function will be called on the popped element
* after copying it to `out`
*
* \param vec_p Reference to the vector object
* \param out A pointer to the memory block at which the popped element will be * \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 * 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 * element is copied to `out` and the receiving code is responsible for its
@@ -327,54 +291,54 @@ ev_vec_dup(
*/ */
EV_VEC_API ev_vec_error_t EV_VEC_API ev_vec_error_t
ev_vec_pop( ev_vec_pop(
void* vec_p, ev_vec_t *v,
void *out); void *out);
/*! /*!
* \brief A function that returns the last element in the vector. * \brief A function that returns the last element in the vector.
* *
* \param vec_p A pointer 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 * \returns Pointer to the last element in the vector. NULL if the vector is
* empty. * empty.
*/ */
EV_VEC_API void * EV_VEC_API void *
ev_vec_last( ev_vec_last(
const void* v); const ev_vec_t* v);
/*! /*!
* \brief A function that returns the length of a vector * \brief A function that returns the length of a vector
* *
* \param vec_p A pointer to the vector object * \param v A pointer to the vector object
* *
* \returns Current length of the vector * \returns Current length of the vector
*/ */
EV_VEC_API u64 EV_VEC_API u64
ev_vec_len( ev_vec_len(
void* vec_p); const ev_vec_t* v);
/*! /*!
* \brief A function that returns the capacity of a vector * \brief A function that returns the capacity of a vector
* *
* \param vec_p A pointer to the vector object * \param v A pointer to the vector object
* *
* \returns Current capacity of the vector * \returns Current capacity of the vector
*/ */
EV_VEC_API u64 EV_VEC_API u64
ev_vec_capacity( ev_vec_capacity(
const void* vec_p); const ev_vec_t* v);
/*! /*!
* \brief Calls the free operation (if exists) on every element, then sets * \brief Calls the free operation (if exists) on every element, then sets
* the length to 0. * the length to 0.
* *
* \param vec_p A pointer to the vector object * \param v A pointer to the vector object
* *
* \returns 0 on success * \returns 0 on success
*/ */
EV_VEC_API u32 EV_VEC_API u32
ev_vec_clear( ev_vec_clear(
const void* vec_p); const ev_vec_t* v);
/*! /*!
* \brief Sets the length of the vector to `len`. * \brief Sets the length of the vector to `len`.
@@ -386,20 +350,20 @@ ev_vec_clear(
* For `svec`, if the `len` is more than the already allocated capacity, it is * For `svec`, if the `len` is more than the already allocated capacity, it is
* treated as an OOM. * treated as an OOM.
* *
* \param vec_p Reference to the vector object * \param v Reference to the vector object
* \param len The desired new length * \param len The desired new length
* *
* \returns `VEC_ERR_NONE` on success * \returns `VEC_ERR_NONE` on success
*/ */
EV_VEC_API ev_vec_error_t EV_VEC_API ev_vec_error_t
ev_vec_setlen( ev_vec_setlen(
void* vec_p, ev_vec_t *v,
u64 len); u64 len);
/*! /*!
* \brief Sets the capacity of the vector to `cap`. * \brief Sets the capacity of the vector to `cap`.
* *
* \param vec_p Reference to the vector object * \param v Reference to the vector object
* \param cap The desired new capacity * \param cap The desired new capacity
* *
* For stack-allocated vectors, `VEC_ERR_OOM` is returned * For stack-allocated vectors, `VEC_ERR_OOM` is returned
@@ -408,26 +372,25 @@ ev_vec_setlen(
*/ */
EV_VEC_API ev_vec_error_t EV_VEC_API ev_vec_error_t
ev_vec_setcapacity( ev_vec_setcapacity(
void* vec_p, ev_vec_t *v,
u64 cap); u64 cap);
/*! /*!
* \brief Grows the vector's capacity by a factor of `VEC_GROWTH_RATE` * \brief Grows the vector's capacity by a factor of `VEC_GROWTH_RATE`
* *
* \param vec_p Reference to the vector object * \param Reference to the vector object
* *
* \returns `VEC_ERR_NONE` on success * \returns `VEC_ERR_NONE` on success
*/ */
EV_VEC_API ev_vec_error_t EV_VEC_API ev_vec_error_t
ev_vec_grow( ev_vec_grow(
void* vec_p); ev_vec_t *v);
static const ev_vec_t EV_VEC_EMPTY = static const ev_vec_t EV_VEC_EMPTY =
(ev_vec(i32))&((struct { (ev_vec(i32))&((struct {
struct ev_vec_meta_t meta; struct ev_vec_meta_t meta;
EV_ALIGNAS(EV_ALIGNOF(i32)) i32 data[0]; EV_ALIGNAS(EV_ALIGNOF(i32)) i32 data[0];
}) { }) {
.meta._magic = EV_VEC_MAGIC,
.meta.length = 0, .meta.length = 0,
.meta.capacity = 0, .meta.capacity = 0,
.meta.typeData = TypeData(i32), .meta.typeData = TypeData(i32),
@@ -449,7 +412,6 @@ TYPEDATA_GEN(
#ifdef EV_VEC_IMPLEMENTATION #ifdef EV_VEC_IMPLEMENTATION
#undef EV_VEC_IMPLEMENTATION #undef EV_VEC_IMPLEMENTATION
#ifdef EV_VEC_API_CHECK #ifdef EV_VEC_API_CHECK
#define EV_VEC_CHECK(x) do { x; } while (0) #define EV_VEC_CHECK(x) do { x; } while (0)
#else #else
@@ -463,8 +425,7 @@ TYPEDATA_GEN(
((struct ev_vec_meta_t *)v) - 1 ((struct ev_vec_meta_t *)v) - 1
#define __ev_vec_getmeta(v) \ #define __ev_vec_getmeta(v) \
struct ev_vec_meta_t *metadata = ((struct ev_vec_meta_t *)(v)) - 1; \ struct ev_vec_meta_t *metadata = ((struct ev_vec_meta_t *)(v)) - 1;
assert(metadata->_magic == EV_VEC_MAGIC);
#define __ev_vec_syncmeta(v) \ #define __ev_vec_syncmeta(v) \
metadata = ((struct ev_vec_meta_t *)(v)) - 1; metadata = ((struct ev_vec_meta_t *)(v)) - 1;
@@ -489,7 +450,6 @@ ev_vec_init_impl(
struct ev_vec_meta_t *metadata = (struct ev_vec_meta_t *)v; struct ev_vec_meta_t *metadata = (struct ev_vec_meta_t *)v;
*metadata = (struct ev_vec_meta_t){ *metadata = (struct ev_vec_meta_t){
._magic = EV_VEC_MAGIC,
.length = 0, .length = 0,
.capacity = EV_VEC_INIT_CAP, .capacity = EV_VEC_INIT_CAP,
.allocationType = EV_VEC_ALLOCATION_TYPE_HEAP, .allocationType = EV_VEC_ALLOCATION_TYPE_HEAP,
@@ -501,10 +461,9 @@ ev_vec_init_impl(
i32 i32
ev_vec_find( ev_vec_find(
const void* vec_p, const ev_vec_t* v,
void *val) void *val)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if(metadata->typeData.equal_fn) { 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)) { for (void *elem = ev_vec_iter_begin(v); elem != ev_vec_iter_end(v); ev_vec_iter_next(v, &elem)) {
@@ -527,9 +486,8 @@ ev_vec_find(
void void
ev_vec_fini( ev_vec_fini(
void* vec_p) ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if (metadata->typeData.free_fn) { if (metadata->typeData.free_fn) {
@@ -547,10 +505,9 @@ ev_vec_fini(
int int
ev_vec_push_impl( ev_vec_push_impl(
void* vec_p, ev_vec_t *v,
void *val) void *val)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if (metadata->length == metadata->capacity) { if (metadata->length == metadata->capacity) {
@@ -574,16 +531,15 @@ ev_vec_push_impl(
void * void *
ev_vec_iter_begin( ev_vec_iter_begin(
const void* vec_p) const ev_vec_t* v)
{ {
return *(void**)vec_p; return *v;
} }
void * void *
ev_vec_iter_end( ev_vec_iter_end(
const void* vec_p) const ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
return ((char *)*v) + (metadata->typeData.size * metadata->length); return ((char *)*v) + (metadata->typeData.size * metadata->length);
@@ -591,21 +547,19 @@ ev_vec_iter_end(
void void
ev_vec_iter_next( ev_vec_iter_next(
const void* vec_p, const ev_vec_t* v,
void **iter) void **iter)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
*iter = ((char*)*iter) + metadata->typeData.size; *iter = ((char*)*iter) + metadata->typeData.size;
} }
EV_VEC_API u32 EV_VEC_API u32
ev_vec_append( ev_vec_append(
void* vec_p, ev_vec_t *v,
void **arr, void **arr,
u64 size) u64 size)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
size_t old_len = metadata->length; size_t old_len = metadata->length;
size_t req_len = old_len + size; size_t req_len = old_len + size;
@@ -622,50 +576,25 @@ ev_vec_append(
return (int)old_len; 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_error_t
ev_vec_pop( ev_vec_pop(
void* vec_p, ev_vec_t *v,
void *out) void *out)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if(metadata->length == 0) return EV_VEC_ERR_INVALID_OP;
void *elem = ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
if(out != NULL) { if(out != NULL) {
void *src = ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
if (metadata->typeData.copy_fn) { if (metadata->typeData.copy_fn) {
metadata->typeData.copy_fn(out, elem); metadata->typeData.copy_fn(out, src);
} else { } else {
memcpy(out, elem, metadata->typeData.size); 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);
} }
}
if (metadata->typeData.free_fn) {
metadata->typeData.free_fn(elem);
} }
metadata->length--; metadata->length--;
@@ -675,9 +604,8 @@ ev_vec_pop(
void * void *
ev_vec_last( ev_vec_last(
const void* vec_p) const ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if(metadata->length == 0) { if(metadata->length == 0) {
@@ -689,27 +617,24 @@ ev_vec_last(
u64 u64
ev_vec_len( ev_vec_len(
void* vec_p) const ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
return metadata->length; return metadata->length;
} }
u64 u64
ev_vec_capacity( ev_vec_capacity(
const void* vec_p) const ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
return metadata->capacity; return metadata->capacity;
} }
u32 u32
ev_vec_clear( ev_vec_clear(
const void* vec_p) const ev_vec_t* v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if (metadata->typeData.free_fn) { if (metadata->typeData.free_fn) {
@@ -725,15 +650,11 @@ ev_vec_clear(
ev_vec_error_t ev_vec_error_t
ev_vec_setlen( ev_vec_setlen(
void* vec_p, ev_vec_t *v,
u64 len) u64 len)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
while(metadata->length > len)
ev_vec_pop(vec_p, NULL);
while(len > metadata->capacity) { while(len > metadata->capacity) {
ev_vec_error_t grow_err = ev_vec_grow(v); ev_vec_error_t grow_err = ev_vec_grow(v);
if(grow_err) { if(grow_err) {
@@ -748,10 +669,9 @@ ev_vec_setlen(
ev_vec_error_t ev_vec_error_t
ev_vec_setcapacity( ev_vec_setcapacity(
void* vec_p, ev_vec_t *v,
u64 cap) u64 cap)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
if(metadata->allocationType == EV_VEC_ALLOCATION_TYPE_STACK) { if(metadata->allocationType == EV_VEC_ALLOCATION_TYPE_STACK) {
@@ -762,10 +682,6 @@ ev_vec_setcapacity(
return EV_VEC_ERR_NONE; return EV_VEC_ERR_NONE;
} }
if(metadata->length > cap) {
ev_vec_setlen(vec_p, cap);
}
void *buf = ((char *)(*v) - sizeof(struct ev_vec_meta_t)); void *buf = ((char *)(*v) - sizeof(struct ev_vec_meta_t));
void *tmp = realloc(buf, sizeof(struct ev_vec_meta_t) + (cap * metadata->typeData.size)); void *tmp = realloc(buf, sizeof(struct ev_vec_meta_t) + (cap * metadata->typeData.size));
@@ -785,12 +701,10 @@ ev_vec_setcapacity(
ev_vec_error_t ev_vec_error_t
ev_vec_grow( ev_vec_grow(
void* vec_p) ev_vec_t *v)
{ {
ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
u64 new_cap = max(EV_VEC_MIN_CAPACITY, metadata->capacity * EV_VEC_GROWTH_RATE); return ev_vec_setcapacity(v, metadata->capacity * EV_VEC_GROWTH_RATE);
return ev_vec_setcapacity(v, new_cap);
} }
#endif #endif
+22
View 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
View File
@@ -0,0 +1,4 @@
[binaries]
c = 'clang.exe'
c_ld = 'lld'
cpp = 'clang++.exe'
+9 -31
View File
@@ -1,24 +1,8 @@
project('evol-headers', 'c', project('evol-headers', 'c',
default_options : [ default_options : [ 'c_std=gnu23' ])
'c_std=c23',
# 'warning_level=everything',
# 'werror=true'
],
meson_version: '>=1.1',
)
headers_include = include_directories('.') headers_include = include_directories('.')
disabled_warnings = {
'clang': [
'unused-macros',
'reserved-macro-identifier',
'pre-c11-compat',
'pre-c23-compat',
]
}
evh_c_args = [] evh_c_args = []
buildtype = get_option('buildtype') buildtype = get_option('buildtype')
if buildtype == 'debug' if buildtype == 'debug'
@@ -36,36 +20,30 @@ elif cc.get_id() == 'clang'
evh_c_args += '-DEV_CC_CLANG=1' evh_c_args += '-DEV_CC_CLANG=1'
endif endif
foreach w:disabled_warnings[cc.get_id()]
evh_c_args += '-Wno-'+w
endforeach
# All other targets should follow the same template # All other targets should follow the same template
str_lib = static_library('ev_str', files('buildfiles/ev_str.c'), c_args: evh_c_args) 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) 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) 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) str_dep = declare_dependency(link_with: str_lib, include_directories: headers_include)
vec_dep = declare_dependency(link_with: vec_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) 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( headers_dep = declare_dependency(
dependencies: [ dependencies: [
str_dep, str_dep,
vec_dep, vec_dep,
helpers_dep, helpers_dep,
log_dep
] ]
) )
meson.override_dependency('ev_vec', vec_dep) # Tests
meson.override_dependency('ev_str', str_dep) str_test = executable('str_test', 'str_test.c', dependencies: [str_dep], c_args: evh_c_args)
meson.override_dependency('ev_helpers', helpers_dep) test('evstr', str_test)
meson.override_dependency('ev_log', log_dep)
meson.override_dependency('evol-headers', headers_dep)
if get_option('build_tests') if meson.version().version_compare('>= 0.54.0')
subdir('tests') 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 endif
-1
View File
@@ -1 +0,0 @@
option('build_tests', type: 'boolean', value: true, description: 'Build the tests')
+81
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;
}
-7
View File
@@ -1,7 +0,0 @@
tests = [
]
foreach t : tests
exec = executable(t, t+'.c', include_directories: headers_include, c_args: evh_c_args)
test(t, exec, suite: 'hash')
endforeach
-9
View File
@@ -1,9 +0,0 @@
#define EV_LOG_IMPLEMENTATION
#include "ev_log.h"
int main()
{
ev_log_trace("Trace Log");
return 0;
}
-8
View File
@@ -1,8 +0,0 @@
tests = [
'basic_log',
]
foreach t : tests
exec = executable(t, t+'.c', dependencies: [log_dep], c_args: evh_c_args)
test(t, exec, suite: 'log')
endforeach
-23
View File
@@ -1,23 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
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);
return 0;
}
-15
View File
@@ -1,15 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("Hello, this is me saying `Hello` like someone who says 'Hello'");
assert(evstring_findAll(text, evstr("Hello"), NULL) == 3);
assert(evstring_findAll(evstr("abc"), evstr("abc"), NULL) == 1);
assert(evstring_findAll(evstr("abcx"), evstr("abc"), NULL) == 1);
return 0;
}
-18
View File
@@ -1,18 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring_view search_results[1];
evstring text = evstr("abc");
evstring query = evstr("abc");
assert(evstring_findAll(text, query, search_results) == 1);
assert(search_results[0].data == text);
assert(search_results[0].len == 3);
assert(search_results[0].offset == 0);
return 0;
}
-16
View File
@@ -1,16 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring_view search_results[1];
evstring text = evstr("Hello, this is me saying `Hello` like someone who says 'Hello'");
assert(evstring_findAll(text, evstr(""), search_results) == 0);
assert(evstring_findAll(text, evstr("Goodbye"), search_results) == 0);
assert(evstring_findAll(evstr("ab"), evstr("abc"), search_results) == 0);
return 0;
}
-23
View File
@@ -1,23 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring_view search_results[2];
evstring text = evstr("aaa");
evstring query = evstr("aa");
assert(evstring_findAll(text, query, search_results) == 2);
assert(search_results[0].data == text);
assert(search_results[0].len == 2);
assert(search_results[0].offset == 0);
assert(search_results[1].data == text);
assert(search_results[1].len == 2);
assert(search_results[1].offset == 1);
return 0;
}
-18
View File
@@ -1,18 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring_view search_results[1];
evstring text = evstr("abcx");
evstring query = evstr("abc");
assert(evstring_findAll(text, query, search_results) == 1);
assert(search_results[0].data == text);
assert(search_results[0].len == 3);
assert(search_results[0].offset == 0);
return 0;
}
-17
View File
@@ -1,17 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("abc");
evstring query = evstr("");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 0);
assert(match.offset == ~0ull);
return 0;
}
-17
View File
@@ -1,17 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("");
evstring query = evstr("a");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 0);
assert(match.offset == ~0ull);
return 0;
}
-16
View File
@@ -1,16 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("aab");
evstring query = evstr("ab");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 2);
assert(match.offset == 1);
return 0;
}
@@ -1,16 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("aaab");
evstring query = evstr("aab");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 3);
assert(match.offset == 1);
return 0;
}
-17
View File
@@ -1,17 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("ab");
evstring query = evstr("abc");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 0);
assert(match.offset == ~0ull);
return 0;
}
-27
View File
@@ -1,27 +0,0 @@
tests = [
'stack_global_heap',
'slice',
'push_variants',
'new_format',
'replace_first',
'find_all',
'find_all_exact_match',
'find_all_short_suffix',
'find_all_count_only',
'find_all_no_matches',
'find_all_overlapping',
'push_fmt_float',
'find_first_mismatch',
'find_first_overlapping_prefix',
'stack_get_space',
'overlapping_push',
'find_first_empty_query',
'find_first_query_too_long',
'find_first_empty_text',
'replace_first_query_too_long',
]
foreach t : tests
exec = executable(t, t+'.c', dependencies: [str_dep], c_args: evh_c_args)
test(t, exec, suite: 'str')
endforeach
-19
View File
@@ -1,19 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
evstring source = evstr("Stack 'Hello, World!'");
evstring_view view = evstring_slice(source, 0, -1);
evstring str_fmt = evstring_new("%d, %d, %.*s", 1, 0, view.len, view.data + view.offset);
assert(str_fmt != NULL);
assert(strcmp(str_fmt, "1, 0, Stack 'Hello, World!'") == 0);
evstring_free(str_fmt);
return 0;
}
-19
View File
@@ -1,19 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
evstring s = evstring_newFromStr("abc");
assert(s != NULL);
evstring_error_t err = evstring_pushStr(&s, s);
assert(err == EV_STR_ERR_NONE);
assert(strcmp(s, "abcabc") == 0);
evstring_free(s);
return 0;
}
-25
View File
@@ -1,25 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
evstring heap_str = evstring_new("Heap 'Hello, World!'");
assert(heap_str != NULL);
evstring_error_t res = evstring_push(&heap_str, "%.05f", 1.0f);
assert(res == EV_STR_ERR_NONE);
assert(evstring_getLength(heap_str) == 27);
assert(strcmp(heap_str, "Heap 'Hello, World!'1.00000") == 0);
res = evstring_push(&heap_str, "Something");
assert(res == EV_STR_ERR_NONE);
assert(evstring_getLength(heap_str) == 36);
assert(strcmp(heap_str, "Heap 'Hello, World!'1.00000Something") == 0);
evstring_free(heap_str);
return 0;
}
-29
View File
@@ -1,29 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
evstring heap_str = evstring_new("Heap 'Hello, World!'");
assert(heap_str != NULL);
evstring_error_t push_str_res = evstring_push(&heap_str, "Hello, Sisyphus! %f", 0.001f);
assert(push_str_res == EV_STR_ERR_NONE);
assert(strcmp(heap_str, "Heap 'Hello, World!'Hello, Sisyphus! 0.001000") == 0);
evstring_error_t push_char_res = evstring_push(&heap_str, (char)'X');
assert(push_char_res == EV_STR_ERR_NONE);
assert(strcmp(heap_str, "Heap 'Hello, World!'Hello, Sisyphus! 0.001000X") == 0);
evstring source = evstr("Stack 'Hello, World!'");
evstring_view view = evstring_slice(source, 0, -1);
evstring_error_t push_view_res = evstring_push(&heap_str, view);
assert(push_view_res == EV_STR_ERR_NONE);
assert(strcmp(heap_str, "Heap 'Hello, World!'Hello, Sisyphus! 0.001000XStack 'Hello, World!'") == 0);
evstring_free(heap_str);
return 0;
}
-20
View File
@@ -1,20 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
evstring text = evstring_new("Hello, Hello!");
assert(text != NULL);
evstring rep_str = evstring_replaceFirst(text, evstr("Hello"), evstr("Bye"));
assert(rep_str != NULL);
assert(strcmp(rep_str, "Bye, Hello!") == 0);
evstring_free(rep_str);
evstring_free(text);
return 0;
}
@@ -1,18 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring text = evstr("ab");
evstring replacement = evstr("x");
evstring query = evstr("abc");
evstring result = evstring_replaceFirst(text, query, replacement);
assert(EV_EQUAL(evstring)(&result, &text));
evstring_free(result);
return 0;
}
-24
View File
@@ -1,24 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
int main(void)
{
const evstring stack_str = evstr("Stack 'Hello, World!'");
evstring_view view = evstring_slice(stack_str, 0, -1);
assert(view.data == stack_str);
assert(view.offset == 0);
assert(view.len == evstring_getLength(stack_str));
evstring heap_str = evstring_new(view);
assert(heap_str != NULL);
assert(strcmp(heap_str, stack_str) == 0);
assert(evstring_getLength(heap_str) == evstring_getLength(stack_str));
evstring_free(heap_str);
return 0;
}
-12
View File
@@ -1,12 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
int main(void)
{
evstring stack_str = evstr("abc");
assert(evstring_getSpace(stack_str) == 0);
return 0;
}
-26
View File
@@ -1,26 +0,0 @@
#define EV_STR_IMPLEMENTATION
#include "ev_str.h"
#include <assert.h>
#include <string.h>
static evstring global_str = evstr("Global 'Hello, World!'");
int main(void)
{
const evstring stack_str = evstr("Stack 'Hello, World!'");
assert(strcmp(stack_str, "Stack 'Hello, World!'") == 0);
assert(evstring_getLength(stack_str) == 21);
assert(strcmp(global_str, "Global 'Hello, World!'") == 0);
assert(evstring_getLength(global_str) == 22);
evstring heap_str = evstring_new("Heap 'Hello, World!'");
assert(heap_str != NULL);
assert(strcmp(heap_str, "Heap 'Hello, World!'") == 0);
assert(evstring_getLength(heap_str) == 20);
evstring_free(heap_str);
return 0;
}
-8
View File
@@ -1,8 +0,0 @@
tests = [
'tostr',
]
foreach t : tests
exec = executable(t, t+'.c', include_directories: headers_include, c_args: evh_c_args)
test(t, exec, suite: 'types')
endforeach
-12
View File
@@ -1,12 +0,0 @@
tests = [
'zero_cap_grow',
'reducecap_updatelen',
'reducecap_free_elems',
'reducelen_free_elems',
'pop_out_frees_vector_owned_elem',
]
foreach t : tests
exec = executable(t, t+'.c', dependencies: [vec_dep], c_args: evh_c_args)
test(t, exec, suite: 'vec')
endforeach
@@ -1,55 +0,0 @@
#define EV_VEC_IMPLEMENTATION
#include "ev_vec.h"
#include <assert.h>
#include <stdlib.h>
static int free_calls = 0;
typedef struct OwningInt {
int *ptr;
} OwningInt;
DEFINE_COPY_FUNCTION(OwningInt, Default)
{
dst->ptr = malloc(sizeof(*dst->ptr));
assert(dst->ptr != NULL);
*dst->ptr = *src->ptr;
}
DEFINE_FREE_FUNCTION(OwningInt, Default)
{
assert(self->ptr != NULL);
free(self->ptr);
self->ptr = NULL;
free_calls++;
}
TYPEDATA_GEN(OwningInt, COPY(Default), FREE(Default));
int main(void)
{
ev_vec(OwningInt) v = ev_vec_init(OwningInt);
assert(v != NULL);
OwningInt original = { .ptr = malloc(sizeof(*original.ptr)) };
assert(original.ptr != NULL);
*original.ptr = 42;
assert(ev_vec_push_impl(&v, &original) == 0);
free(original.ptr);
OwningInt out = {0};
assert(ev_vec_pop(&v, &out) == EV_VEC_ERR_NONE);
assert(out.ptr != NULL);
assert(*out.ptr == 42);
FREE_FUNCTION(OwningInt, Default)(&out);
/* Popping with an output copy transfers no pointer from the vector element.
The vector's own deep-copied element must still be destroyed. */
assert(free_calls == 2);
ev_vec_fini(&v);
return 0;
}
-28
View File
@@ -1,28 +0,0 @@
#define EV_VEC_IMPLEMENTATION
#include "ev_vec.h"
#include <assert.h>
static int free_calls = 0;
static void count_free(void *self)
{
(void)self;
free_calls++;
}
int main(void)
{
ev_vec(i32) v = ev_vec_init(i32, free = count_free);
assert(v != NULL);
for(i32 i = 0; i < 5; i++) {
assert(ev_vec_push_impl(&v, &i) >= 0);
}
free_calls = 0;
assert(ev_vec_setcapacity(&v, 3) == EV_VEC_ERR_NONE);
assert(free_calls == 2);
ev_vec_fini(&v);
}
-21
View File
@@ -1,21 +0,0 @@
#define EV_VEC_IMPLEMENTATION
#include "ev_vec.h"
#include <assert.h>
int main(void)
{
ev_vec(i32) v = ev_vec_init(i32);
assert(v != NULL);
for(i32 i = 0; i < 5; i++) {
assert(ev_vec_push_impl(&v, &i) >= 0);
}
ev_vec_error_t err = ev_vec_setcapacity(&v, 2);
assert(err != EV_VEC_ERR_NONE || ev_vec_len(&v) <= ev_vec_capacity(&v));
ev_vec_fini(&v);
return 0;
}
-25
View File
@@ -1,25 +0,0 @@
#define EV_VEC_IMPLEMENTATION
#include "ev_vec.h"
#include <assert.h>
static int free_calls = 0;
static void count_free(void *self)
{
(void)self;
free_calls++;
}
int main(void)
{
ev_vec(i32) v = ev_vec_init(i32, free = count_free);
assert(v != NULL);
free_calls = 0;
assert(ev_vec_setlen(&v, 3) == EV_VEC_ERR_NONE);
assert(ev_vec_setlen(&v, 1) == EV_VEC_ERR_NONE);
assert(free_calls == 2);
ev_vec_fini(&v);
}
-19
View File
@@ -1,19 +0,0 @@
#define EV_VEC_IMPLEMENTATION
#include "ev_vec.h"
#include <assert.h>
int main(void)
{
ev_vec(i32) v = ev_vec_init(i32);
assert(v != NULL);
assert(ev_vec_setcapacity(&v, 0) == EV_VEC_ERR_NONE);
assert(ev_vec_capacity(&v) == 0);
assert(ev_vec_grow(&v) == EV_VEC_ERR_NONE);
assert(ev_vec_capacity(&v) > 0);
ev_vec_fini(&v);
return 0;
}
-5
View File
@@ -1,5 +0,0 @@
subdir('ev_hash')
subdir('ev_log')
subdir('ev_str')
subdir('ev_types')
subdir('ev_vec')