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