diff --git a/cig.h b/cig.h index 78364c2..4266874 100644 --- a/cig.h +++ b/cig.h @@ -117,10 +117,29 @@ typedef struct dyn_array_create_func_args { } dyn_array_create_func_args_t; void *dyn_array_create_func(dyn_array_create_func_args_t args); #define dyn_array_create(ALLOCATOR, TYPE, ...) ((TYPE*) dyn_array_create_func((dyn_array_create_func_args_t){.allocator=ALLOCATOR, .itemsize=sizeof(TYPE), .file=__FILE__, .line=__LINE__, __VA_ARGS__})) - // Always reassign the array. if multiple variables reference the same growing // array, then you should be using pointer pointers. -void *dyn_array_append_func(void *this, void *data); +void *dyn_array_append_func(void *this, void *item, const char *file, int line); +#define dyn_array_append(THIS, ITEM) dyn_array_append_func(THIS, &(ITEM), __FILE__, __LINE__) + +typedef struct dyn_array_create_non_crashing_func_args { + allocator_t allocator; + size_t itemsize; + size_t initial_capacity; +} dyn_array_create_non_crashing_func_args_t; +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. +// It is up to you to check that the pointer returned isn't NULL +#define dyn_array_create_non_crashing(ALLOCATOR, TYPE, ...) ((TYPE*) dyn_array_create_func((dyn_array_create_non_crashing_func_args_t){.allocator=ALLOCATOR, .itemsize=sizeof(TYPE), __VA_ARGS__})) +// 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 +// Always reassign the array. if multiple variables reference the same growing +// array, then you should be using pointer pointers. +void *dyn_array_append_non_crashing_func(void *this, void *item); +#define dyn_array_append_non_crashing(THIS, ITEM) dyn_array_append_non_crashing_func(THIS, &(ITEM)) + +size_t dyn_array_length(void *this); +size_t dyn_array_capacity(void *this); #ifdef ALLOCATOR_IMPLEMENTATION @@ -137,6 +156,7 @@ void allocator_free_func(allocator_t this, void *ptr, const char *file, int line #include "std_allocator.c" #include "buffer_allocator.c" #include "borrow_allocator.c" +#include "dyn_array.c" #endif // ALLOCATOR_IMPLEMENTATION #endif // ALLOCATOR_H diff --git a/dyn_array.c b/dyn_array.c new file mode 100644 index 0000000..e599ce1 --- /dev/null +++ b/dyn_array.c @@ -0,0 +1,86 @@ +#include "cig.h" +#include + +void *dyn_array_create_func(dyn_array_create_func_args_t args) { + void *bytes = dyn_array_create_non_crashing_func( + (dyn_array_create_non_crashing_func_args_t) { + .allocator=args.allocator, + .itemsize=args.itemsize, + .initial_capacity=args.initial_capacity, + } + ); + if (bytes == NULL) { + fprintf( + stderr, + "%s:%d: allocator returned NULL\n", + args.file, + args.line + ); + exit(1); + } + return bytes; +} + +void *dyn_array_append_func(void *this, void *item, const char *file, int line) { + void *bytes = dyn_array_append_non_crashing_func(this, item); + if (bytes == NULL) { + fprintf( + stderr, + "%s:%d: allocator returned NULL\n", + file, + line + ); + exit(1); + } + return bytes; +} + +void *dyn_array_create_non_crashing_func(dyn_array_create_non_crashing_func_args_t args) { + dyn_array_header_t *header = allocator_alloc( + args.allocator, + sizeof(dyn_array_header_t) + args.itemsize * args.initial_capacity + ); + if (header == NULL) { return NULL; } + header->size = 0; + header->capacity = args.initial_capacity; + header->itemsize = args.itemsize; + header->allocator = args.allocator; + return &header->bytes; +} + +void *dyn_array_append_non_crashing_func(void *this, void *item) { + dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); + if (header->capacity <= header->size) { + size_t new_capacity = header->capacity * 2; + if (new_capacity == 0) { new_capacity = 1; } + header = allocator_resize( + header->allocator, + header, + sizeof(dyn_array_header_t) + header->itemsize * new_capacity + ); + if (header == NULL) { return NULL; } + header->capacity = new_capacity; + } + &header->bytes[header->itemsize*header->size] +// typedef struct dyn_array_header { +// size_t size, capacity, itemsize; +// allocator_t allocator; +// uint8_t bytes[]; +// } dyn_array_header_t; + +// TODO: this is not good. the type has to be passed into the macro or +// something because passing in an integer does not work. it won't know to cast +// it to a char, int, long, whatever, so the bytes will be fucked. Either the +// macro can take the type to cast the value into the type, or we can just have +// some grow function instead... +} + +size_t dyn_array_length(void *this) { + dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); +} + +size_t dyn_array_capacity(void *this); { + dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this); +} + +