1 #ifndef LI_VECTOR_H 2 #define LI_VECTOR_H 3 #include "first.h" 4 5 #include "buffer.h" /* force_assert() */ 6 7 static inline size_t vector_align_size(size_t s) { 8 size_t a = (s + 16) & ((size_t)~15); 9 return (a < s) ? s : a; 10 } 11 12 void vector_free(void *data); 13 void *vector_malloc(size_t sz); 14 void *vector_realloc(void *data, size_t elem_size, size_t size, size_t used); 15 16 #define DEFINE_TYPED_VECTOR(name, entry, release) \ 17 typedef struct vector_ ## name { \ 18 entry* data; \ 19 size_t used; \ 20 size_t size; \ 21 } vector_ ## name; \ 22 static inline void vector_ ## name ## _init(vector_ ## name *v) { \ 23 v->data = NULL; \ 24 v->used = v->size = 0; \ 25 } \ 26 static inline vector_ ## name *vector_ ## name ## _alloc() { \ 27 vector_ ## name *v = vector_malloc(sizeof(*v)); \ 28 force_assert(NULL != v); \ 29 vector_ ## name ## _init(v); \ 30 return v; \ 31 } \ 32 static inline void vector_ ## name ## _clear(vector_ ## name *v) { \ 33 size_t ndx; \ 34 vector_ ## name vcopy = *v; \ 35 vector_ ## name ## _init(v); \ 36 if (release) for (ndx = 0; ndx < vcopy.used; ++ndx) release(vcopy.data[ndx]); \ 37 vector_free(vcopy.data); \ 38 } \ 39 static inline void vector_ ## name ## _free(vector_ ## name *v) { \ 40 if (NULL != v) { \ 41 vector_ ## name ## _clear(v); \ 42 vector_free(v); \ 43 } \ 44 } \ 45 static inline void vector_ ## name ## _reserve(vector_ ## name *v, size_t p) { \ 46 force_assert(v->used < SIZE_MAX - p); \ 47 if (v->size < v->used + p) { \ 48 v->size = vector_align_size(v->used + p); \ 49 v->data = vector_realloc(v->data, sizeof(entry), v->size, v->used); \ 50 } \ 51 } \ 52 static inline void vector_ ## name ## _push(vector_ ## name *v, entry e) { \ 53 vector_ ## name ## _reserve(v, 1); \ 54 v->data[v->used++] = e; \ 55 } \ 56 static inline entry vector_ ## name ## _pop(vector_ ## name *v) { \ 57 force_assert(v->used > 0); \ 58 return v->data[--v->used]; \ 59 } \ 60 struct vector_ ## name /* expect trailing semicolon */ \ 61 /* end of DEFINE_TYPED_VECTOR */ 62 63 #define DEFINE_TYPED_VECTOR_NO_RELEASE(name, entry) \ 64 DEFINE_TYPED_VECTOR(name, entry, ((void(*)(entry)) NULL)) \ 65 /* end of DEFINE_TYPED_VECTOR_NO_RELEASE */ 66 67 68 #endif 69