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