vtt2ass-cstyle/src/dyna.c

121 lines
2.5 KiB
C

#include "dyna.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
static void *dyna_elem_(const struct dyna *d, int64_t idx)
{
if (d->flags & DYNAFLAG_HEAPCOPY) {
return ((uint8_t*)d->data) + (sizeof(void*) * idx);
}
return ((uint8_t*)d->data) + (d->e_size * idx);
}
struct dyna *dyna_create(size_t e_size)
{
return dyna_create_size_flags(e_size, 64, DYNAFLAG_NONE);
}
struct dyna *dyna_create_size(size_t e_size, size_t init_size)
{
return dyna_create_size_flags(e_size, init_size, DYNAFLAG_NONE);
}
struct dyna *dyna_create_size_flags(size_t e_size, size_t init_size, enum dyna_flags flags)
{
size_t delem_size = e_size;
struct dyna *d = calloc(1, sizeof(*d));
if (d == NULL)
return NULL;
d->e_cap = init_size;
d->e_size = e_size;
d->flags = flags;
if (flags & DYNAFLAG_HEAPCOPY)
delem_size = sizeof(void*);
d->data = reallocarray(NULL, d->e_cap, delem_size);
if (d->data == NULL) {
free(d);
return NULL;
}
return d;
}
void dyna_destroy(struct dyna *dyna)
{
if (dyna->e_free_fn) {
for (int i = 0; i < dyna->e_idx; i++) {
void *elem = dyna_elem(dyna, i);
dyna->e_free_fn(elem);
if (dyna->flags & DYNAFLAG_HEAPCOPY)
free(elem);
}
}
if (dyna->data)
free(dyna->data);
if (dyna)
free(dyna);
}
void dyna_set_free_fn(struct dyna *d, dyna_free_fn fn)
{
d->e_free_fn = fn;
}
static int dyna_grow(struct dyna *d)
{
int new_cap = d->e_cap * 2;
size_t delem_size = (d->flags & DYNAFLAG_HEAPCOPY) ? sizeof(void*) : d->e_size;
void *new_data = reallocarray(d->data, new_cap, delem_size);
if (new_data == NULL)
return -1;
d->e_cap = new_cap;
d->data = new_data;
return 0;
}
void *dyna_append(struct dyna *d, void *elem)
{
void *dst = dyna_emplace(d);
memcpy(dst, elem, d->e_size);
return dst;
}
void *dyna_emplace(struct dyna *d)
{
if (d->e_idx >= d->e_cap) {
int e = dyna_grow(d);
assert(e == 0);
}
void *ptr = dyna_elem_(d, d->e_idx);
if (d->flags & DYNAFLAG_HEAPCOPY) {
void *hptr = malloc(d->e_size);
assert(hptr);
*(void**)ptr = hptr;
ptr = hptr;
}
d->e_idx++;
return ptr;
}
void *dyna_elem(const struct dyna *d, int64_t idx)
{
if (idx >= d->e_idx)
return NULL;
void *elemptr = dyna_elem_(d, idx);
if (d->flags & DYNAFLAG_HEAPCOPY) {
return *(void**)elemptr;
}
return elemptr;
}