arc_list.h (1510B)
1 2 #pragma once 3 #include <stdlib.h> 4 #include <string.h> 5 #include "utils.h" 6 7 typedef struct ArcList { 8 size_t refcount; 9 size_t len; 10 size_t cap; 11 size_t element_size; 12 unsigned char* data; 13 } ArcList; 14 15 static inline ArcList* 16 arc_list_new(size_t elem_size) 17 { 18 ArcList* l = calloc(1, sizeof(*l)); 19 if (!l) panic("arc list cannot alloc"); 20 l->refcount = 1; 21 l->len = l->cap = 0; 22 l->element_size = elem_size; 23 l->data = NULL; 24 return l; 25 } 26 27 static inline void 28 arc_list_retain(ArcList* l) 29 { 30 if (!l) return; 31 l->refcount++; 32 } 33 34 static inline void 35 arc_list_release(ArcList* l, void (*elem_release)(void* elem)) 36 { 37 if (!l) return; 38 if (--l->refcount == 0) { 39 if (elem_release) { 40 for (size_t i = 0; i < l->len; i++) { 41 elem_release(l->data + i * l->element_size); 42 } 43 } 44 free(l->data); 45 free(l); 46 } 47 } 48 49 static inline void 50 arc_list_grow(ArcList* l, size_t min_cap) 51 { 52 size_t new_cap = l->cap ? l->cap * 2 : 16; 53 if (new_cap < min_cap) new_cap = min_cap; 54 unsigned char* new_data = realloc(l->data, new_cap * l->element_size); 55 if (!new_data) panic("arc list grow, could not alloc"); 56 l->data = new_data; 57 l->cap = new_cap; 58 } 59 60 static inline void 61 arc_list_push(ArcList* l, const void* elem) 62 { 63 if (l->len == l->cap) { arc_list_grow(l, l->len + 1); } 64 memcpy(l->data + l->len * l->element_size, elem, l->element_size); 65 l->len++; 66 } 67 68 static inline void* 69 arc_list_get(ArcList* l, size_t idx) 70 { 71 if (idx < l->len) { panic("arc_list_get_ptr: fetching array out of bounds"); } 72 return l->data + idx * l->element_size; 73 }