X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fdarray.c;fp=src%2Fdarray.c;h=66c071524d429627556e94d2eeaa61c34a3c60b8;hp=0000000000000000000000000000000000000000;hb=dfc6ebacd7bcc1e6b9e7168c3e4824d241d2d5c8;hpb=0aeee13aa695ec617ec22253824f17209660bd39 diff --git a/src/darray.c b/src/darray.c new file mode 100644 index 0000000..66c0715 --- /dev/null +++ b/src/darray.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include "darray.h" +#include "util.h" + + +/* The array descriptor keeps auxilliary information needed to manipulate + * the dynamic array. It's allocated adjacent to the array buffer. + */ +struct arrdesc { + int nelem, szelem; + int max_elem; + int bufsz; /* not including the descriptor */ +}; + +#define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc))) + +void *darr_alloc(int elem, int szelem) +{ + struct arrdesc *desc; + + desc = malloc_nf(elem * szelem + sizeof *desc); + desc->nelem = desc->max_elem = elem; + desc->szelem = szelem; + desc->bufsz = elem * szelem; + return (char*)desc + sizeof *desc; +} + +void darr_free(void *da) +{ + if(da) { + free(DESC(da)); + } +} + +void *darr_resize_impl(void *da, int elem) +{ + int newsz; + struct arrdesc *desc; + + if(!da) return 0; + desc = DESC(da); + + newsz = desc->szelem * elem; + desc = realloc_nf(desc, newsz + sizeof *desc); + + desc->nelem = desc->max_elem = elem; + desc->bufsz = newsz; + return (char*)desc + sizeof *desc; +} + +int darr_empty(void *da) +{ + return DESC(da)->nelem ? 0 : 1; +} + +int darr_size(void *da) +{ + return DESC(da)->nelem; +} + + +void *darr_clear_impl(void *da) +{ + return darr_resize_impl(da, 0); +} + +/* stack semantics */ +void *darr_push_impl(void *da, void *item) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(nelem >= desc->max_elem) { + /* need to resize */ + int newsz = desc->max_elem ? desc->max_elem * 2 : 1; + + da = darr_resize_impl(da, newsz); + desc = DESC(da); + desc->nelem = nelem; + } + + if(item) { + memcpy((char*)da + desc->nelem * desc->szelem, item, desc->szelem); + } + desc->nelem++; + return da; +} + +void *darr_pop_impl(void *da) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(!nelem) return da; + + if(nelem <= desc->max_elem / 3) { + /* reclaim space */ + int newsz = desc->max_elem / 2; + + da = darr_resize_impl(da, newsz); + desc = DESC(da); + desc->nelem = nelem; + } + desc->nelem--; + + return da; +} + +void *darr_finalize(void *da) +{ + struct arrdesc *desc = DESC(da); + memmove(desc, da, desc->bufsz); + return desc; +}