aboutsummaryrefslogtreecommitdiffstats
path: root/l4array.c
diff options
context:
space:
mode:
Diffstat (limited to 'l4array.c')
-rw-r--r--l4array.c304
1 files changed, 179 insertions, 125 deletions
diff --git a/l4array.c b/l4array.c
index b57c021..fed2876 100644
--- a/l4array.c
+++ b/l4array.c
@@ -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;
}