diff --git a/mie/include/mie/vector.h b/mie/include/mie/vector.h new file mode 100644 index 0000000..c35ef30 --- /dev/null +++ b/mie/include/mie/vector.h @@ -0,0 +1,70 @@ +#ifndef MIE_VECTOR_H_ +#define MIE_VECTOR_H_ + +#include +#include + +#define MIE_VECTOR_DEFINE(type, name) \ + size_t name##_count = 0; \ + size_t name##_max = 0; \ + type *name = NULL + +#define MIE_VECTOR_DECLARE(type, name) \ + size_t name##_count; \ + size_t name##_max; \ + type *name + +#define MIE_VECTOR_COUNT(name) name##_count +#define MIE_VECTOR_MAX(name) name##_max + +#define MIE_VECTOR_PARAM(type, name) \ + type **name, size_t *name##_count, size_t *name##_max +#define MIE_VECTOR_ARG(name) &(name), &(name##_count), &(name##_max) +#define MIE_VECTOR_REF_ARG(name) (name), (name##_count), (name##_max) + +#define mie_vector_push_back(vector, ptr) \ + __mie_vector_push_back( \ + (void **)&(vector), ptr, sizeof *ptr, &(vector##_count), \ + &(vector##_max)) +#define mie_vector_pop_back(vector) \ + __mie_vector_pop_back( \ + (void **)&(vector), sizeof *vector, &(vector##_count), \ + &(vector##_max)) +#define mie_vector_emplace_back(vector) \ + __mie_vector_emplace_back( \ + (void **)&(vector), sizeof *vector, &(vector##_count), \ + &(vector##_max)) + +#define mie_vector_ref_push_back(vector, ptr) \ + __mie_vector_push_back( \ + (void **)(vector), ptr, sizeof *ptr, (vector##_count), \ + (vector##_max)) +#define mie_vector_ref_pop_back(vector) \ + __mie_vector_pop_back( \ + (void **)(vector), sizeof **vector, (vector##_count), \ + (vector##_max)) +#define mie_vector_ref_emplace_back(vector) \ + __mie_vector_emplace_back( \ + (void **)(vector), sizeof **vector, (vector##_count), \ + (vector##_max)) + +#define mie_vector_destroy(vector, dtor) \ + __mie_vector_destroy( \ + (void **)&(vector), sizeof *vector, &(vector##_count), \ + &(vector##_max), dtor) +#define mie_vector_ref_destroy(vector, dtor) \ + __mie_vector_destroy( \ + (void **)(vector), sizeof **vector, (vector##_count), \ + (vector##_max), dtor) + +MIE_API int __mie_vector_push_back( + void **vector, void *item, size_t item_size, size_t *count, size_t *max); +MIE_API void __mie_vector_pop_back( + void **vector, size_t item_size, size_t *count, size_t *max); +MIE_API void *__mie_vector_emplace_back( + void **vector, size_t item_size, size_t *count, size_t *max); +MIE_API void __mie_vector_destroy( + void **vector, size_t item_size, size_t *count, size_t *max, + void (*dtor)(void *)); + +#endif diff --git a/mie/vector.c b/mie/vector.c new file mode 100644 index 0000000..3805689 --- /dev/null +++ b/mie/vector.c @@ -0,0 +1,154 @@ +#include +#include +#include + +#define DEFAULT_CAPACITY 4 + +struct vector { + void *v_buf; + size_t v_itemsz; + size_t v_count; + size_t v_max; +}; + +static void vector_wrap( + struct vector *v, void **vector, size_t item_size, size_t *count, + size_t *max) +{ + v->v_buf = *vector; + v->v_itemsz = item_size; + v->v_count = *count; + v->v_max = *max; +} + +static void vector_unwrap( + struct vector *v, void **vector, size_t item_size, size_t *count, + size_t *max) +{ + *vector = v->v_buf; + *count = v->v_count; + *max = v->v_max; +} + +static int vector_reserve(struct vector *v, size_t new_capacity) +{ + if (v->v_max >= new_capacity) { + return 0; + } + + void *ptr = realloc(v->v_buf, new_capacity * v->v_itemsz); + if (!ptr) { + return -1; + } + + v->v_buf = ptr; + v->v_max = new_capacity; + + return 0; +} + +static int vector_push_back(struct vector *v, void *item) +{ + int err = vector_reserve(v, v->v_count + 1); + if (err != 0) { + return err; + } + + void *dest = (char *)v->v_buf + (v->v_count * v->v_itemsz); + memcpy(dest, item, v->v_itemsz); + v->v_count++; + + return 0; +} + +static int vector_pop_back(struct vector *v) +{ + if (v->v_count > 0) { + v->v_count--; + } + + return 0; +} + +static void *vector_emplace_back(struct vector *v) +{ + int err = vector_reserve(v, v->v_count + 1); + if (err != 0) { + return NULL; + } + + void *dest = (char *)v->v_buf + (v->v_count * v->v_itemsz); + memset(dest, 0x0, v->v_itemsz); + v->v_count++; + + return dest; +} + +static void vector_destroy_items(struct vector *v, void (*dtor)(void *)) +{ + for (size_t i = 0; i < v->v_count; i++) { + void *item = (char *)v->v_buf + (i * v->v_itemsz); + dtor(item); + } +} + +static void vector_destroy(struct vector *v, void (*dtor)(void *)) +{ + if (dtor) { + vector_destroy_items(v, dtor); + } + + if (v->v_buf) { + free(v->v_buf); + } + + v->v_buf = NULL; + v->v_count = 0; + v->v_max = 0; +} + +int __mie_vector_push_back( + void **vector, void *item, size_t item_size, size_t *count, size_t *max) +{ + struct vector v = {}; + int err = 0; + + vector_wrap(&v, vector, item_size, count, max); + err = vector_push_back(&v, item); + vector_unwrap(&v, vector, item_size, count, max); + + return err; +} + +void __mie_vector_pop_back( + void **vector, size_t item_size, size_t *count, size_t *max) +{ + struct vector v = {}; + + vector_wrap(&v, vector, item_size, count, max); + vector_pop_back(&v); + vector_unwrap(&v, vector, item_size, count, max); +} + +void *__mie_vector_emplace_back( + void **vector, size_t item_size, size_t *count, size_t *max) +{ + struct vector v = {}; + void *p = 0; + + vector_wrap(&v, vector, item_size, count, max); + p = vector_emplace_back(&v); + vector_unwrap(&v, vector, item_size, count, max); + + return p; +} + +void __mie_vector_destroy( + void **vector, size_t item_size, size_t *count, size_t *max, + void (*dtor)(void *)) +{ + struct vector v = {}; + vector_wrap(&v, vector, item_size, count, max); + vector_destroy(&v, dtor); + vector_unwrap(&v, vector, item_size, count, max); +}