diff options
Diffstat (limited to 'src/array.c')
-rw-r--r-- | src/array.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..2920320 --- /dev/null +++ b/src/array.c @@ -0,0 +1,158 @@ +#include "array.h" +#include "utility.h" + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +typedef struct{ + size_t size; + uint use_count; + uint mem_count; + + char buf[]; +} VectorHeader; + +#define getHeader(X) ((VectorHeader*)(pChar(X)-sizeof(VectorHeader))) +#define getTotal2(X,Y) ((Y)*(X)+sizeof(VectorHeader)) +#define getTotal(X) getTotal2((X)->mem_count,(X)->size) + +/********************** initalize *************************/ +pvoid ctl_array_initX(ppvoid v, size_t size, uint count){ + VectorHeader *tmp; + + int mem = 0; + if(count >= 1) + for(mem = 1; mem < count; mem *= 2); + + tmp = (VectorHeader*)ctl_malloc(getTotal2(mem, size)); + + tmp->size = size; + tmp->use_count = count; + tmp->mem_count = mem; + if(v != NULL){ + *v = pVoid(tmp->buf); + } + return pVoid(tmp->buf); +} + +/******************** destructure *************************/ +pvoid ctl_array_freeX(ppvoid v){ + free(pVoid(getHeader(*v))); + *v = NULL; + return NULL; +} + +/******************** methods about get??? ****************/ +int ctl_array_getSizeX(ppvoid v){ + return getHeader(*v)->use_count; +} + +pcvoid ctl_array_getEntryX(ppvoid v, uint index){ + return pcVoid(pChar(*v) + getHeader(*v)->size * index); +} + +int ctl_array_getEntrySizeX(ppvoid v){ + return getHeader(*v)->size; +} + +/******************** methods about set??? ****************/ +int ctl_array_setSizeX(ppvoid v, uint count){ + VectorHeader *tmp = getHeader(*v); + + int mem = 0; + if(count >= 1) + for(mem = 1; mem < count; mem *= 2); + tmp->use_count = count; + tmp->mem_count = mem; + + tmp = (VectorHeader*)ctl_realloc(pVoid(tmp), getTotal(tmp)); + *v = pVoid(tmp->buf); + + return tmp->use_count; +} +pvoid ctl_array_setEntryX(ppvoid v, uint index, pcvoid data){ + VectorHeader *tmp = getHeader(*v); + memcpy(pVoid(tmp->buf + index * tmp->size), data, tmp->size); +} + +/************** add/del element on the back ***************/ +int ctl_array_addBackX(ppvoid v, pcvoid entry){ + VectorHeader *tmp = getHeader(*v); + + if(tmp->use_count + 1 > tmp->mem_count){ + if(tmp->mem_count == 0) tmp->mem_count = 1; + else tmp->mem_count *= 2; + tmp = (VectorHeader*)realloc(pVoid(tmp), getTotal(tmp)); + *v = pVoid(tmp->buf); + } + memcpy(tmp->buf + tmp->size * tmp->use_count, entry, tmp->size); + tmp->use_count++; + return tmp->use_count; +} +int ctl_array_delBackX(ppvoid v){ + VectorHeader *tmp = getHeader(*v); + + if((tmp->use_count - 1) * 2 < tmp->mem_count){ + tmp->mem_count /= 2; + tmp = (VectorHeader*)realloc(pVoid(tmp), getTotal(tmp)); + *v = pVoid(tmp->buf); + } + + tmp->use_count--; + return tmp->use_count; +} +//int ctl_array_addFrontX(ppvoid v, pcvoid entry); +//int ctl_array_delFrontX(ppvoid v); + +int ctl_array_catX(ppvoid v, ppcvoid v2){ + int count0 = getHeader(*v)->use_count; + int count2 = getHeader(*v2)->use_count; + ctl_array_setSize(v, count0 + count2); + int i; + for(i = 0; i < count2; i++) + ctl_array_setEntry(v, count0 + i, ctl_array_getEntry(v2, i)); + return count0 + count2; +} +pvoid ctl_array_copyX(ppvoid v, ppcvoid v2){ + VectorHeader* tmp = getHeader(*v2); + VectorHeader* p = (VectorHeader*)malloc(getTotal(tmp)); + memcpy(pVoid(p), pVoid(tmp), getTotal(tmp)); + if(v != NULL){ + if(*v != NULL){ + ctl_array_free(v); + } + *v = p->buf; + } + return p->buf; +} +int ctl_array_replaceX( ppvoid v , uint start1, uint length1, + ppcvoid v2, uint start2, int length2){ + int end1 = (int)start1 + length1 - 1; + int end2 = (int)start2 + abs(length2) - 1, step2 = 1; + if(length2 < 0){ + length2 *= -1; + step2 *= -1; + ctl_swap(int, start2, end2); + } + if (length1 < length2){ // need increase size + int sz0 = ctl_array_getSize(v); + int delta = length2 - length1; + ctl_array_setSize(v, sz0 + delta); + int i; + for(i = sz0 + delta - 1; i - delta > end1; i--){ + ctl_array_setEntry(v, i, ctl_array_getEntry(v, i - delta)); + } + }else if(length1 > length2){ // need decrease size + int sz0 = ctl_array_getSize(v); + int delta = length1 - length2; + int i; + for(i = end1 - delta + 1; i + delta < sz0; i++){ + ctl_array_setEntry(v, i, ctl_array_getEntry(v, i + delta)); + } + ctl_array_setSize(v, sz0 - delta); + } + for(end2 += step2; start2 != end2; start2 += step2, start1 += 1){ + ctl_array_setEntry(v, start1, ctl_array_getEntry(v2, start2)); + } +} |