some progress on dynamic arrays
This commit is contained in:
@@ -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
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
#include "cig.h"
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user