diff --git a/src/typed_list.c b/src/typed_list.c new file mode 100644 index 0000000..295864a --- /dev/null +++ b/src/typed_list.c @@ -0,0 +1,29 @@ +#include "list/typed_list.h" +#include "mem_arena.h" +#include +#include +#include +#include + +list_void *_create_list(Arena *arena, u64 size, u64 count) { + list_void *list = (list_void *)_alloc_for_list(arena, sizeof(list_void)); + if (!list) { + return NULL; + } + + list->items = (void *)_alloc_for_list(arena, size * count); + if (!list->items) { + munmap(list, sizeof(list_void)); + return NULL; + } + memset(list->items, 0, sizeof(size * count)); + + list->capacity = count; + list->count = 0; + + return list; +} + +void *_alloc_for_list(Arena *arena, u64 size) { + return wapp_mem_arena_alloc(arena, size); +} diff --git a/src/typed_list.h b/src/typed_list.h new file mode 100644 index 0000000..6869515 --- /dev/null +++ b/src/typed_list.h @@ -0,0 +1,79 @@ +#ifndef TYPED_LIST_H +#define TYPED_LIST_H + +#include "aliases.h" +#include "mem_arena.h" +#include +#include + +#define BASE_LIST_CAPACITY 1024 + +#define CONCAT(A, B) A##B +#define LIST_TYPE_NAME(T) CONCAT(list_, T) + +#define MAKE_LIST_TYPE(T) \ + typedef struct { \ + T *items; \ + u64 capacity; \ + u64 count; \ + } LIST_TYPE_NAME(T) + +#define list_create(T, ARENA) \ + (LIST_TYPE_NAME(T) *)_create_list(ARENA, sizeof(T), BASE_LIST_CAPACITY) +#define list_create_with_capacity(T, ARENA, CAPACITY) \ + (LIST_TYPE_NAME(T) *)_create_list(ARENA, sizeof(T), CAPACITY) + +#define _increase_list_capacity(T, ARENA, LP, CAP) \ + do { \ + u64 new_capacity = LP->capacity * 2; \ + T *tmp = _alloc_for_list(ARENA, sizeof(T) * new_capacity); \ + assert(tmp != NULL && "Failed to increase capacity"); \ + \ + memcpy(tmp, LP->items, sizeof(T) * LP->count); \ + \ + LP->capacity = new_capacity; \ + LP->items = tmp; \ + } while (0) + +#define list_append(T, ARENA, LP, ITEM) \ + do { \ + if (LP->count + 1 >= LP->capacity) { \ + _increase_list_capacity(T, ARENA, LP, LP->capacity * 2); \ + } \ + \ + LP->items[(LP->count)++] = ITEM; \ + } while (0) + +#define list_remove(LP, IDX) \ + do { \ + LP->items[IDX] = LP->items[(LP->count)--]; \ + } while (0) +#define list_pop(LP) (LP->count -= 1) + +#define list_set(LP, IDX, ITEM) LP->items[IDX] = ITEM +#define list_get(LP, IDX) LP->items[IDX] + +#define list_merge(T, ARENA, DST, LP1, LP2) \ + do { \ + u64 new_count = LP1->count + LP2->count; \ + u64 capacity = \ + new_count < BASE_LIST_CAPACITY ? BASE_LIST_CAPACITY : new_count * 2; \ + \ + DST = (LIST_TYPE_NAME(T) *)_create_list(ARENA, new_count, capacity); \ + assert(DST != NULL && "Failed to allocate new list"); \ + \ + u64 lp1_copy_size = sizeof(T) * LP1->count; \ + u64 lp2_copy_size = sizeof(T) * LP2->count; \ + memcpy(DST->items, LP1->items, lp1_copy_size); \ + T *dst = &(DST->items[LP1->count]); \ + memcpy(dst, LP2->items, lp2_copy_size); \ + DST->capacity = capacity; \ + DST->count = new_count; \ + } while (0) + +MAKE_LIST_TYPE(void); + +list_void *_create_list(Arena *arena, u64 size, u64 count); +void *_alloc_for_list(Arena *arena, u64 size); + +#endif // !TYPED_LIST_H