retab everything to use tabs

This commit is contained in:
2025-12-03 19:38:43 +01:00
parent 1b33ace698
commit 9214b986ac
12 changed files with 473 additions and 443 deletions
+55 -55
View File
@@ -5,87 +5,87 @@
#include <stdbool.h> #include <stdbool.h>
void *borrow_allocator_alloc_func(borrow_allocator_t *this, size_t bytes) { void *borrow_allocator_alloc_func(borrow_allocator_t *this, size_t bytes) {
linked_allocation_node_t *node = malloc(sizeof(*this->head) + bytes); linked_allocation_node_t *node = malloc(sizeof(*this->head) + bytes);
if (node == NULL) { return NULL; } if (node == NULL) { return NULL; }
node->prev = NULL; node->prev = NULL;
node->next = this->head; node->next = this->head;
if (this->head != NULL) { if (this->head != NULL) {
assert(this->head->prev == NULL); assert(this->head->prev == NULL);
this->head->prev = node; this->head->prev = node;
} }
this->head = node; this->head = node;
return &node->data; return &node->data;
} }
void *borrow_allocator_resize_func(borrow_allocator_t *this, void *old_ptr, size_t bytes) { void *borrow_allocator_resize_func(borrow_allocator_t *this, void *old_ptr, size_t bytes) {
linked_allocation_node_t *old_node = PTR_FROM_FIELD_PTR(linked_allocation_node_t, data, old_ptr); linked_allocation_node_t *old_node = PTR_FROM_FIELD_PTR(linked_allocation_node_t, data, old_ptr);
linked_allocation_node_t *new_node = realloc(old_node, sizeof(*old_node) + bytes); linked_allocation_node_t *new_node = realloc(old_node, sizeof(*old_node) + bytes);
if (new_node == NULL) { return NULL; } if (new_node == NULL) { return NULL; }
if (this->head == old_node) { if (this->head == old_node) {
assert(new_node->prev == NULL); assert(new_node->prev == NULL);
this->head = new_node; this->head = new_node;
} }
if (new_node->prev != NULL) { new_node->prev->next = new_node; } if (new_node->prev != NULL) { new_node->prev->next = new_node; }
if (new_node->next != NULL) { new_node->next->prev = new_node; } if (new_node->next != NULL) { new_node->next->prev = new_node; }
return &new_node->data; return &new_node->data;
} }
// TODO: remove // TODO: remove
void borrow_allocator_free(borrow_allocator_t *this, void *old_ptr) { void borrow_allocator_free(borrow_allocator_t *this, void *old_ptr) {
linked_allocation_node_t *node = PTR_FROM_FIELD_PTR(linked_allocation_node_t, data, old_ptr); linked_allocation_node_t *node = PTR_FROM_FIELD_PTR(linked_allocation_node_t, data, old_ptr);
if (node->prev != NULL) { node->prev->next = node->next; } if (node->prev != NULL) { node->prev->next = node->next; }
if (node->next != NULL) { node->next->prev = node->prev; } if (node->next != NULL) { node->next->prev = node->prev; }
if (this->head == node) { if (this->head == node) {
assert(node->prev == NULL); assert(node->prev == NULL);
if (node->next != NULL) { assert(node->next->prev == NULL); } if (node->next != NULL) { assert(node->next->prev == NULL); }
this->head = node->next; this->head = node->next;
} }
free(node); free(node);
} }
void borrow_allocator_free_all(borrow_allocator_t *this) { void borrow_allocator_free_all(borrow_allocator_t *this) {
if (this->head == NULL) { if (this->head == NULL) {
return; return;
} }
assert(this->head->prev == NULL); assert(this->head->prev == NULL);
void *prev = NULL; void *prev = NULL;
for (linked_allocation_node_t *node = this->head; node != NULL; node = node->next) { for (linked_allocation_node_t *node = this->head; node != NULL; node = node->next) {
free(prev); free(prev);
prev = node; prev = node;
} }
free(prev); free(prev);
this->head = NULL; this->head = NULL;
} }
size_t borrow_allocator_count_allocations(borrow_allocator_t *this) { size_t borrow_allocator_count_allocations(borrow_allocator_t *this) {
size_t output = 0; size_t output = 0;
for (linked_allocation_node_t *node = this->head; node != NULL; node = node->next) { for (linked_allocation_node_t *node = this->head; node != NULL; node = node->next) {
output++; output++;
} }
return output; return output;
} }
static void *borrow_alloc_impl(void *this, size_t bytes) { static void *borrow_alloc_impl(void *this, size_t bytes) {
return borrow_allocator_alloc_func(this, bytes); return borrow_allocator_alloc_func(this, bytes);
} }
static void *borrow_resize_impl(void *this, void *old_ptr, size_t bytes) { static void *borrow_resize_impl(void *this, void *old_ptr, size_t bytes) {
return borrow_allocator_resize_func(this, old_ptr, bytes); return borrow_allocator_resize_func(this, old_ptr, bytes);
} }
static void borrow_reset(void *this) { static void borrow_reset(void *this) {
borrow_allocator_free_all(this); borrow_allocator_free_all(this);
} }
static const allocator_vtbl_t borrow_vtbl = { static const allocator_vtbl_t borrow_vtbl = {
.alloc = borrow_alloc_impl, .alloc = borrow_alloc_impl,
.resize = borrow_resize_impl, .resize = borrow_resize_impl,
.reset = borrow_reset, .reset = borrow_reset,
}; };
allocator_t allocator_from_borrow(borrow_allocator_t *this) { allocator_t allocator_from_borrow(borrow_allocator_t *this) {
return (allocator_t) { return (allocator_t) {
.this=this, .this=this,
.vtbl=&borrow_vtbl, .vtbl=&borrow_vtbl,
}; };
} }
+32 -32
View File
@@ -1,56 +1,56 @@
#include "cig.h" #include "cig.h"
void *buffer_allocator_alloc(buffer_allocator_t *this, size_t bytes) { void *buffer_allocator_alloc(buffer_allocator_t *this, size_t bytes) {
size_t address_of_new_data = (size_t) &this->data[this->size]; size_t address_of_new_data = (size_t) &this->data[this->size];
size_t offset = address_of_new_data % MAX_ALIGN; size_t offset = address_of_new_data % MAX_ALIGN;
size_t new_size = this->size + offset + bytes; size_t new_size = this->size + offset + bytes;
if (new_size > this->capacity) { if (new_size > this->capacity) {
return NULL; return NULL;
} }
this->size += offset; this->size += offset;
void *ptr = &this->data[this->size]; void *ptr = &this->data[this->size];
this->size = new_size; this->size = new_size;
return ptr; return ptr;
} }
void *buffer_allocator_resize(buffer_allocator_t *this, void *old_ptr, size_t bytes) { void *buffer_allocator_resize(buffer_allocator_t *this, void *old_ptr, size_t bytes) {
void *new_ptr = buffer_allocator_alloc(this, bytes); void *new_ptr = buffer_allocator_alloc(this, bytes);
if (new_ptr == NULL) { if (new_ptr == NULL) {
return NULL; return NULL;
} }
for (size_t i = 0; i < bytes; i++) { for (size_t i = 0; i < bytes; i++) {
unsigned char *new_ptr_b = (unsigned char *)new_ptr; unsigned char *new_ptr_b = (unsigned char *)new_ptr;
unsigned char *old_ptr_b = (unsigned char *)old_ptr; unsigned char *old_ptr_b = (unsigned char *)old_ptr;
new_ptr_b[i] = old_ptr_b[i]; new_ptr_b[i] = old_ptr_b[i];
} }
return new_ptr; return new_ptr;
} }
void buffer_allocator_reset(buffer_allocator_t *this) { void buffer_allocator_reset(buffer_allocator_t *this) {
this->size = 0; this->size = 0;
} }
static void *buffer_alloc_impl(void *this, size_t bytes) { static void *buffer_alloc_impl(void *this, size_t bytes) {
return buffer_allocator_alloc((buffer_allocator_t *)this, bytes); return buffer_allocator_alloc((buffer_allocator_t *)this, bytes);
} }
static void *buffer_resize_impl(void *this, void *old_ptr, size_t bytes) { static void *buffer_resize_impl(void *this, void *old_ptr, size_t bytes) {
return buffer_allocator_resize((buffer_allocator_t *)this, old_ptr, bytes); return buffer_allocator_resize((buffer_allocator_t *)this, old_ptr, bytes);
} }
static void buffer_reset_impl(void *this) { static void buffer_reset_impl(void *this) {
buffer_allocator_reset((buffer_allocator_t *)this); buffer_allocator_reset((buffer_allocator_t *)this);
} }
static const allocator_vtbl_t buffer_vtbl = { static const allocator_vtbl_t buffer_vtbl = {
.alloc = buffer_alloc_impl, .alloc = buffer_alloc_impl,
.resize = buffer_resize_impl, .resize = buffer_resize_impl,
.reset = buffer_reset_impl, .reset = buffer_reset_impl,
}; };
allocator_t buffer_allocator(buffer_allocator_t *this) { allocator_t allocator_from_buffer(buffer_allocator_t *this) {
return (allocator_t) { return (allocator_t) {
.this=this, .this=this,
.vtbl=&buffer_vtbl, .vtbl=&buffer_vtbl,
}; };
} }
+98 -68
View File
@@ -18,17 +18,17 @@ typedef union any_align { char c; int i; long l; long long ll; float f; double d
// Contains all operations an allocator can do. Similar interface to sdtlibs // Contains all operations an allocator can do. Similar interface to sdtlibs
// malloc, realloc and free. // malloc, realloc and free.
typedef struct allocator_vtbl { typedef struct allocator_vtbl {
void *(*alloc)(void *this, size_t bytes); void *(*alloc)(void *this, size_t bytes);
void *(*resize)(void *this, void *old_ptr, size_t bytes); void *(*resize)(void *this, void *old_ptr, size_t bytes);
void (*reset)(void *this); void (*reset)(void *this);
} allocator_vtbl_t; } allocator_vtbl_t;
// An instance of an allocator. // An instance of an allocator.
typedef struct allocator { typedef struct allocator {
// pointer to the behind-the-scenes data that an allocator may store. // pointer to the behind-the-scenes data that an allocator may store.
void *this; void *this;
// pointer to the method implementations of an allocator. // pointer to the method implementations of an allocator.
const allocator_vtbl_t *vtbl; const allocator_vtbl_t *vtbl;
} allocator_t; } allocator_t;
void *allocator_alloc_func(allocator_t this, size_t bytes, const char *file, int line); void *allocator_alloc_func(allocator_t this, size_t bytes, const char *file, int line);
@@ -37,29 +37,31 @@ void allocator_reset(allocator_t this);
#define allocator_alloc(this, bytes) allocator_alloc_func(this, bytes, __FILE__, __LINE__) #define allocator_alloc(this, bytes) allocator_alloc_func(this, bytes, __FILE__, __LINE__)
#define allocator_resize(this, old_ptr, bytes) allocator_resize_func(this, old_ptr, bytes, __FILE__, __LINE__) #define allocator_resize(this, old_ptr, bytes) allocator_resize_func(this, old_ptr, bytes, __FILE__, __LINE__)
// std_allocator /////////////////////////////////////////////////////////////// // forever_allocator ///////////////////////////////////////////////////////////
allocator_t forever_allocator(); allocator_t forever_allocator();
// buffer_allocator //////////////////////////////////////////////////////////// // buffer_allocator ////////////////////////////////////////////////////////////
typedef struct buffer_allocator { typedef struct buffer_allocator {
size_t size, capacity; size_t size, capacity;
uint8_t *data; uint8_t *data;
} buffer_allocator_t; } buffer_allocator_t;
#define buffer_allocator_create(CAPACITY) \ // TODO: name stack value or something to signal what is happening here!
#define buffer_allocator_value(CAPACITY) \
((buffer_allocator_t){ \ ((buffer_allocator_t){ \
.size = 0, .capacity = CAPACITY, .data = (uint8_t[CAPACITY]){0}}) .size = 0, .capacity = CAPACITY, .data = (uint8_t[CAPACITY]){0}})
allocator_t buffer_allocator(buffer_allocator_t *this); allocator_t allocator_from_buffer(buffer_allocator_t *this);
// borrow_allocator //////////////////////////////////////////////////////////// // borrow_allocator ////////////////////////////////////////////////////////////
typedef struct linked_allocation_node { typedef struct linked_allocation_node {
struct linked_allocation_node *next; struct linked_allocation_node *next;
struct linked_allocation_node *prev; struct linked_allocation_node *prev;
any_align_t data[]; any_align_t data[];
} linked_allocation_node_t; } linked_allocation_node_t;
typedef struct borrow_allocator { typedef struct borrow_allocator {
linked_allocation_node_t *head; linked_allocation_node_t *head;
} borrow_allocator_t; } borrow_allocator_t;
#define borrow_allocator_value() ((borrow_allocator_t){.head=NULL}) #define borrow_allocator_value() ((borrow_allocator_t){.head=NULL})
@@ -76,67 +78,94 @@ allocator_t allocator_from_borrow(borrow_allocator_t *this);
// with_borrow(foos_allocator) {bar = foo(foos_allocator, my_allocator); } Using // with_borrow(foos_allocator) {bar = foo(foos_allocator, my_allocator); } Using
// the return a keyword in the statement following this macro will cause a // the return a keyword in the statement following this macro will cause a
// guaranteed memory leak. // guaranteed memory leak.
#define with_borrow(NAME) \ #define with_borrow(NAME) \
for (allocator_t NAME = borrow_allocator_create(); NAME.this != NULL; \ for (allocator_t NAME = borrow_allocator_create(); NAME.this != NULL; \
NAME.this = (allocator_reset(NAME), NULL)) \ NAME.this = (allocator_reset(NAME), NULL)) \
for (int UNIQUE = 0; UNIQUE < 1; UNIQUE++) for (int UNIQUE = 0; UNIQUE < 1; UNIQUE++)
// arena allocator /////////////////////////////////////////////////////////////
typedef struct arena_allocator {
allocator_t allocator;
size_t size;
size_t capacity;
// this may grow outside the allocated data. When data is not large enough,
// the backing allocator will be used to allocate exactly what the user
// asked for, and the total_allocated will grow for each such allocation.
// On the next reset if total_allocated is larger than capacity, we know
// that there are allocations outside the large buffer, so we reset the
// allocator, and allocate a new buffer that is the size of
// total_allocated, and set the new size of the capacity. Otherwise the
// size is just reset to 0. plus something else I think I forgot.
size_t total_allocated_bytes;
uint8_t *data;
} arena_allocator_t;
#define arena_allocator_value(INITIAL_CAPACITY) ((arena_allocator_t) { \
.allocator=borrow_allocator_create(), \
.size=0, \
.capacity=INITIAL_CAPACITY, \
.data=NULL \
})
allocator_t allocator_from_arena(arena_allocator_t *this);
// dynamic arrays ////////////////////////////////////////////////////////////// // dynamic arrays //////////////////////////////////////////////////////////////
typedef struct dyn_array_header { typedef struct dyn_array_header {
size_t size, capacity, itemsize; size_t size, capacity, itemsize;
allocator_t allocator; allocator_t allocator;
uint8_t bytes[]; uint8_t bytes[];
} dyn_array_header_t; } dyn_array_header_t;
typedef struct dyn_array_create_func_args { typedef struct dyn_array_create_func_args {
allocator_t allocator; allocator_t allocator;
size_t itemsize; size_t itemsize;
size_t initial_capacity; size_t initial_capacity;
const char *file; const char *file;
int line; int line;
} dyn_array_create_func_args_t; } dyn_array_create_func_args_t;
void *dyn_array_create_func(dyn_array_create_func_args_t args); void *dyn_array_create_func(dyn_array_create_func_args_t args);
#define dyn_array_create(ALLOCATOR, TYPE, ...) \ #define dyn_array_create(ALLOCATOR, TYPE, ...) \
((TYPE *)dyn_array_create_func( \ ((TYPE *)dyn_array_create_func( \
(dyn_array_create_func_args_t){.allocator = ALLOCATOR, \ (dyn_array_create_func_args_t){.allocator = ALLOCATOR, \
.itemsize = sizeof(TYPE), \ .itemsize = sizeof(TYPE), \
.file = __FILE__, \ .file = __FILE__, \
.line = __LINE__, \ .line = __LINE__, \
__VA_ARGS__})) __VA_ARGS__}))
// Always reassign the array. if multiple variables reference the same growing // Always reassign the array. if multiple variables reference the same growing
// array, then you should be using pointer pointers. // array, then you should be using pointer pointers.
void *dyn_array_grow_func(void *this, size_t n_new_items, const char *file, int line); void *dyn_array_grow_func(void *this, size_t n_new_items, const char *file, int line);
void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *file, int line); void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *file, int line);
#define dyn_array_grow(THIS, N_NEW_ITEMS) \ #define dyn_array_grow(THIS, N_NEW_ITEMS) \
dyn_array_grow_func(THIS, N_NEW_ITEMS, __FILE__, __LINE__) dyn_array_grow_func(THIS, N_NEW_ITEMS, __FILE__, __LINE__)
#define dyn_array_shrink(THIS, N_ITEMS_TO_REMOVE) \ #define dyn_array_shrink(THIS, N_ITEMS_TO_REMOVE) \
dyn_array_shrink_func(THIS, N_ITEMS_TO_REMOVE, __FILE__, __LINE__) dyn_array_shrink_func(THIS, N_ITEMS_TO_REMOVE, __FILE__, __LINE__)
#define dyn_array_reset(THIS) \ #define dyn_array_reset(THIS) \
do { \ do { \
dyn_array_shrink(THIS, dyn_array_length(THIS)); \ dyn_array_shrink(THIS, dyn_array_length(THIS)); \
} while (0) } while (0)
typedef struct dyn_array_create_non_crashing_func_args { typedef struct dyn_array_create_non_crashing_func_args {
allocator_t allocator; allocator_t allocator;
size_t itemsize; size_t itemsize;
size_t initial_capacity; size_t initial_capacity;
const char *file; const char *file;
size_t line; size_t line;
} dyn_array_create_non_crashing_func_args_t; } dyn_array_create_non_crashing_func_args_t;
void *dyn_array_create_non_crashing_func(dyn_array_create_non_crashing_func_args_t args); void *dyn_array_create_non_crashing_func(dyn_array_create_non_crashing_func_args_t args);
// This version returns a NULL pointer instead of crashing if the allocator return NULL. // This version returns a NULL pointer instead of crashing if the allocator return NULL.
// It is up to you to check that the pointer returned isn't NULL // It is up to you to check that the pointer returned isn't NULL
#define dyn_array_create_non_crashing(ALLOCATOR, TYPE, ...) \ #define dyn_array_create_non_crashing(ALLOCATOR, TYPE, ...) \
((TYPE *)dyn_array_create_non_crashing_func( \ ((TYPE *)dyn_array_create_non_crashing_func( \
(dyn_array_create_non_crashing_func_args_t){.allocator = ALLOCATOR, \ (dyn_array_create_non_crashing_func_args_t){.allocator = ALLOCATOR, \
.itemsize = sizeof(TYPE), \ .itemsize = sizeof(TYPE), \
.file = __FILE__, \ .file = __FILE__, \
.line = __LINE__, \ .line = __LINE__, \
__VA_ARGS__})) __VA_ARGS__}))
// TODO: remove the non-crashing versions. they crash... // TODO: remove the non-crashing versions. they crash...
// This version returns a NULL pointer instead of crashing if the allocator return NULL. // This version returns a NULL pointer instead of crashing if the allocator return NULL.
// It is up to you to check that the pointer returned isn't NULL // It is up to you to check that the pointer returned isn't NULL
@@ -149,8 +178,8 @@ size_t dyn_array_length(void *this);
size_t dyn_array_capacity(void *this); size_t dyn_array_capacity(void *this);
#define dyn_array_append(THIS, VAL) do { \ #define dyn_array_append(THIS, VAL) do { \
THIS = dyn_array_grow(THIS, 1); \ THIS = dyn_array_grow(THIS, 1); \
THIS[dyn_array_length(THIS)-1] = VAL; \ THIS[dyn_array_length(THIS)-1] = VAL; \
} while(0) } while(0)
#define dyn_array_pop(THIS) (dyn_array_shrink(THIS, 1), THIS[dyn_array_length(THIS)]) #define dyn_array_pop(THIS) (dyn_array_shrink(THIS, 1), THIS[dyn_array_length(THIS)])
@@ -158,28 +187,29 @@ size_t dyn_array_capacity(void *this);
#ifdef CIG_IMPL #ifdef CIG_IMPL
void *allocator_alloc_func(allocator_t this, size_t bytes, const char *file, int line) { void *allocator_alloc_func(allocator_t this, size_t bytes, const char *file, int line) {
void *ptr = this.vtbl->alloc(this.this, bytes); void *ptr = this.vtbl->alloc(this.this, bytes);
if (ptr == NULL) { if (ptr == NULL) {
fprintf(stderr, "%s:%d: alloc returned NULL\n", file, line); fprintf(stderr, "%s:%d: alloc returned NULL\n", file, line);
exit(1); exit(1);
} }
return ptr; return ptr;
} }
void *allocator_resize_func(allocator_t this, void *old_ptr, size_t bytes, const char *file, int line) { void *allocator_resize_func(allocator_t this, void *old_ptr, size_t bytes, const char *file, int line) {
void *ptr = this.vtbl->resize(this.this, old_ptr, bytes); void *ptr = this.vtbl->resize(this.this, old_ptr, bytes);
if (ptr == NULL) { if (ptr == NULL) {
fprintf(stderr, "%s:%d: alloc returned NULL\n", file, line); fprintf(stderr, "%s:%d: alloc returned NULL\n", file, line);
exit(1); exit(1);
} }
return ptr; return ptr;
} }
void allocator_reset(allocator_t this) { void allocator_reset(allocator_t this) {
this.vtbl->reset(this.this); this.vtbl->reset(this.this);
} }
#include "forever_allocator.c" #include "forever_allocator.c"
#include "buffer_allocator.c" #include "buffer_allocator.c"
#include "borrow_allocator.c" #include "borrow_allocator.c"
#include "arena_allocator.c"
#include "dyn_array.c" #include "dyn_array.c"
#endif // CIG_IMPL #endif // CIG_IMPL
+102 -102
View File
@@ -7,8 +7,8 @@
#define CLI_UNIQUE2 __macro_internal_34bba35b8b9b20a75f9881e3795630e25d36e620d9c9741e2e9141ba82ec6ef8__ #define CLI_UNIQUE2 __macro_internal_34bba35b8b9b20a75f9881e3795630e25d36e620d9c9741e2e9141ba82ec6ef8__
typedef struct args { typedef struct args {
int count; int count;
const char **values; const char **values;
} args_t; } args_t;
args_t cli_make_args(int argc, const char **argv); // no crash args_t cli_make_args(int argc, const char **argv); // no crash
@@ -25,24 +25,24 @@ int cli_req_int_func(args_t args, const char *flag_name, const char *file, int l
#define cli_req_int(ARGS, FLAG_NAME) cli_req_int_func(ARGS, FLAG_NAME, __FILE__, __LINE__) #define cli_req_int(ARGS, FLAG_NAME) cli_req_int_func(ARGS, FLAG_NAME, __FILE__, __LINE__)
#define with_opt_str(ARGS, FLAG_NAME, VAR) \ #define with_opt_str(ARGS, FLAG_NAME, VAR) \
for (const char *VAR = NULL; VAR == NULL;) \ for (const char *VAR = NULL; VAR == NULL;) \
for (bool CLI_UNIQUE1 = true; CLI_UNIQUE1;) \ for (bool CLI_UNIQUE1 = true; CLI_UNIQUE1;) \
for ( \ for ( \
bool CLI_UNIQUE2 = (CLI_UNIQUE1 = cli_opt_str(ARGS, FLAG_NAME, &VAR), true); \ bool CLI_UNIQUE2 = (CLI_UNIQUE1 = cli_opt_str(ARGS, FLAG_NAME, &VAR), true); \
CLI_UNIQUE2; \ CLI_UNIQUE2; \
CLI_UNIQUE2 = (VAR = ((const char *) 1), CLI_UNIQUE1 = false, false) \ CLI_UNIQUE2 = (VAR = ((const char *) 1), CLI_UNIQUE1 = false, false) \
) \ ) \
if (CLI_UNIQUE1) if (CLI_UNIQUE1)
#define with_opt_int(ARGS, FLAG_NAME, VAR) \ #define with_opt_int(ARGS, FLAG_NAME, VAR) \
for (int VAR = 0; VAR == 0;) \ for (int VAR = 0; VAR == 0;) \
for (bool CLI_UNIQUE1 = true; CLI_UNIQUE1;) \ for (bool CLI_UNIQUE1 = true; CLI_UNIQUE1;) \
for ( \ for ( \
bool CLI_UNIQUE2 = (CLI_UNIQUE1 = cli_opt_int(ARGS, FLAG_NAME, &VAR), true); \ bool CLI_UNIQUE2 = (CLI_UNIQUE1 = cli_opt_int(ARGS, FLAG_NAME, &VAR), true); \
CLI_UNIQUE2; \ CLI_UNIQUE2; \
CLI_UNIQUE2 = (VAR = 1, CLI_UNIQUE1 = false, false) \ CLI_UNIQUE2 = (VAR = 1, CLI_UNIQUE1 = false, false) \
) \ ) \
if (CLI_UNIQUE1) if (CLI_UNIQUE1)
#ifdef CLI_IMPL #ifdef CLI_IMPL
@@ -51,108 +51,108 @@ int cli_req_int_func(args_t args, const char *flag_name, const char *file, int l
#include <string.h> #include <string.h>
bool cli_command(args_t *args, const char *command_name) { bool cli_command(args_t *args, const char *command_name) {
if (args->count == 0) { if (args->count == 0) {
return false; return false;
} }
if (strcmp(args->values[0], command_name) == 0) { if (strcmp(args->values[0], command_name) == 0) {
args->values++; args->values++;
args->count--; args->count--;
return true; return true;
} }
return false; return false;
} }
bool cli_bool(args_t args, const char *flag_name) { bool cli_bool(args_t args, const char *flag_name) {
for ( int i = 0; i < args.count; i++ ) { for ( int i = 0; i < args.count; i++ ) {
if (strcmp(args.values[i], flag_name) == 0) { if (strcmp(args.values[i], flag_name) == 0) {
return true; return true;
} }
} }
return false; return false;
} }
bool cli_opt_str_func(args_t args, const char *flag_name, const char **output, const char *file, int line) { bool cli_opt_str_func(args_t args, const char *flag_name, const char **output, const char *file, int line) {
bool is_flag_name_found = false; bool is_flag_name_found = false;
int flag_name_index; int flag_name_index;
for ( int i = 0; i < args.count; i++ ) { for ( int i = 0; i < args.count; i++ ) {
if (strcmp(args.values[i], flag_name) == 0) { if (strcmp(args.values[i], flag_name) == 0) {
is_flag_name_found = true; is_flag_name_found = true;
flag_name_index = i; flag_name_index = i;
break; break;
} }
} }
static const char *dummy = ""; static const char *dummy = "";
if (!is_flag_name_found) { if (!is_flag_name_found) {
*output = dummy; *output = dummy;
return false; return false;
} }
int flag_value_index = flag_name_index + 1; int flag_value_index = flag_name_index + 1;
if (args.count <= flag_value_index) { if (args.count <= flag_value_index) {
fprintf(stderr, "%s:%d: No value provided for %s!\n", file, line, flag_name); fprintf(stderr, "%s:%d: No value provided for %s!\n", file, line, flag_name);
exit(1); exit(1);
} }
*output = args.values[flag_value_index]; *output = args.values[flag_value_index];
return true; return true;
} }
const char *cli_req_str_func(args_t args, const char *flag_name, const char *file, int line) { const char *cli_req_str_func(args_t args, const char *flag_name, const char *file, int line) {
const char *value; const char *value;
if (cli_opt_str_func(args, flag_name, &value, file, line)) { if (cli_opt_str_func(args, flag_name, &value, file, line)) {
return value; return value;
} else { } else {
fprintf(stderr, "%s:%d: Required string %s not provided!\n", file, line, flag_name); fprintf(stderr, "%s:%d: Required string %s not provided!\n", file, line, flag_name);
exit(1); exit(1);
} }
return ""; return "";
} }
bool cli_opt_int_func(args_t args, const char *flag_name, int *output, const char *file, int line) { bool cli_opt_int_func(args_t args, const char *flag_name, int *output, const char *file, int line) {
const char *text = ""; const char *text = "";
if (cli_opt_str_func(args, flag_name, &text, file, line)) { if (cli_opt_str_func(args, flag_name, &text, file, line)) {
if ( if (
text[0] != '-' && text[0] != '-' &&
text[0] < '0' && text[0] < '0' &&
'9' < text[0] '9' < text[0]
) { ) {
fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text); fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text);
exit(1); exit(1);
} }
if ( if (
text[0] == '-' && text[0] == '-' &&
text[1] == '\0' text[1] == '\0'
) { ) {
fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text); fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text);
exit(1); exit(1);
} }
for ( const char *c = &text[1]; (*c) != '\0'; c++ ) { for ( const char *c = &text[1]; (*c) != '\0'; c++ ) {
if ((*c) < '0' || '9' < (*c)) { if ((*c) < '0' || '9' < (*c)) {
fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text); fprintf(stderr, "%s:%d: Invalid integer %s!\n", file, line, text);
exit(1); exit(1);
} }
} }
*output = atoi(text); *output = atoi(text);
return true; return true;
} }
*output = 0; *output = 0;
return false; return false;
} }
int cli_req_int_func(args_t args, const char *flag_name, const char *file, int line) { int cli_req_int_func(args_t args, const char *flag_name, const char *file, int line) {
int value; int value;
if (cli_opt_int_func(args, flag_name, &value, file, line)) { if (cli_opt_int_func(args, flag_name, &value, file, line)) {
return value; return value;
} else { } else {
fprintf(stderr, "%s:%d: Required int %s not provided!\n", file, line, flag_name); fprintf(stderr, "%s:%d: Required int %s not provided!\n", file, line, flag_name);
exit(1); exit(1);
} }
return 0; return 0;
} }
args_t cli_make_args(int argc, const char **argv) { args_t cli_make_args(int argc, const char **argv) {
return (args_t) { return (args_t) {
.count = argc-1, .count = argc-1,
.values = argv+1, .values = argv+1,
}; };
} }
#endif /* CLI_IMPL */ #endif /* CLI_IMPL */
+59 -59
View File
@@ -2,83 +2,83 @@
#include <stdio.h> #include <stdio.h>
void *dyn_array_create_func(dyn_array_create_func_args_t args) { void *dyn_array_create_func(dyn_array_create_func_args_t args) {
void *bytes = dyn_array_create_non_crashing_func( void *bytes = dyn_array_create_non_crashing_func(
(dyn_array_create_non_crashing_func_args_t) { (dyn_array_create_non_crashing_func_args_t) {
.allocator=args.allocator, .allocator=args.allocator,
.itemsize=args.itemsize, .itemsize=args.itemsize,
.initial_capacity=args.initial_capacity, .initial_capacity=args.initial_capacity,
.file=args.file, .file=args.file,
.line=args.line .line=args.line
} }
); );
return bytes; return bytes;
} }
void *dyn_array_grow_func(void *this, size_t n_new_items, const char *file, int line) { void *dyn_array_grow_func(void *this, size_t n_new_items, const char *file, int line) {
void *bytes = dyn_array_grow_non_crashing_func(this, n_new_items, file, line); void *bytes = dyn_array_grow_non_crashing_func(this, n_new_items, file, line);
return bytes; return bytes;
} }
void *dyn_array_create_non_crashing_func(dyn_array_create_non_crashing_func_args_t args) { void *dyn_array_create_non_crashing_func(dyn_array_create_non_crashing_func_args_t args) {
dyn_array_header_t *header = allocator_alloc_func( dyn_array_header_t *header = allocator_alloc_func(
args.allocator, args.allocator,
sizeof(dyn_array_header_t) + args.itemsize * args.initial_capacity, sizeof(dyn_array_header_t) + args.itemsize * args.initial_capacity,
args.file, args.file,
args.line args.line
); );
header->size = 0; header->size = 0;
header->capacity = args.initial_capacity; header->capacity = args.initial_capacity;
header->itemsize = args.itemsize; header->itemsize = args.itemsize;
header->allocator = args.allocator; header->allocator = args.allocator;
return &header->bytes; return &header->bytes;
} }
void *dyn_array_grow_non_crashing_func(void *this, size_t n_new_items, const char *file, int line) { void *dyn_array_grow_non_crashing_func(void *this, size_t n_new_items, const char *file, int line) {
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
size_t new_size = header->size + n_new_items; size_t new_size = header->size + n_new_items;
if (header->capacity < new_size) { if (header->capacity < new_size) {
size_t cap_times_2 = header->capacity * 2; size_t cap_times_2 = header->capacity * 2;
size_t new_capacity = size_t new_capacity =
cap_times_2 < new_size cap_times_2 < new_size
? new_size ? new_size
: cap_times_2; : cap_times_2;
header = allocator_resize_func( header = allocator_resize_func(
header->allocator, header->allocator,
header, header,
sizeof(dyn_array_header_t) + header->itemsize * new_capacity, sizeof(dyn_array_header_t) + header->itemsize * new_capacity,
file, file,
line line
); );
header->capacity = new_capacity; header->capacity = new_capacity;
} }
header->size = new_size; header->size = new_size;
return &header->bytes; return &header->bytes;
} }
void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *file, int line) { void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *file, int line) {
if (dyn_array_length(this) < n_items_to_remove) { if (dyn_array_length(this) < n_items_to_remove) {
fprintf( fprintf(
stderr, stderr,
"%s:%d: tried to remove more items than contained in dynamic array.\n", "%s:%d: tried to remove more items than contained in dynamic array.\n",
file, file,
line line
); );
exit(1); exit(1);
} }
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
header->size -= n_items_to_remove; header->size -= n_items_to_remove;
} }
size_t dyn_array_length(void *this) { size_t dyn_array_length(void *this) {
if (this == NULL) { return 0; } if (this == NULL) { return 0; }
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
return header->size; return header->size;
} }
size_t dyn_array_capacity(void *this) { size_t dyn_array_capacity(void *this) {
if (this == NULL) { return 0; } if (this == NULL) { return 0; }
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
return header->capacity; return header->capacity;
} }
+12 -12
View File
@@ -1,27 +1,27 @@
#include "cig.h" #include "cig.h"
static void *forever_alloc(void *this, size_t bytes) { static void *forever_alloc(void *this, size_t bytes) {
(void)this; (void)this;
return malloc(bytes); return malloc(bytes);
} }
static void *forever_resize(void *this, void *old_ptr, size_t bytes) { static void *forever_resize(void *this, void *old_ptr, size_t bytes) {
(void)this; (void)this;
return realloc(old_ptr, bytes); return realloc(old_ptr, bytes);
} }
static void forever_no_op(void *this) { static void forever_no_op(void *this) {
(void)this; (void)this;
} }
static const allocator_vtbl_t forever_vtbl = { static const allocator_vtbl_t forever_vtbl = {
.alloc = forever_alloc, .alloc = forever_alloc,
.resize = forever_resize, .resize = forever_resize,
.reset = forever_no_op, .reset = forever_no_op,
}; };
allocator_t forever_allocator() { allocator_t forever_allocator() {
return (allocator_t) { return (allocator_t) {
.this=NULL, .this=NULL,
.vtbl=&forever_vtbl, .vtbl=&forever_vtbl,
}; };
} }
+14 -14
View File
@@ -5,26 +5,26 @@
int main() { int main() {
// test 1/////////////////////////////////////////////////////////////////////// // test 1///////////////////////////////////////////////////////////////////////
arena_allocator_t aalloc = arena_allocator_create(); arena_allocator_t aalloc = arena_allocator_create();
for ( int i = 0; i < 10; i++ ) with_arena(&aalloc, allocator) { for ( int i = 0; i < 10; i++ ) with_arena(&aalloc, allocator) {
allocator_alloc(allocator, 10); allocator_alloc(allocator, 10);
} }
assert(aalloc.to_allocate == 10); assert(aalloc.to_allocate == 10);
assert(borrow_allocator_count_allocations(&aalloc.borrow_allocator) == 0); assert(borrow_allocator_count_allocations(&aalloc.borrow_allocator) == 0);
assert(dyn_array_capacity(aalloc.bytes) == 10); assert(dyn_array_capacity(aalloc.bytes) == 10);
arena_allocator_destroy(&aalloc); arena_allocator_destroy(&aalloc);
assert(aalloc.to_allocate == 0); assert(aalloc.to_allocate == 0);
arena_allocator_destroy(&aalloc); arena_allocator_destroy(&aalloc);
// test 2 ////////////////////////////////////////////////////////////////////// // test 2 //////////////////////////////////////////////////////////////////////
aalloc = arena_allocator_create(); aalloc = arena_allocator_create();
for ( int i = 0; i < 10; i++ ) with_arena(&aalloc, allocator) { for ( int i = 0; i < 10; i++ ) with_arena(&aalloc, allocator) {
allocator_alloc(allocator, 1000); allocator_alloc(allocator, 1000);
} }
with_arena(&aalloc, allocator) { with_arena(&aalloc, allocator) {
size_t prev_addr = 0; size_t prev_addr = 0;
@@ -37,7 +37,7 @@ int main() {
} }
arena_allocator_reset(&aalloc); arena_allocator_reset(&aalloc);
fprintf(stderr, "%zu\n", aalloc.to_allocate); fprintf(stderr, "%zu\n", aalloc.to_allocate);
//assert(aalloc.to_allocate == MAX_ALIGN * 1000 + 1); //assert(aalloc.to_allocate == MAX_ALIGN * 1000 + 1);
// TODO: WHAT is happening here? // TODO: WHAT is happening here?
arena_allocator_destroy(&aalloc); arena_allocator_destroy(&aalloc);
} }
+16 -16
View File
@@ -3,24 +3,24 @@
#define EXPECT 5 #define EXPECT 5
Test(borrow_allocator, test) { Test(borrow_allocator, test) {
allocator_t balloc = allocator_from_borrow(&borrow_allocator_value()); allocator_t balloc = allocator_from_borrow(&borrow_allocator_value());
int *ptr = allocator_alloc(balloc, sizeof(int)); int *ptr = allocator_alloc(balloc, sizeof(int));
*ptr = EXPECT; *ptr = EXPECT;
cr_assert_eq(*ptr, EXPECT); cr_assert_eq(*ptr, EXPECT);
allocator_reset(balloc); allocator_reset(balloc);
} }
#define IS_SIZE 900 #define IS_SIZE 900
Test(borrow_allocator, with) { Test(borrow_allocator, with) {
with_borrow(foo) { with_borrow(foo) {
with_borrow(bar) { with_borrow(bar) {
} }
int *is = allocator_alloc(foo, sizeof(int) * IS_SIZE); int *is = allocator_alloc(foo, sizeof(int) * IS_SIZE);
for (int i = 0; i < IS_SIZE; i++) is[i] = i; for (int i = 0; i < IS_SIZE; i++) is[i] = i;
is = allocator_alloc(foo, sizeof(int) * IS_SIZE); is = allocator_alloc(foo, sizeof(int) * IS_SIZE);
for (int i = 0; i < IS_SIZE; i++) is[i] = i; for (int i = 0; i < IS_SIZE; i++) is[i] = i;
is = allocator_alloc(foo, sizeof(int) * IS_SIZE); is = allocator_alloc(foo, sizeof(int) * IS_SIZE);
for (int i = 0; i < IS_SIZE; i++) is[i] = i; for (int i = 0; i < IS_SIZE; i++) is[i] = i;
break; break;
} }
} }
+26 -26
View File
@@ -2,33 +2,33 @@
#include "cig.h" #include "cig.h"
static void test_buffer_alloc(buffer_allocator_t impl) { static void test_buffer_alloc(buffer_allocator_t impl) {
allocator_t inter = buffer_allocator(&impl); allocator_t inter = allocator_from_buffer(&impl);
const int n_ints = 100; const int n_ints = 100;
int *ints = allocator_alloc(inter, sizeof(int) * n_ints); int *ints = allocator_alloc(inter, sizeof(int) * n_ints);
for (int i = 0; i < n_ints; i++) { for (int i = 0; i < n_ints; i++) {
ints[i] = i; ints[i] = i;
} }
for (int i = 0; i < n_ints; i++) { for (int i = 0; i < n_ints; i++) {
cr_assert_eq(ints[i], i); cr_assert_eq(ints[i], i);
} }
cr_assert_eq(impl.size, sizeof(int)*n_ints); cr_assert_eq(impl.size, sizeof(int)*n_ints);
ints = allocator_alloc(inter, sizeof(int) * n_ints); ints = allocator_alloc(inter, sizeof(int) * n_ints);
for (int i = 0; i < n_ints; i++) { for (int i = 0; i < n_ints; i++) {
ints[i] = i; ints[i] = i;
} }
for (int i = 0; i < n_ints; i++) { for (int i = 0; i < n_ints; i++) {
cr_assert_eq(ints[i], i); cr_assert_eq(ints[i], i);
} }
cr_assert_eq(impl.size, sizeof(int)*2*n_ints); cr_assert_eq(impl.size, sizeof(int)*2*n_ints);
size_t double_ints = ((size_t) n_ints) * 2; size_t double_ints = ((size_t) n_ints) * 2;
void *should_be_addr = allocator_resize(inter, ints, double_ints); void *should_be_addr = allocator_resize(inter, ints, double_ints);
cr_assert_neq(should_be_addr, NULL); cr_assert_neq(should_be_addr, NULL);
allocator_reset(inter); allocator_reset(inter);
} }
Test(buffer_allocator, test) { Test(buffer_allocator, test) {
buffer_allocator_t impl = buffer_allocator_create(MB); buffer_allocator_t impl = buffer_allocator_value(MB);
test_buffer_alloc(impl); test_buffer_alloc(impl);
cr_assert_eq(impl.size, 0); cr_assert_eq(impl.size, 0);
test_buffer_alloc(impl); test_buffer_alloc(impl);
} }
+41 -41
View File
@@ -5,48 +5,48 @@
#include "cig.h" #include "cig.h"
Test(dynamic_arrays, append) { Test(dynamic_arrays, append) {
with_borrow(alloc) { with_borrow(alloc) {
int *numbers = dyn_array_create(alloc, int); int *numbers = dyn_array_create(alloc, int);
dyn_array_append(numbers, 40); dyn_array_append(numbers, 40);
dyn_array_append(numbers, 41); dyn_array_append(numbers, 41);
dyn_array_append(numbers, 42); dyn_array_append(numbers, 42);
dyn_array_append(numbers, 43); dyn_array_append(numbers, 43);
dyn_array_append(numbers, 44); dyn_array_append(numbers, 44);
dyn_array_append(numbers, 45); dyn_array_append(numbers, 45);
dyn_array_append(numbers, 46); dyn_array_append(numbers, 46);
dyn_array_append(numbers, 47); dyn_array_append(numbers, 47);
dyn_array_append(numbers, 48); dyn_array_append(numbers, 48);
dyn_array_append(numbers, 49); dyn_array_append(numbers, 49);
dyn_array_append(numbers, 50); dyn_array_append(numbers, 50);
for (int i = 0; i < (int)dyn_array_length(numbers); i++) { for (int i = 0; i < (int)dyn_array_length(numbers); i++) {
cr_assert_eq(numbers[i], i+40); cr_assert_eq(numbers[i], i+40);
} }
} }
} }
Test(dynamic_arrays, pop) { Test(dynamic_arrays, pop) {
with_borrow(alloc) { with_borrow(alloc) {
int *numbers = dyn_array_create(alloc, int); int *numbers = dyn_array_create(alloc, int);
dyn_array_append(numbers, 40); dyn_array_append(numbers, 40);
dyn_array_append(numbers, 41); dyn_array_append(numbers, 41);
dyn_array_append(numbers, 42); dyn_array_append(numbers, 42);
dyn_array_append(numbers, 43); dyn_array_append(numbers, 43);
dyn_array_append(numbers, 44); dyn_array_append(numbers, 44);
dyn_array_append(numbers, 45); dyn_array_append(numbers, 45);
dyn_array_append(numbers, 46); dyn_array_append(numbers, 46);
dyn_array_append(numbers, 47); dyn_array_append(numbers, 47);
dyn_array_append(numbers, 48); dyn_array_append(numbers, 48);
dyn_array_append(numbers, 49); dyn_array_append(numbers, 49);
dyn_array_append(numbers, 50); dyn_array_append(numbers, 50);
cr_assert_eq(dyn_array_length(numbers), 11); cr_assert_eq(dyn_array_length(numbers), 11);
// NOTE: you can stack for loops to have scoped variables you can abuse // NOTE: you can stack for loops to have scoped variables you can abuse
// in macros. e.g. // in macros. e.g.
// for (TYPE UNIQUE = (int)dyn_array_length(numbers); UNIQUE != 0; UNIQUE = 0;) // for (TYPE UNIQUE = (int)dyn_array_length(numbers); UNIQUE != 0; UNIQUE = 0;)
// for (int i = 0, i < UNIQUE; i++) // for (int i = 0, i < UNIQUE; i++)
int len = (int)dyn_array_length(numbers); int len = (int)dyn_array_length(numbers);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
int num = dyn_array_pop(numbers); int num = dyn_array_pop(numbers);
cr_assert_eq(num, 50-i); cr_assert_eq(num, 50-i);
} }
} }
} }
+12 -12
View File
@@ -2,25 +2,25 @@
#include <stdbool.h> #include <stdbool.h>
enum animal { enum animal {
dog, dog,
cat, cat,
}; };
typedef struct args { typedef struct args {
enum animal animal; enum animal animal;
bool is_true; bool is_true;
} args_t; } args_t;
#define ARGS_DEFAULT .animal=cat, .is_true=true #define ARGS_DEFAULT .animal=cat, .is_true=true
#define ARGS(...) ((args_t){ ARGS_DEFAULT, __VA_ARGS__ }) #define ARGS(...) ((args_t){ ARGS_DEFAULT, __VA_ARGS__ })
Test(macro_magic, default_values) { Test(macro_magic, default_values) {
args_t a1 = ARGS(); args_t a1 = ARGS();
args_t a2 = ARGS(.animal=dog); args_t a2 = ARGS(.animal=dog);
args_t a3 = ARGS(.animal=dog, .is_true=false); args_t a3 = ARGS(.animal=dog, .is_true=false);
cr_assert_eq(a1.animal, cat); cr_assert_eq(a1.animal, cat);
cr_assert_eq(a2.animal, dog); cr_assert_eq(a2.animal, dog);
cr_assert_eq(a1.is_true, true); cr_assert_eq(a1.is_true, true);
cr_assert_eq(a2.is_true, true); cr_assert_eq(a2.is_true, true);
cr_assert_eq(a3.is_true, false); cr_assert_eq(a3.is_true, false);
} }
+6 -6
View File
@@ -3,10 +3,10 @@
// TODO rename std to forever allocator // TODO rename std to forever allocator
Test(std_allocator, test) { Test(std_allocator, test) {
allocator_t this = forever_allocator(); allocator_t this = forever_allocator();
void *ptr = allocator_alloc(this, 10); void *ptr = allocator_alloc(this, 10);
cr_assert(ptr != ((void *)0), "non null from malloc"); cr_assert(ptr != ((void *)0), "non null from malloc");
void *new_ptr = allocator_resize(this, ptr, 1024*1024*500); void *new_ptr = allocator_resize(this, ptr, 1024*1024*500);
cr_assert(new_ptr != ((void *)0), "non null from realloc"); cr_assert(new_ptr != ((void *)0), "non null from realloc");
cr_assert(new_ptr != ptr, "realloc is not the same ptr as malloc"); cr_assert(new_ptr != ptr, "realloc is not the same ptr as malloc");
} }