Skip to content

Instantly share code, notes, and snippets.

@justinmeiners
Last active January 20, 2020 07:03
Show Gist options
  • Save justinmeiners/3999c2e25eb1689d46a9d1c55d6f8caa to your computer and use it in GitHub Desktop.
Save justinmeiners/3999c2e25eb1689d46a9d1c55d6f8caa to your computer and use it in GitHub Desktop.
generic vector template in ANSI C
/*
https://gist.github.com/pervognsen/c56d4ddce94fbef3c80e228b39efc028
https://gist.github.com/pervognsen/6f295f356010186f3c350f31fbeec28b
*/
/*
EXAMPLE
#define VEC_NAME vec_int
#define VEC_TYPE int
#define VEC_IMPLEMENTATION 1
#include "vector.h"
...
vec_int v;
vec_int_init(&v);
int i;
for (i = 0; i < 128; ++i)
{
vec_int_push(&v, i);
printf("%i ", v.capacity);
}
*/
#ifndef VEC_NAME
#error "must define vector name"
#endif
#ifndef VEC_TYPE
#error "must define vector type"
#endif
#include <stdlib.h>
#include <assert.h>
/* Two levels of macros to expand NAME variables.
See: https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing */
#define INNER_NS(NAME, FUNC) NAME ## _ ## FUNC
#define NS(NAME, FUNC) INNER_NS(NAME, FUNC)
typedef struct
{
VEC_TYPE* data;
size_t size;
size_t capacity;
} VEC_NAME;
void NS(VEC_NAME, init)(VEC_NAME* v);
void NS(VEC_NAME, init_opt)(VEC_NAME* v, size_t capacity);
void NS(VEC_NAME, shutdown)(VEC_NAME* v);
void NS(VEC_NAME, push)(VEC_NAME* v, VEC_TYPE e);
VEC_TYPE NS(VEC_NAME, pop)(VEC_NAME* v);
void NS(VEC_NAME, reserve)(VEC_NAME* v, size_t capacity);
#ifdef VEC_IMPLEMENTATION
void NS(VEC_NAME, init)(VEC_NAME* v)
{
NS(VEC_NAME, init_opt)(v, 16);
}
void NS(VEC_NAME, init_opt)(VEC_NAME* v, size_t capacity)
{
v->capacity = capacity;
v->size = 0;
v->data = malloc(sizeof(VEC_TYPE) * capacity);
}
void NS(VEC_NAME, shutdown)(VEC_NAME* v)
{
free(v->data);
}
void NS(VEC_NAME, push)(VEC_NAME* v, VEC_TYPE e)
{
if (v->size + 1 > v->capacity)
{
v->capacity = (v->capacity * 3) / 2;
v->data = realloc(v->data, sizeof(VEC_TYPE) * v->capacity);
}
v->data[v->size++] = e;
}
VEC_TYPE NS(VEC_NAME, pop)(VEC_NAME* v)
{
assert(v->size > 0);
VEC_TYPE r = v->data[--v->size];
if (v->size > 16 && v->size <= v->capacity / 4)
{
v->capacity = v->capacity / 2;
v->data = realloc(v->data, sizeof(VEC_TYPE) * v->capacity);
}
return r;
}
void NS(VEC_NAME, reserve)(VEC_NAME* v, size_t capacity)
{
if (capacity <= v->capacity) return;
v->capacity = capacity;
v->data = realloc(v->data, sizeof(VEC_TYPE) * v->capacity);
}
#endif
#undef VEC_NAME
#undef VEC_TYPE
#undef NS
#undef INNER_NS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment