diff options
Diffstat (limited to 'l4array.c')
-rw-r--r-- | l4array.c | 304 |
1 files changed, 179 insertions, 125 deletions
@@ -3,176 +3,230 @@ #include <stdlib.h> #include <string.h> -L4DA* l4da_create_setmax(int itemsize, int len, int maxlen){ - if(itemsize <= 0 || len < 0 || maxlen < len){ +LbsArray* lbs_array_new_with_max (size_t size, size_t max) { + if (size <= 0) { return NULL; } - L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); - if(arr == NULL){ + + LbsArray* array = malloc (sizeof (LbsArray)); + if (array == NULL) { return NULL; } - arr->arr_itemsize = itemsize; - arr->arr_curlen = len; - arr->arr_maxlen = maxlen; - if(maxlen != 0){ - arr->arr_data = malloc(itemsize * maxlen); - if(arr->arr_data == NULL){ - free(arr); + + if (max > 0) { + void* data = malloc (size * max); + if (data == NULL) { + free (array); return NULL; } - }else{ - arr->arr_data = NULL; + array->data = data; + } else { + array->data = NULL; } - return arr; -} -L4DA* l4da_create(int itemsize, int len){ - return l4da_create_setmax(itemsize, len, len); + array->free_func = NULL; + array->size = size; + array->len = max; + array->max = max; + array->ref_count = 1; + array->is_alloc = true; + + return array; } -void l4da_free(L4DA* arr){ - if(arr->arr_data != NULL){ - free(arr->arr_data); +int lbs_array_init_with_max (LbsArray* array, size_t size, size_t max) { + if (size <= 0) { + return -1; } - free(arr); -} -int l4da_pushback(L4DA* arr, const void* data){ - if((arr->arr_maxlen) < (arr->arr_curlen + 1)){ - if(arr->arr_maxlen != 0){ - if(l4da_setmax(arr, arr->arr_maxlen*2) < 0){ - return -1; - } - }else{ - if(l4da_setmax(arr, 1) < 0){ - return -1; - } + if (max > 0) { + void* data = malloc (size * max); + if (data == NULL) { + return -1; } + array->data = data; + } else { + array->data = NULL; } - memcpy(l4da_vp(arr, arr->arr_curlen), data, arr->arr_itemsize); - arr->arr_curlen++; + + array->free_func = NULL; + array->size = size; + array->len = max; + array->max = max; + array->ref_count = 1; + array->is_alloc = false; + return 0; } -int l4da_setlen(L4DA* arr, int len){ - if(len > (arr->arr_maxlen)){ - if(l4da_setmax(arr, len) < 0){ - return -1; - }else{ - arr->arr_curlen = len; +LbsArray* lbs_array_copy (LbsArray* dest, const LbsArray* src) { + if (dest == NULL) { + dest = lbs_array_new_with_max (src->size, src->max); + if (dest == NULL) { + return NULL; + } + } else { + if (lbs_array_init_with_max (dest, src->size, src->max) < 0) { + return NULL; } - }else{ - arr->arr_curlen = len; - return 0; } - return 0; + + dest->len = src->len; + dest->free_func = src->free_func; + memcpy (dest->data, src->data, src->size * src->len); + return dest; } -int l4da_setmax(L4DA* arr, int max){ - void* newptr; - if(arr->arr_data == NULL){ - newptr = malloc((arr->arr_itemsize)*max); - if(newptr == NULL){ - return -1; - }else{ - arr->arr_maxlen = max; - arr->arr_data = newptr; - return 0; - } +LbsArray* lbs_array_cat (LbsArray* dest, const LbsArray* more) { + if (dest == NULL) { + return lbs_array_copy (dest, more); } - newptr = realloc(arr->arr_data, (arr->arr_itemsize)*max); - if(newptr == NULL){ - return -1; - }else{ - arr->arr_maxlen = max; - arr->arr_data = newptr; + + if (dest->size != more->size) { + return NULL; } - return 0; + + int oldlen = dest->len; + if (lbs_array_set_len (dest, dest->len + more->len) < 0) { + return NULL; + } + + memcpy (lbs_array_vp (dest, oldlen), more->data, more->size * more->len); + return dest; } -int l4da_strip(L4DA* arr){ - if(arr->arr_data == NULL){ - return 0; +void* lbs_array_ref_generic (void* array_generic) { + LbsArray* array = LBS_ARRAY (array_generic); + int oldref = array->ref_count; + int newref = oldref + 1; + if (newref <= oldref) { + return NULL; } - L4DA* newptr; - /* 其實縮小空間營該一定會成功才對...... - * 不過還是保險一點,加個判斷式,別說 memory leak 是我害的 - * 當然也是避免編譯器一直跳 warning - */ - if((arr->arr_maxlen) > (arr->arr_curlen)){ - arr->arr_maxlen = arr->arr_curlen; - newptr = realloc(arr->arr_data, (arr->arr_curlen)*(arr->arr_itemsize)); - if(newptr == NULL){ - return -1; + + array->ref_count = newref; + return array; +} + +void lbs_array_unref_generic (void* array_generic) { + LbsArray* array = LBS_ARRAY (array_generic); + array->ref_count--; + if (array->ref_count <= 0) { + lbs_array_free (array); + } +} + +void lbs_array_free_generic (void* array_generic) { + LbsArray* array = LBS_ARRAY (array_generic); + if (array->free_func != NULL) { + int i = 0; + char* d = array->data; + for (; i < array->len; i++, d += array->size) { + (*(array->free_func)) (*((void**)d)); } - arr->arr_data = newptr; } - return 0; + free (array->data); + if (array->is_alloc) { + free (array); + } } -/* 基本上直接玩 struct 的函式還是少用吧 */ -void* l4da_drop_struct(L4DA* arr){ - void* toreturn = arr->arr_data; - free(arr); - return toreturn; +void* lbs_array_drop_struct (LbsArray* array) { + if (!array->is_alloc) { + return array->data; + } + + void* data = array->data; + free (array); + return data; } -L4DA* l4da_make_struct(void* data, int itemsize, int len, int maxlen){ - if(itemsize <= 0 || len < 0 || maxlen < len){ - return NULL; +LbsArray* lbs_array_make_struct (LbsArray* array, + size_t size, size_t len, size_t max, void* data) { + + if (array == NULL) { + array = lbs_array_new (size); + if (array == NULL) { + return NULL; + } + } else { + if (lbs_array_init (array, size) < 0) { + return NULL; + } } - L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); - if(arr == NULL){ - return NULL; + + array->len = len; + array->max = max; + array->data = data; + return array; +} + +int lbs_array_set_len (LbsArray* array, size_t len) { + if (len > (array->max)){ + if (lbs_array_set_max (array, len) < 0) { + return -1; + } else { + array->len = len; + } + } else { + array->len = len; + return 0; } - arr->arr_itemsize = itemsize; - arr->arr_curlen = len; - arr->arr_maxlen = maxlen; - arr->arr_data = data; - return arr; + return 0; } -L4DA* l4da_dup(const L4DA* arr){ - L4DA* newarr = l4da_create_setmax( - l4da_itemsize(arr), l4da_getlen(arr), l4da_getmax(arr)); - if(newarr == NULL){ - return NULL; +int lbs_array_set_max (LbsArray* array, size_t max) { + void* ptr = realloc (array->data, array->size * max); + if (ptr == NULL) { + return -1; } - memcpy(newarr->arr_data, arr->arr_data, - l4da_getlen(arr) * l4da_itemsize(arr)); - return newarr; + + array->max = max; + array->data = ptr; + return 0; } -int l4da_combine(L4DA* arr, const L4DA* att){ - if(l4da_itemsize(arr) != l4da_itemsize(att)){ - return -2; +int lbs_array_append_ptr (LbsArray* array, const void* ptr) { + return lbs_array_append_data (array, &ptr); +} + +int lbs_array_append_data (LbsArray* array, const void* data) { + if (array->max < array->len + 1) { + if (array->max > 0){ + if (lbs_array_set_max (array, array->max * 2) < 0) { + return -1; + } + } else { + if (lbs_array_set_max (array, 1) < 0){ + return -1; + } + } } - if(l4da_setlen(arr, l4da_getlen(arr) + l4da_getlen(att)) < 0){ + + memcpy (lbs_array_vp (array, array->len), data, array->size); + array->len++; + return 0; +} + +int lbs_array_remove (LbsArray* array) { + if (array->len <= 0) { return -1; } - memcpy(l4da_vp(arr, l4da_getlen(arr)), att->arr_data, - l4da_getlen(att) * l4da_itemsize(att)); + + array->len--; + if (array->len < array->max * 2) { + lbs_array_minimize (array); + } return 0; } -L4DA* l4da_filereadline_delim(FILE* infile, int chr){ - L4DA* newarr = l4da_create(1, 0); - if(newarr == NULL){ - return NULL; - } - int c; - char towrite; - while((c = getc(infile)) != chr && !feof(infile)){ - towrite = c; - if(l4da_pushback(newarr, (void*)&towrite) < 0){ - l4da_free(newarr); - return NULL; +int lbs_array_minimize (LbsArray* array) { + if (array->max > array->len) { + void* ptr = realloc (array->data, array->size * array->len); + if (ptr == NULL) { + return -1; } + array->max = array->len; + array->data = ptr; } - towrite = '\0'; - if(l4da_pushback(newarr, (void*)&towrite) < 0){ - l4da_free(newarr); - return NULL; - } - return newarr; + return 0; } |