79 lines
1.6 KiB
C
79 lines
1.6 KiB
C
#include "dynbuf.h"
|
|
#include <stdio.h>
|
|
|
|
#ifndef GROWTH_FACTOR
|
|
#define GROWTH_FACTOR 2
|
|
#endif
|
|
|
|
#ifndef INITIAL_CAPACITY
|
|
#define INITIAL_CAPACITY 4
|
|
#endif
|
|
|
|
#ifdef GROWTH_POW2
|
|
#define ROUND_UP_POW2(x) round_up_pow2(x)
|
|
|
|
static inline int round_up_pow2(int x) {
|
|
if (x <= 1)
|
|
return 1;
|
|
|
|
x--;
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
return x + 1;
|
|
}
|
|
#else
|
|
#define ROUND_UP_POW2(x) (x)
|
|
#endif
|
|
|
|
void dynbuf_init(Dynbuf *v, size_t elem_size) {
|
|
v->elem_size = elem_size;
|
|
v->length = 0;
|
|
v->capacity = INITIAL_CAPACITY;
|
|
v->data = malloc(v->capacity * elem_size);
|
|
assert(v->data != NULL);
|
|
}
|
|
|
|
void dynbuf_free(Dynbuf *v) {
|
|
free(v->data);
|
|
v->data = NULL;
|
|
v->length = 0;
|
|
v->capacity = 0;
|
|
v->elem_size = 0;
|
|
}
|
|
|
|
void dynbuf_push(Dynbuf *v, const void *elem) {
|
|
if (v->length == v->capacity) {
|
|
dynbuf_resize(v, ROUND_UP_POW2(v->capacity * GROWTH_FACTOR));
|
|
}
|
|
|
|
memcpy((char *)v->data + v->length * v->elem_size, elem, v->elem_size);
|
|
v->length++;
|
|
}
|
|
|
|
void dynbuf_resize(Dynbuf *v, size_t newcap) {
|
|
printf("Resize to %zu\n", newcap);
|
|
|
|
if (newcap > v->capacity) {
|
|
v->capacity = newcap;
|
|
v->data = realloc(v->data, v->capacity * v->elem_size);
|
|
assert(v->data != NULL);
|
|
}
|
|
}
|
|
|
|
void dynbuf_pop(Dynbuf *v) {
|
|
if (v->length > 0) {
|
|
v->length--;
|
|
}
|
|
}
|
|
|
|
void *dynbuf_get(Dynbuf *v, size_t index) {
|
|
assert(index < v->length);
|
|
return (char *)v->data + index * v->elem_size;
|
|
}
|
|
|
|
inline size_t dynbuf_size(const Dynbuf *v) { return v->length; }
|
|
|
|
inline size_t dynbuf_capacity(const Dynbuf *v) { return v->capacity; }
|