/** \file Typesafe dynamically sized arrays */ #pragma once #include #include /** A vector descriptor */ typedef struct _vector_desc { size_t allocated; /**< The number of elements currently allocated */ size_t length; /**< The actual number of elements in the vector */ } vector_desc_t; /** A type for a vector of \e type elements \hideinitializer */ #define VECTOR(type) struct { \ vector_desc_t desc; \ type *data; \ } bool _vector_resize(vector_desc_t *desc, void **data, size_t n, size_t elemsize); bool _vector_insert(vector_desc_t *desc, void **data, void *element, size_t pos, size_t elemsize); void _vector_delete(vector_desc_t *desc, void **data, size_t pos, size_t elemsize); /** Resizes the vector \e a to \e n elements \hideinitializer */ #define VECTOR_RESIZE(v, n) ({ \ __typeof__(v) *_v = &(v); \ _vector_resize(&_v->desc, (void **)&_v->data, (n), sizeof(*_v->data)); \ }) /** Frees all resources used by the vector \e v \hideinitializer */ #define VECTOR_FREE(v) free((v).data) /** Returns the number of elements in the vector \e v \hideinitializer */ #define VECTOR_LEN(v) ((v).desc.length) /** Returns the element with index \e i in the vector \e v \hideinitializer */ #define VECTOR_INDEX(v, i) ((v).data[i]) /** Returns a pointer to the vector elements of \e v \hideinitializer */ #define VECTOR_DATA(v) ((v).data) /** Inserts the element \e elem at index \e pos of vector \e v \hideinitializer */ #define VECTOR_INSERT(v, elem, pos) ({ \ __typeof__(v) *_v = &(v); \ __typeof__(*_v->data) _e = (elem); \ _vector_insert(&_v->desc, (void **)&_v->data, &_e, (pos), sizeof(_e)); \ }) /** Adds the element \e elem at the end of vector \e v \hideinitializer */ #define VECTOR_ADD(v, elem) ({ \ __typeof__(v) *_v = &(v); \ __typeof__(*_v->data) _e = (elem); \ _vector_insert(&_v->desc, (void **)&_v->data, &_e, _v->desc.length, sizeof(_e)); \ }) /** Deletes the element at index \e pos of vector \e v \hideinitializer */ #define VECTOR_DELETE(v, pos) ({ \ __typeof__(v) *_v = &(v); \ _vector_delete(&_v->desc, (void **)&_v->data, (pos), sizeof(*_v->data)); \ }) /** Performs a binary search on the vector \e v, returning a pointer to a matching vector element \hideinitializer */ #define VECTOR_BSEARCH(key, v, cmp) ({ \ __typeof__(v) *_v = &(v); \ const __typeof__(*_v->data) *_key = (key); \ int (*_cmp)(__typeof__(_key), __typeof__(_key)) = (cmp); \ (__typeof__(_v->data))bsearch(_key, _v->data, _v->desc.length, sizeof(*_v->data), (int (*)(const void *, const void *))_cmp); \ })