stb style single header libs for basic utilities in C programs.
Note: DO NOT EVER BUILD DYNAMIC OR STATIC LIBS FOR ANY OF THE SINGLE HEADER LIBS Always build these single header libs from source in whatever project uses them as correctness of code in this libs is done via asserts which are normally turned off for release builds (via -DZDX_ASSERT_DISABLE) and only enabled in DEBUG builds and thus if packaged as a dynamic or static library which means it's likely built in release mode all the asserts will be removed and the consumers of the library will have no protection against bad usage of the functions in that dynamic or static library
To use any library in this repository:
- copy the header file into your project - for e.g., copy
zdx_da.h
- copy the util header file into your project -
zdx_util.h
- in one C file, do the following to include the implementation - for e.g., to use
zdx_da.h
#define ZDX_DA_IMPLEMENTATION
#include "<path to zdx_da.h>"
- in all other files, just a
#include <path to lib header>
should suffice - done!
You can find usage examples in tests/<lib>_test.c
- for e.g., zdx_da.h
usage can be found in tests/zdx_da_test.c
.
# make test_<lib name> or make test_<lib name>_dbg for debug build of tests
make test_zdx_da
# OR
make test_zdx_da_dbg
Notes on how to make a single header-file library can be found here.
This contains a (mostly) macro based dynamic array implementation.
It only works with gcc
and clang
for now as it uses statement expressions
.
It requires a container struct
with the following mandatory members:
size_t length
: will hold dynamic array lengthsize_t capacity
: will hold the capacity of the dynamic array as multiples of items<type> *items
: this will hold all the items of type<type>
pushed into the dynamic array.<type>
can be anything you want.
Other members can also be specified in the struct
alongside the above mandatory members.
For example, the following is a valid dynamic array container:
typedef struct {
char *name;
uint8_t age;
} Person;
typedef struct {
int i;
size_t length;
size_t capacity;
Person *items;
float f;
union {
uint8_t ui;
int8_t si;
}
} SomeStruct;
DA_ASSERT
- defaults toassert()
from<assert.h>
. Can be redefined if you'd like to not abort on assertion failureDA_RESIZE_FACTOR
- defaults to 2. Decides by what factor the capactiy of the dynamic array is scaled. It can be redefined.DA_MIN_CAPACITY
- defaults to 8. Can be redefined to control the minimum capacity of a dynamic array.
da_push(&container, ...elements)
- appends elements tocontainer.items
and returns the length after pushtypedef struct { int member1; struct { union { int16_t nested_member1; float nester_member2; } } member2; } Item; typedef struct { size_t length; size_t capacity; Item *items; char *tag; } da_t; da_t container = {0}; size_t len = da_push(&container, (Item){ .member1 = 80 }, (Item){ .member1 = 100, .member2.nested_member1 = "Hello!" }); assert(len == 2 == container.length);
da_pop(&container)
- pops the last element incontainer.items
and returns it
Item i = da_pop(&container); assert(i.member1 == 100); assert(container.length == 1);
da_deinit(&container)
-free()
scontainer.items
da_deinit(&container); assert(container.length == 0); assert(container.capacity == 0); assert(container.items == NULL);
This header contains utility macros and maybe utility functions in the future.
ZDX_LOG_LEVEL
-L_ERROR
(1),L_WARN
(2),L_INFO
(3)
-
assertm(condition, ...)
- asserts if condition is truthy. If falsy, it prints the message provided in...
tostderr
and callsabort()
assertm(moreReplHistory.capacity == 2, "Expected: 2, Received: %zu", moreReplHistory.capacity);
-
log(ZDX_LOG_LEVEL, ...args)
- prints logs with given level tostderr
.Logging can be disabled by flag
-DZDX_LOGS_DISABLE
.log(L_INFO, "%d tests passed. All ok!\n", 10);
-
dbg(...args)
- prints debug logs tostderr
.It's disabled by default and can be enabled by
-DZDX_TRACE_ENABLE
.dbg("Starting resizing: new capacity %zu", new_capacity);
-
bail(...args)
- prings...args
tostderr
and then callsexit(1)
bail("Oh no!");