18 Commits

Author SHA1 Message Date
mo7sen 89b34bf63c Fixed issue with ev_vec_push macros
Run tests / Run tests (push) Has been cancelled
2026-05-14 23:42:35 +03:00
mo7sen e3d47ebc67 Renamed build_evh_tests option to build_tests
Run tests / Run tests (push) Successful in 10s
2026-05-08 14:28:10 +03:00
mo7sen d403ebb0df Added option to disable building of tests
Run tests / Run tests (push) Successful in 10s
2026-05-07 03:13:49 +03:00
mo7sen 32c2134245 Fixed incorrect condition breaking compilation with clang on windows
Run tests / Run tests (push) Successful in 11s
2026-05-06 14:58:36 +03:00
mo7sen 0bf963b21c Updated run_tests.yaml
Run tests / Run tests (push) Successful in 10s
2026-05-05 18:31:32 +03:00
mo7sen 0886535722 Made numeric types more stable
Run tests / Run tests (push) Successful in 44s
2026-05-05 15:10:08 +03:00
mo7sen 7b8bac2b55 Fixed + disabled some warnings
Run tests / Run tests (push) Successful in 11s
2026-05-04 22:53:56 +03:00
mo7sen 2c74b727ef Added more tests + fixed evstr issues
Run tests / Run tests (push) Successful in 11s
2026-05-04 21:44:32 +03:00
mo7sen 7c4768a3dd Fixed overlapping push in ev_str
Run tests / Run tests (push) Successful in 10s
2026-05-04 21:07:10 +03:00
mo7sen 82abc8fee5 Fixed non-memory related failing tests
Run tests / Run tests (push) Failing after 9s
2026-05-04 20:42:46 +03:00
mo7sen 396e2c1e52 Changed evstring to use capacity instead of size
Run tests / Run tests (push) Failing after 9s
2026-05-03 23:52:41 +03:00
mo7sen 0f62e962c9 Fixed str - find_first_empty_query
Run tests / Run tests (push) Failing after 9s
2026-05-03 23:30:34 +03:00
mo7sen e7c6cc507c Fixed ev_vec_pop not always free'ing the popped element
Run tests / Run tests (push) Failing after 9s
2026-05-03 23:23:47 +03:00
mo7sen 8b6c7ec42a Fixed murmur hash function signature and removed seed_high_bits test as it's no longer relevant
Run tests / Run tests (push) Failing after 9s
2026-05-03 23:09:07 +03:00
mo7sen a0f16f8ca0 Disabled coverage reporting
Run tests / Run tests (push) Failing after 9s
2026-05-03 20:30:01 +03:00
mo7sen 81a5b4a3c8 Added more tests
Run tests / Run tests (push) Failing after 6s
2026-05-03 20:21:33 +03:00
mo7sen 96131f8188 Added coverage report generation to CI + always running memory testing
Run tests / Run tests (push) Failing after 7s
2026-05-03 20:10:54 +03:00
mo7sen a4fa298d95 Moved tests + Added more tests + Added memory testing to actions
Run tests / Run tests (push) Failing after 6s
2026-05-03 20:07:16 +03:00
44 changed files with 808 additions and 234 deletions
+18 -5
View File
@@ -13,12 +13,25 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Configure - name: Configure
run: meson setup build run: meson setup build
- name: Run tests # run: meson setup -Db_coverage=true build
- name: Run Tests
run: meson test -C build run: meson test -C build
- name: Upload Meson Logs - name: Run Memory Tests
if: always() if: always()
uses: christopherHX/gitea-upload-artifact@v4 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: with:
name: meson-logs path: |
path: build/meson-logs/ build/meson-logs/meson-log.txt
build/meson-logs/meson-setup.txt
build/meson-logs/testlog.txt
archive: false
+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, u64 seed); u64 ev_hash_murmur3(const void *data, u32 len, u32 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, u64 seed) u64 ev_hash_murmur3(const void *data, u32 len, u32 seed)
{ {
u64 out[2]; u64 out[2];
MurmurHash3_x64_128(data, len, (u32)seed, out); MurmurHash3_x64_128(data, len, (u32)seed, out);
+10 -8
View File
@@ -1,15 +1,17 @@
#ifndef EV_HEADERS_INTERNAL_H #ifndef EV_HEADERS_INTERNAL_H
#define EV_HEADERS_INTERNAL_H #define EV_HEADERS_INTERNAL_H
typedef signed char i8; #include <stdint.h>
typedef short int i16;
typedef int i32;
typedef long long int i64;
typedef unsigned char u8; typedef int8_t i8;
typedef unsigned short int u16; typedef int16_t i16;
typedef unsigned int u32; typedef int32_t i32;
typedef unsigned long long int u64; typedef int64_t i64;
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;
+10 -10
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; };
+98 -49
View File
@@ -43,18 +43,25 @@
#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 size; u64 capacity;
enum { enum {
EV_STR_ALLOCATION_TYPE_STACK, EV_STR_ALLOCATION_TYPE_STACK,
EV_STR_ALLOCATION_TYPE_HEAP EV_STR_ALLOCATION_TYPE_HEAP
@@ -67,7 +74,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.size = len, \ .meta.capacity = len, \
.meta.allocationType = EV_STR_ALLOCATION_TYPE_STACK, \ .meta.allocationType = EV_STR_ALLOCATION_TYPE_STACK, \
.data = str \ .data = str \
}).data }).data
@@ -120,6 +127,11 @@ 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,
@@ -171,11 +183,6 @@ 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,
@@ -211,7 +218,16 @@ TYPEDATA_GEN(evstring,
EQUAL(Default), EQUAL(Default),
COPY(Default), COPY(Default),
FREE(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)
@@ -249,9 +265,10 @@ evstring_new_impl(
const char *data, const char *data,
u64 len) u64 len)
{ {
u64 size = sizeof(struct evstr_meta_t) + len + 1; u64 str_cap = len + 1;
u64 alloc_size = sizeof(struct evstr_meta_t) + str_cap;
void *p = ev_str_malloc(size); void *p = ev_str_malloc(alloc_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;
@@ -260,7 +277,7 @@ EV_DEBUG
meta->magic = EV_STR_evstring_MAGIC; meta->magic = EV_STR_evstring_MAGIC;
) )
meta->length = len; meta->length = len;
meta->size = size; meta->capacity = str_cap;
meta->allocationType = EV_STR_ALLOCATION_TYPE_HEAP; meta->allocationType = EV_STR_ALLOCATION_TYPE_HEAP;
evstring s = (evstring)(meta + 1); evstring s = (evstring)(meta + 1);
@@ -281,10 +298,11 @@ evstring_newFmt_v(
{ {
va_list test; va_list test;
va_copy(test, args); va_copy(test, args);
i32 len = vsnprintf(NULL, 0, fmt, test); i32 expected_len = vsnprintf(NULL, 0, fmt, test);
if(len < 0) { if(expected_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);
@@ -343,9 +361,9 @@ evstring_getLength(
} }
evstring_error_t evstring_error_t
evstring_setSize( evstring_setCapacity(
evstring *s, evstring *s,
size_t newsize) size_t new_capacity)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
struct evstr_meta_t *meta = META(*s); struct evstr_meta_t *meta = META(*s);
@@ -353,12 +371,12 @@ evstring_setSize(
return EV_STR_ERR_OOM; return EV_STR_ERR_OOM;
} }
if(meta->size == newsize) { if(meta->capacity == new_capacity) {
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) + newsize); void *tmp = ev_str_realloc(buf, sizeof(struct evstr_meta_t) + new_capacity);
if (!tmp) { if (!tmp) {
return EV_STR_ERR_OOM; return EV_STR_ERR_OOM;
@@ -370,7 +388,7 @@ evstring_setSize(
*s = (evstring)(meta+1); *s = (evstring)(meta+1);
} }
meta->size = newsize; meta->capacity = new_capacity;
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
@@ -379,7 +397,8 @@ evstring_grow(
evstring *s) evstring *s)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
return evstring_setSize(s, META(*s)->size * EV_STR_GROWTH_FACTOR); u64 new_cap = max(EV_STR_MIN_CAPACITY, META(*s)->capacity * EV_STR_GROWTH_FACTOR);
return evstring_setCapacity(s, new_cap);
} }
evstring_error_t evstring_error_t
@@ -393,8 +412,8 @@ evstring_setLength(
return EV_STR_ERR_NONE; return EV_STR_ERR_NONE;
} }
u64 required_size = sizeof(struct evstr_meta_t) + newlen + 1; u64 required_capacity = newlen + 1;
while(required_size > meta->size) { while(required_capacity > meta->capacity) {
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;
@@ -430,6 +449,19 @@ 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(
@@ -440,9 +472,18 @@ 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_size = sizeof(struct evstr_meta_t) + meta->length + sz + 1; u64 required_capacity = meta->length + sz + 1;
while(required_size > meta->size) { // `<=` because of the null terminator while(required_capacity > meta->capacity) { // `<=` 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;
@@ -520,7 +561,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->size - meta->length - 1 - sizeof(struct evstr_meta_t); return meta->capacity - meta->length - 1;
} }
evstring_error_t evstring_error_t
@@ -529,33 +570,34 @@ evstring_addSpace(
u64 space) u64 space)
{ {
evstr_asserttype(*s); evstr_asserttype(*s);
return evstring_setSize(s, META(*s)->size + space); return evstring_setCapacity(s, META(*s)->capacity + 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
}; };
for(u64 i = text.offset; i < text.offset + text.len; i++) { if(query.len == 0 || query.len > text.len)
if(text.data[i] == query.data[query.offset + found_progress]) return result;
found_progress++;
else for(u64 l = text.offset; l <= text.offset + text.len - query.len; l++)
found_progress = 0; {
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;
} }
@@ -566,7 +608,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
@@ -685,18 +727,25 @@ 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);
v.len != 0; for(u64 l = 0; l <= text_len - query_len; l++)
v = __evstring_findFirst_impl( {
evstring_slice(text, v.offset + v.len, -1), evstring_view curr_view = {
evstring_slice(query, 0, -1))) { .data = text,
if(!check_run) { .len = query_len,
results[count] = v; .offset = l
} };
if(EV_EQUAL(evstring_view)(&curr_view, &query_view))
{
if(results) results[count] = curr_view;
count++; count++;
} }
}
return count; return count;
} }
+7 -6
View File
@@ -80,9 +80,10 @@ 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), \
@@ -91,8 +92,8 @@ 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_WARNING_POP(); \ EV_UNUSED static T EV_OVERRIDE_VAR(T); \
EV_UNUSED static T EV_OVERRIDE_VAR(T) EV_WARNING_POP()
#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_CAT(EV_CAT(__EV_,EV_HEAD __VA_ARGS__),_FN)(T, EV_TAIL __VA_ARGS__)
@@ -152,6 +153,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
+32 -13
View File
@@ -6,7 +6,7 @@
#include "ev_types.h" #include "ev_types.h"
#include "ev_numeric.h" #include "ev_numeric.h"
#if !EV_OS_WINDOWS #if !EV_CC_MSVC
#include <string.h> #include <string.h>
#endif #endif
@@ -34,6 +34,14 @@
#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
@@ -178,8 +186,8 @@ 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 vec_p A pointer to the vector that we want an iterator for
@@ -304,6 +312,10 @@ ev_vec_dup(
* 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
* 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 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
@@ -643,19 +655,18 @@ ev_vec_pop(
if(metadata->length == 0) return EV_VEC_ERR_INVALID_OP; if(metadata->length == 0) return EV_VEC_ERR_INVALID_OP;
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); void *elem = ((char *)*v) + ((metadata->length-1) * metadata->typeData.size);
if(out != NULL) {
if (metadata->typeData.copy_fn) {
metadata->typeData.copy_fn(out, elem);
} else {
memcpy(out, elem, metadata->typeData.size);
}
}
if (metadata->typeData.free_fn) { if (metadata->typeData.free_fn) {
metadata->typeData.free_fn(elem); metadata->typeData.free_fn(elem);
} }
}
metadata->length--; metadata->length--;
@@ -720,6 +731,9 @@ ev_vec_setlen(
ev_vec_t* v = (ev_vec_t*)vec_p; 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,6 +762,10 @@ 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));
@@ -771,7 +789,8 @@ ev_vec_grow(
{ {
ev_vec_t* v = (ev_vec_t*)vec_p; ev_vec_t* v = (ev_vec_t*)vec_p;
__ev_vec_getmeta(*v) __ev_vec_getmeta(*v)
return ev_vec_setcapacity(v, metadata->capacity * EV_VEC_GROWTH_RATE); u64 new_cap = max(EV_VEC_MIN_CAPACITY, metadata->capacity * EV_VEC_GROWTH_RATE);
return ev_vec_setcapacity(v, new_cap);
} }
#endif #endif
+28 -14
View File
@@ -1,8 +1,24 @@
project('evol-headers', 'c', project('evol-headers', 'c',
default_options : [ 'c_std=c23' ]) default_options : [
'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'
@@ -20,6 +36,10 @@ 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)
@@ -40,18 +60,12 @@ headers_dep = declare_dependency(
] ]
) )
# Tests meson.override_dependency('ev_vec', vec_dep)
str_test = executable('str_test', 'str_test.c', dependencies: [str_dep], c_args: evh_c_args) meson.override_dependency('ev_str', str_dep)
test('evstr', str_test) meson.override_dependency('ev_helpers', helpers_dep)
vec_test = executable('vec_test', 'vec_test.c', dependencies: [vec_dep], c_args: evh_c_args) meson.override_dependency('ev_log', log_dep)
test('evvec', vec_test) meson.override_dependency('evol-headers', headers_dep)
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') if get_option('build_tests')
meson.override_dependency('ev_vec', vec_dep) subdir('tests')
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 endif
+1
View File
@@ -0,0 +1 @@
option('build_tests', type: 'boolean', value: true, description: 'Build the tests')
-106
View File
@@ -1,106 +0,0 @@
#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);
}
{ // Incorrectly handled mismatches
evstring text = evstr("aab");
evstring query = evstr("ab");
evstring_view match = evstring_findFirst(text, query);
assert(match.len == 2);
assert(match.offset == 1);
}
{ // Underflowing getSpace for stack strings
evstring stack_str = evstr("abc");
assert(evstring_getSpace(stack_str) == 0);
}
{ // Overlapping push
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;
}
+7
View File
@@ -0,0 +1,7 @@
tests = [
]
foreach t : tests
exec = executable(t, t+'.c', include_directories: headers_include, c_args: evh_c_args)
test(t, exec, suite: 'hash')
endforeach
+8
View File
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,23 @@
#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
@@ -0,0 +1,15 @@
#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
@@ -0,0 +1,18 @@
#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
@@ -0,0 +1,16 @@
#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
@@ -0,0 +1,23 @@
#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
@@ -0,0 +1,18 @@
#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
@@ -0,0 +1,17 @@
#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
@@ -0,0 +1,17 @@
#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
@@ -0,0 +1,16 @@
#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;
}
@@ -0,0 +1,16 @@
#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
@@ -0,0 +1,17 @@
#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
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,19 @@
#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
@@ -0,0 +1,19 @@
#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
@@ -0,0 +1,25 @@
#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
@@ -0,0 +1,29 @@
#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
@@ -0,0 +1,20 @@
#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;
}
@@ -0,0 +1,18 @@
#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
@@ -0,0 +1,24 @@
#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
@@ -0,0 +1,12 @@
#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
@@ -0,0 +1,26 @@
#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
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,55 @@
#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
@@ -0,0 +1,28 @@
#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
@@ -0,0 +1,21 @@
#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
@@ -0,0 +1,25 @@
#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
@@ -0,0 +1,19 @@
#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
@@ -0,0 +1,5 @@
subdir('ev_hash')
subdir('ev_log')
subdir('ev_str')
subdir('ev_types')
subdir('ev_vec')
-22
View File
@@ -1,22 +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;
}