Last active
January 20, 2020 07:03
-
-
Save justinmeiners/3999c2e25eb1689d46a9d1c55d6f8caa to your computer and use it in GitHub Desktop.
generic vector template in ANSI C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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