#include #include #include #include "config.h" #include "tools/dynarray.h" /* * Dynamic array starting size in bytes. Will be at least one item, if * it's smaller than it. */ #ifndef DYNARR_SSIZE #define DYNARR_SSIZE 1024 #endif /* Dynamic array */ dynarray *dynarray_init(size_t isize, const void *dflt) { uint32_t nsize; dynarray *d = (dynarray *)malloc(sizeof (dynarray)); if (!d) return NULL; d->isize = isize; d->count = 0; nsize = DYNARR_SSIZE/isize; if (!nsize) nsize = 1; d->dflt = malloc(isize); if (!d->dflt) return NULL; memcpy(d->dflt, dflt, isize); d->data = NULL; if (!dynarray_resize(d, nsize)) return NULL; return d; } void dynarray_del(dynarray *d, const uint32_t pos, const uint32_t nitems) { assert(d); assert(pos + nitems < d->count); /* Copy the data above the deleted area onto it */ memmove((void *)dynarray_peek(d, pos), dynarray_peek(d, pos + nitems), \ (d->count - pos - nitems) * d->isize); d->count -= nitems; } void dynarray_free(dynarray **d) { assert(d); assert(*d); free((*d)->data); free(*d); *d = NULL; } int dynarray_put(dynarray *d, const uint32_t pos, const void *n, const uint32_t nitems) { uint32_t i; assert(d); if (!nitems) return 1; if (pos + nitems > d->avail) { /* * This should be slightly less than 2x the expected size. Adding * larger vectors will grow the table in increments of its size * before addition. Should be more efficient in case of bulk * addition and maybe less wasteful. */ d->avail += (pos + nitems + 1) * 1.5 / d->avail * d->avail; /* Do the resizin on our own, fill only required elements */ if (!(d->data = (char *)realloc(d->data, d->avail * d->isize))) return 0; /* Fill empty fields with defaults */ for (i = d->count; i < pos; i++) memcpy(d->data + i * d->isize, d->dflt, d->isize); } /* Copy the items */ memmove(d->data + pos * d->isize, n, nitems * d->isize); if (d->count < pos + nitems) d->count = pos + nitems; return 1; } int dynarray_append(dynarray *d, const void *n, const uint32_t nitems) { assert(d); return dynarray_put(d, d->count, n, nitems); } int dynarray_insert(dynarray *d, const uint32_t pos, const void *n, const uint32_t nitems) { assert(d); if (!nitems) return 1; if (pos > d->count) /* Should be the same */ return dynarray_put(d, pos, n, nitems); if (d->count + nitems > d->avail) { d->avail += (d->count + nitems + 1) * 1.5 / d->avail * d->avail; /* Do the resizing on our own - no default-filling */ if (!(d->data = (char *)realloc(d->data, d->avail * d->isize))) return 0; } /* Move the objects in the path */ memmove(d->data + (pos + nitems) * d->isize, d->data + pos * d->isize, \ (d->count - pos) * d->isize); /* Copy the data */ memmove(d->data + pos * d->isize, n, nitems * d->isize); d->count += nitems; return 1; } const void *dynarray_peek(const dynarray *d, const uint32_t pos) { if (pos > d->count) return NULL; return d->data + pos * d->isize; } void *dynarray_get(const dynarray *d, const uint32_t pos, const uint32_t nitems) { void *res; if (!nitems) return NULL; if (d->count < pos + nitems) return NULL; if (!(res = malloc(nitems * d->isize))) return NULL; memcpy(res, dynarray_peek(d, pos), nitems * d->isize); return res; } int dynarray_resize(dynarray *d, const uint32_t nitems) { uint32_t i; assert(d); if (!(d->data = (char *)realloc(d->data, nitems * d->isize))) return 0; if (d->avail < nitems) /* Fill with default items */ for (i = 0; i < nitems - d->avail; i++) memcpy(d->data + d->avail + i, d->dflt, d->isize); d->avail = nitems; if (d->count > d->avail) d->count = d->avail; return 1; }