mie: add macros for defining and using resizable vectors
This commit is contained in:
70
mie/include/mie/vector.h
Normal file
70
mie/include/mie/vector.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef MIE_VECTOR_H_
|
||||||
|
#define MIE_VECTOR_H_
|
||||||
|
|
||||||
|
#include <mie/misc.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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
|
||||||
154
mie/vector.c
Normal file
154
mie/vector.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <mie/vector.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user