#ifndef CORE_LIST_H #define CORE_LIST_H #include #include "core/ToString.h" #include "core/Types.h" #include "core/Utility.h" #define LIST(T, N) \ struct ListT##N { \ size_t length; \ size_t capacity; \ T* data; \ }; \ typedef struct ListT##N List##N; \ \ void initList##N(List##N* l); \ void destroyList##N(List##N* l); \ void reserveListEntries##N(List##N* l, size_t n); \ void addListData##N(List##N* l, T data); \ void addLastListData##N(List##N* l); \ T* addEmptyListData##N(List##N* l); \ T* getListIndex##N(const List##N* l, size_t index); \ T* getListLast##N(const List##N* l); \ void clearList##N(List##N* l); \ void removeListIndexBySwap##N(List##N* l, size_t index); \ void removeListIndex##N(List##N* l, size_t index); \ void removeListLast##N(List##N* l); \ T* getListStart##N(const List##N* l); \ T* getListEnd##N(const List##N* l); \ typedef size_t (*ToString##N)(const T* data, char* buffer, size_t n); \ size_t toStringList##N(const List##N* l, char* buffer, size_t n, \ ToString##N c); #define LIST_SOURCE(T, N) \ void initList##N(List##N* l) { \ *l = (List##N){0, 0, nullptr}; \ } \ \ void destroyList##N(List##N* l) { \ coreFree(l->data); \ *l = (List##N){0}; \ } \ \ void reserveListEntries##N(List##N* l, size_t n) { \ if(n > l->capacity) { \ l->capacity = n; \ l->data = coreReallocate(l->data, sizeof(T) * n); \ } \ } \ \ void addListData##N(List##N* l, T data) { \ *addEmptyListData##N(l) = data; \ } \ \ void addLastListData##N(List##N* l) { \ addListData##N(l, *getListLast##N(l)); \ } \ \ T* addEmptyListData##N(List##N* l) { \ if(l->length >= l->capacity) { \ reserveListEntries##N(l, l->capacity + \ maxSize(4lu, l->capacity / 4)); \ } \ return l->data + l->length++; \ } \ \ T* getListIndex##N(const List##N* l, size_t index) { \ assert(index < l->length); \ return l->data + index; \ } \ \ T* getListLast##N(const List##N* l) { \ return getListIndex##N(l, l->length - 1); \ } \ \ void clearList##N(List##N* l) { \ l->length = 0; \ } \ \ void removeListIndexBySwap##N(List##N* l, size_t index) { \ assert(index < l->length); \ size_t length = l->length - 1; \ if(index != length) { \ l->data[index] = l->data[length]; \ } \ l->length = length; \ } \ \ void removeListIndex##N(List##N* l, size_t index) { \ assert(index < l->length); \ l->length--; \ T* p = l->data + index; \ T* end = getListEnd##N(l); \ while(p != end) { \ *p = *(p + 1); \ p++; \ } \ } \ \ void removeListLast##N(List##N* l) { \ removeListIndexBySwap##N(l, l->length - 1); \ } \ \ T* getListStart##N(const List##N* l) { \ return l->data; \ } \ \ T* getListEnd##N(const List##N* l) { \ return l->data + l->length; \ } \ \ size_t toStringList##N(const List##N* l, char* buffer, size_t n, \ ToString##N c) { \ size_t w = 0; \ stringAdd(&w, &buffer, &n, toString(buffer, n, "[")); \ T* end = getListEnd##N(l); \ T* p = getListStart##N(l); \ while(p != end) { \ stringAdd(&w, &buffer, &n, c(p, buffer, n)); \ p++; \ if(p != end) { \ stringAdd(&w, &buffer, &n, toString(buffer, n, ", ")); \ } \ } \ stringAdd(&w, &buffer, &n, toString(buffer, n, "]")); \ return w; \ } #endif