summaryrefslogtreecommitdiff
path: root/list
diff options
context:
space:
mode:
authorEnrique2025-01-06 00:50:11 +0100
committerEnrique2025-01-06 00:50:11 +0100
commit789169d70d24ff2c1c9804f0149d0508de6dfcfa (patch)
tree088ec2ce664a13aeeb3603d0eee6c737caff7190 /list
downloadsoikk-libs-789169d70d24ff2c1c9804f0149d0508de6dfcfa.tar.xz
soikk-libs-789169d70d24ff2c1c9804f0149d0508de6dfcfa.tar.zst
First upload
Diffstat (limited to 'list')
-rwxr-xr-xlist/list.c54
-rwxr-xr-xlist/list.h229
-rwxr-xr-xlist/rulez.txt20
3 files changed, 303 insertions, 0 deletions
diff --git a/list/list.c b/list/list.c
new file mode 100755
index 0000000..4898790
--- /dev/null
+++ b/list/list.c
@@ -0,0 +1,54 @@
+#include "list.h"
+
+
+void _init_list(void **list, u32 n, int tsize, enum LIST_TYPE type){
+ struct list_header *h = calloc(1, sizeof(struct list_header) + n*tsize);
+ if(h == NULL) return; // TODO error warning??
+ *h = (struct list_header){.cap = n, .size = 0, .tsize = tsize, .type = type};
+ *list = h+1;
+}
+
+void _list_realloc(void **list, u32 n){
+ struct list_header *h = list_header(*list);
+ if(h == NULL) return; // TODO error warning??
+ struct list_header *nh = realloc(h, sizeof(struct list_header) + n*h->tsize);
+ if(nh == NULL) return; // TODO error warning??
+ nh->cap = n;
+ *list = (void*)nh+sizeof(struct list_header);
+}
+
+void _list_adjust(void **list){
+ struct list_header *h = list_header(*list);
+ if(h == NULL) return; // TODO error warning??
+ u32 ncap = 0;
+ if(h->type == LIST_DYNAMIC){
+ if(h->size == h->cap && h->cap < UINT32_MAX){
+ ncap = clp2_32(h->cap+2)-1;
+ }else if(h->size < h->cap>>1 && h->cap > LIST_INIT_CAP){
+ ncap = flp2_32(h->cap)-1;
+ }
+ }else if(h->type == LIST_NAIVE_DYNAMIC){
+ if(h->size == h->cap && h->cap < UINT32_MAX){
+ ncap = h->cap+1;
+ }else if(h->size < h->cap && h->cap > 1){
+ ncap = h->cap-1;
+ }
+ }
+ if(ncap != 0) _list_realloc(list, ncap);
+}
+
+void _list_remove(void **list, u32 i){
+ struct list_header *h = list_header(*list);
+ if(h == NULL) return; // TODO error warning??
+ memmove(*list+i*h->tsize, *list+(i+1)*h->tsize, (h->size-i-1)*h->tsize);
+ h->size--;
+ memset(*list+h->size*h->tsize, 0, h->tsize);
+}
+
+void _list_free(void **list){
+ if(*list == NULL) return;
+ struct list_header *h = list_header(*list);
+ free(h);
+ *list = NULL;
+}
+
diff --git a/list/list.h b/list/list.h
new file mode 100755
index 0000000..9834ede
--- /dev/null
+++ b/list/list.h
@@ -0,0 +1,229 @@
+#ifndef LIST_H
+#define LIST_H
+// possible todo: overload macros to be able to pass them the header too
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "types/types.h"
+#include "bit/bit.h"
+
+
+struct list_header {
+ u32 cap;
+ u32 size;
+ int tsize;
+ int type;
+};
+
+enum LIST_TYPE {
+ LIST_STATIC,
+ LIST_DYNAMIC,
+ LIST_NAIVE_DYNAMIC,
+};
+
+
+#define LIST(T) typeof(T) *
+#define LIST_INIT_CAP 31
+
+#define list_header(l) ({ \
+ (l) ? (struct list_header *)(((void*)l) - sizeof(struct list_header)) : NULL; \
+})
+
+#define list_cap(l) ({ \
+ struct list_header *h = list_header(l); \
+ h != NULL ? h->cap : 0; \
+})
+
+#define list_size(l) ({ \
+ struct list_header *h = list_header(l); \
+ h != NULL ? h->size : 0; \
+})
+
+#define list_tsize(l) ({ \
+ struct list_header *h = list_header(l); \
+ h != NULL ? h->tsize : 0; \
+})
+
+#define list_type(l) ({ \
+ struct list_header *h = list_header(l); \
+ h != NULL ? h->type : 0; \
+})
+
+#define list_full(l) ({ \
+ struct list_header *h = list_header(l); \
+ h->size < h->cap ? false : true; \
+})
+
+#define init_slist(l, n) ({ \
+ _init_list((void**)&(l), n, sizeof(*(l)), LIST_STATIC); \
+})
+
+#define init_dlist(l) ({ \
+ _init_list((void**)&(l), LIST_INIT_CAP, sizeof(*(l)), LIST_DYNAMIC); \
+})
+
+#define init_nlist(l) ({ \
+ _init_list((void**)&(l), 1, sizeof(*(l)), LIST_NAIVE_DYNAMIC); \
+})
+
+// if you init with 2 arguments, you init a static list. otherwise,
+// a dynamic list. naive list has to be explicitly initialized
+#define _choose_init(_1, _2, NAME, ...) NAME
+#define init_list(...) _choose_init(__VA_ARGS__, init_slist, init_dlist)(__VA_ARGS__)
+
+#define list_peek(l) ({ \
+ typeof((l)[0]) d = {0}; \
+ struct list_header *h = list_header(l); \
+ if(h != NULL && h->size > 0) d = l[h->size-1]; \
+ d; \
+})
+
+#define list_pop(l) ({ \
+ struct list_header *h = list_header(l); \
+ typeof((l)[0]) d = {0}; \
+ if(h != NULL){ \
+ if(h->size > 0){ \
+ d = l[h->size-1]; \
+ l[h->size-1] = (typeof(d)){0}; \
+ h->size--; \
+ _list_adjust((void**)&(l)); \
+ } \
+ } \
+ d; \
+})
+
+#define list_remove(l, i) ({ \
+ struct list_header *h = list_header(l); \
+ typeof(*(l)) d = {0}; \
+ if(h != NULL && i < h->size){ \
+ d = l[i]; \
+ _list_remove((void**)&(l), i); \
+ } \
+ d; \
+})
+
+#define list_remove_entry(l, d) ({ \
+ struct list_header *h = list_header(l); \
+ typeof(d) _d = (d); \
+ if(h != NULL){ \
+ for(u32 i = 0; i < h->size; i++){ \
+ if(!memcmp(&(l[i]), &(_d), sizeof(_d))){ \
+ _list_remove((void**)&(l), i); \
+ _list_adjust((void**)&(l)); \
+ break; \
+ } \
+ } \
+ } \
+ d; \
+})
+
+#define list_entry_exists(l, d) ({ \
+ struct list_header *h = list_header(l); \
+ bool found = false; \
+ if(h != NULL){ \
+ typeof(d) _d = (d); \
+ for(u32 i = 0; i < h->size; i++){ \
+ if(!memcmp(&(l[i]), &(_d), sizeof(_d))){ \
+ found = true; \
+ break; \
+ } \
+ } \
+ } \
+ found; \
+})
+
+#define list_push(l, d) ({ \
+ _list_adjust((void**)&(l)); \
+ struct list_header *h = list_header(l); \
+ if(h != NULL && h->tsize == sizeof(d)){ \
+ if(h->size < h->cap){ \
+ l[h->size] = d; \
+ h->size++; \
+ } \
+ } \
+})
+
+#define list_push_i(l, d, i) ({ \
+ _list_adjust((void**)&(l)); \
+ struct list_header *h = list_header(l); \
+ if(h != NULL && h->tsize == sizeof(d) && i < h->size){ \
+ u32 n = (h->size-i < h->cap-i-1) ? h->size-i : h->cap-i-1; \
+ memmove(((void*)l)+(i+1)*h->tsize, ((void*)l)+i*h->tsize, n*h->tsize); \
+ l[i] = d; \
+ h->size += h->size < h->cap ; \
+ } \
+})
+
+#define list_append(l1, l2) ({ \
+ struct list_header *h1 = list_header(l1); \
+ struct list_header *h2 = list_header(l2); \
+ if(h1 != NULL && h2 != NULL && h1->tsize == h2->tsize){ \
+ u32 ins = h2->size; \
+ if(h1->size+h2->size > h1->cap){ \
+ if(h1->type == LIST_STATIC){ \
+ ins = h1->cap-h1->size; \
+ }else if(h1->type == LIST_DYNAMIC){ \
+ _list_realloc((void**)&(l1), clp2_32(h1->cap+ins)-1); \
+ }else if(h1->type == LIST_NAIVE_DYNAMIC){ \
+ _list_realloc((void**)&(l1), h1->cap+ins); \
+ } \
+ } \
+ h1 = list_header(l1); \
+ memcpy(l1+h1->size, l2, ins); \
+ h1->size += ins; \
+ } \
+})
+
+#define list_append_array(l, a, n) ({ \
+ struct list_header *h = list_header(l); \
+ if(h != NULL && h->tsize == sizeof(a[0])){ \
+ u32 ins = n; \
+ if(h->size+n > h->cap){ \
+ if(h->type == LIST_STATIC){ \
+ ins = h->cap-h->size; \
+ }else if(h->type == LIST_DYNAMIC){ \
+ _list_realloc((void**)&(l), clp2_32(h->cap+ins)-1); \
+ }else if(h->type == LIST_NAIVE_DYNAMIC){ \
+ _list_realloc((void**)&(l), h->cap+ins); \
+ } \
+ } \
+ h = list_header(l); \
+ memcpy(l+h->size, a, ins); \
+ h->size += ins; \
+ } \
+})
+
+#define list_clamp_n(l, n) ({ \
+ struct list_header *h = list_header(l); \
+ if(h != NULL){ \
+ u32 _n = h->size > n ? h->size : n; \
+ _list_realloc((void**)&l, _n); \
+ } \
+})
+
+#define list_clamp_s(l) ({ \
+ struct list_header *h = list_header(l); \
+ if(h != NULL){ \
+ _list_realloc((void**)&l, h->size); \
+ } \
+})
+
+#define _choose_clamp(_1, _2, NAME, ...) NAME
+#define list_clamp(...) _choose_clamp(__VA_ARGS__, list_clamp_n, list_clamp_s)(__VA_ARGS__)
+
+#define list_free(l) _list_free((void**)&(l))
+
+
+void _init_list(void **list, u32 n, int tsize, enum LIST_TYPE type);
+
+void _list_realloc(void **list, u32 n);
+
+void _list_adjust(void **list);
+
+void _list_remove(void **list, u32 i);
+
+void _list_free(void **list);
+
+#endif
diff --git a/list/rulez.txt b/list/rulez.txt
new file mode 100755
index 0000000..65c7ce5
--- /dev/null
+++ b/list/rulez.txt
@@ -0,0 +1,20 @@
+ push
+ static
+ if space l[size++] = d
+ dynamic || naive
+ if !space realloc
+ if space l[size++] = d
+
+ push_i
+ static
+ no sneed
+ dynamic || naive
+ if !space realloc move
+ l[i] = d, size++
+
+ pop
+ static
+ l[size--] = {0}
+ dynamic || naive
+ l[size--] = {0}
+ if space < limit realloc