retab everything to use tabs
This commit is contained in:
+55
-55
@@ -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
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user