From 218d5b0040f5438b383b3541ba208d9b51d4b9dd Mon Sep 17 00:00:00 2001 From: LAN-TW <lantw44@gmail.com> Date: Fri, 29 Nov 2013 14:06:55 +0800 Subject: Refactor build system and combine some files --- .gitignore | 14 ++++ Makefile | 21 ++--- l4arg/Makefile | 24 ------ l4arg/l4arg.h | 28 ------- l4arg/qarg.c | 54 ------------- l4arg/toargv.c | 111 ------------------------- l4bds/Makefile | 24 ------ l4bds/l4bds.h | 66 --------------- l4bds/list.c | 235 ----------------------------------------------------- l4darr/Makefile | 24 ------ l4darr/d1array.c | 132 ------------------------------ l4darr/d1arrstr.c | 47 ----------- l4darr/d2array.c | 26 ------ l4darr/l4darr.h | 64 --------------- src/Makefile | 67 ++++++++++++++++ src/l4arg.c | 163 +++++++++++++++++++++++++++++++++++++ src/l4arg.h | 28 +++++++ src/l4array.c | 178 ++++++++++++++++++++++++++++++++++++++++ src/l4array.h | 43 ++++++++++ src/l4array2.c | 26 ++++++ src/l4array2.h | 25 ++++++ src/l4list.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/l4list.h | 66 +++++++++++++++ 23 files changed, 854 insertions(+), 848 deletions(-) create mode 100644 .gitignore delete mode 100644 l4arg/Makefile delete mode 100644 l4arg/l4arg.h delete mode 100644 l4arg/qarg.c delete mode 100644 l4arg/toargv.c delete mode 100644 l4bds/Makefile delete mode 100644 l4bds/l4bds.h delete mode 100644 l4bds/list.c delete mode 100644 l4darr/Makefile delete mode 100644 l4darr/d1array.c delete mode 100644 l4darr/d1arrstr.c delete mode 100644 l4darr/d2array.c delete mode 100644 l4darr/l4darr.h create mode 100644 src/Makefile create mode 100644 src/l4arg.c create mode 100644 src/l4arg.h create mode 100644 src/l4array.c create mode 100644 src/l4array.h create mode 100644 src/l4array2.c create mode 100644 src/l4array2.h create mode 100644 src/l4list.c create mode 100644 src/l4list.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..305b898 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.deps +.libs +*~ +*.o +*.lo +*.a +*.la +*.so +*.tar +*.tar.* +*.swp +tags +cscope.out +\#*\# diff --git a/Makefile b/Makefile index b0dd0c8..2667da9 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,13 @@ -.PHONY: all clean install uninstall +.PHONY: all clean install uninstall deinstall remove all: - $(MAKE) -C l4darr all - $(MAKE) -C l4bds all - $(MAKE) -C l4arg all + $(MAKE) -C src all clean: - $(MAKE) -C l4darr clean - $(MAKE) -C l4bds clean - $(MAKE) -C l4arg clean + $(MAKE) -C src clean install: - $(MAKE) -C l4darr install - $(MAKE) -C l4bds install - $(MAKE) -C l4arg install + $(MAKE) -C src install uninstall: - $(MAKE) -C l4darr uninstall - $(MAKE) -C l4bds uninstall - $(MAKE) -C l4arg uninstall + $(MAKE) -C src uninstall + +deinstall: uninstall +remove: uninstall diff --git a/l4arg/Makefile b/l4arg/Makefile deleted file mode 100644 index 0f2ffe3..0000000 --- a/l4arg/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC=cc -AR=ar -RM=rm -f -INSTALL=install -m 644 -LOCAL_CFLAGS=-g -CFLAGS=-Wall -I. -I../l4darr $(LOCAL_CFLAGS) -OBJ=toargv.o qarg.o -LIBFILE=libl4arg.a -DESTDIR=/ -PREFIX=/usr/local -LIBDIR=$(DESTDIR)/$(PREFIX)/lib - -.PHONY: all clean - -all: $(LIBFILE) -$(LIBFILE): $(OBJ) - $(AR) rcs $(LIBFILE) $(OBJ) -clean: - $(RM) $(LIBFILE) $(OBJ) -install: - mkdir -p $(LIBDIR) - $(INSTALL) $(LIBFILE) $(LIBDIR) -uninstall: - $(RM) $(LIBDIR)/$(LIBFILE) diff --git a/l4arg/l4arg.h b/l4arg/l4arg.h deleted file mode 100644 index 68352c8..0000000 --- a/l4arg/l4arg.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef L4LIB_ARG_PARSER -#define L4LIB_ARG_PARSER - -#ifdef __cplusplus -extern "C" { -#endif - -char** l4arg_toargv(const char*, const char*, const char*, const char*); -void l4arg_toargv_free(char**); - -typedef struct l4lib_qarg { - char* arg_name; - char* arg_value; -} L4QARG; - -L4QARG* l4qarg_parse(const char*); -void l4qarg_free(L4QARG*); -#define l4qarg_n(qargitem) ((qargitem).arg_name) -#define l4qarg_v(qargitem) ((qargitem).arg_value) -#define l4qarg_hasvalue(qargitem) (((qargitem).arg_value != NULL)) -#define l4qarg_end(qargitem) \ - ((((qargitem).arg_name) == NULL) && (((qargitem).arg_value) == NULL)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/l4arg/qarg.c b/l4arg/qarg.c deleted file mode 100644 index 412967c..0000000 --- a/l4arg/qarg.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <l4arg.h> - -/* 為什麼叫做 qarg 呢?因為這是用來解析很像 QEMU 命令列參數的參數 */ - -L4QARG* l4qarg_parse(const char* str){ - char** pargv = l4arg_toargv(str, ",", "\"\'", "\\"); - if(pargv == NULL){ - return NULL; - } - int i, allc; - L4QARG* qargarr; - char* pos; - for(i=0; pargv[i]!=NULL; i++); - allc = i + 1; - qargarr = (L4QARG*) malloc(sizeof(L4QARG) * allc); - if(qargarr == NULL){ - l4arg_toargv_free(pargv); - return NULL; - } - for(i=0; pargv[i]!=NULL; i++){ - pos = strchr(pargv[i], '='); - if(pos == NULL){ - qargarr[i].arg_name = pargv[i]; - qargarr[i].arg_value = NULL; - }else{ - *pos = '\0'; - qargarr[i].arg_name = pargv[i]; - pos++; - qargarr[i].arg_value = (char*) malloc(strlen(pos)+1); - if(qargarr[i].arg_value == NULL){ - l4arg_toargv_free(pargv); - return NULL; - } - strcpy(qargarr[i].arg_value, pos); - } - } - free(pargv); - qargarr[i].arg_name = NULL; - qargarr[i].arg_value = NULL; - return qargarr; -} - -void l4qarg_free(L4QARG* qarg){ - int i; - for(i=0; !(qarg[i].arg_name == NULL && qarg[i].arg_value == NULL); i++){ - free(qarg[i].arg_name); - if(qarg[i].arg_value != NULL){ - free(qarg[i].arg_value); - } - } - free(qarg); -} diff --git a/l4arg/toargv.c b/l4arg/toargv.c deleted file mode 100644 index 433ad1a..0000000 --- a/l4arg/toargv.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <string.h> -#include <stdlib.h> -#include <l4arg.h> -#include <l4darr.h> - -/* 基本上優先順序是 escape -> quoting -> delimiter */ - -#define abort_l4arg_toargv \ - do{ \ - l4da_free(parr); \ - l4da_free(tmpstr); \ - return NULL; \ - }while(0) - -char** l4arg_toargv(const char* str, - const char* delim, const char* quoting, const char* esc){ - int i; - char escaped = 0, quoted = 0, delimed = 0; - L4DA* parr; - L4DA* tmpstr; - char* addstr, tmpchar; - char** rval; - parr = l4da_create(sizeof(char*), 0); - if(parr == NULL){ - return NULL; - } - tmpstr = l4da_create(sizeof(char), 0); - if(tmpstr == NULL){ - l4da_free(parr); - return NULL; - } - for(i=0; str[i]!='\0'; i++){ - if(escaped){ - if(l4da_pushback(tmpstr, &str[i]) < 0){ - abort_l4arg_toargv; - } - escaped = 0; - delimed = 0; - continue; - } - if(quoted){ - if(strchr(quoting, str[i]) != NULL){ - quoted = 0; - continue; - } - if(l4da_pushback(tmpstr, &str[i]) < 0){ - abort_l4arg_toargv; - } - delimed = 0; - continue; - } - if(strchr(esc, str[i]) != NULL){ - escaped = 1; - continue; - } - if(strchr(quoting, str[i]) != NULL){ - quoted = 1; - continue; - } - if(strchr(delim, str[i]) != NULL){ - if(l4da_getlen(tmpstr) > 0){ - tmpchar = '\0'; - if(l4da_pushback(tmpstr, &tmpchar) < 0){ - abort_l4arg_toargv; - } - addstr = (char*)l4da_drop_struct(tmpstr); - if(l4da_pushback(parr, &addstr) < 0){ - l4da_free(parr); - return NULL; - } - tmpstr = l4da_create(sizeof(char), 0); - if(tmpstr == NULL){ - l4da_free(parr); - return NULL; - } - } - delimed = 1; - continue; - } - if(l4da_pushback(tmpstr, &str[i]) < 0){ - abort_l4arg_toargv; - } - delimed = 0; - } - if(!delimed){ - tmpchar = '\0'; - if(l4da_pushback(tmpstr, &tmpchar) < 0){ - abort_l4arg_toargv; - } - addstr = (char*)l4da_drop_struct(tmpstr); - if(l4da_pushback(parr, &addstr) < 0){ - l4da_free(parr); - return NULL; - } - } - addstr = NULL; - if(l4da_pushback(parr, &addstr) < 0){ - l4da_free(parr); - return NULL; - } - rval = (char**)l4da_drop_struct(parr); - return rval; -} - -void l4arg_toargv_free(char** pargv){ - int i; - for(i=0; pargv[i]!=NULL; i++){ - free(pargv[i]); - } - free(pargv); -} diff --git a/l4bds/Makefile b/l4bds/Makefile deleted file mode 100644 index c4c2caa..0000000 --- a/l4bds/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC=cc -AR=ar -RM=rm -f -INSTALL=install -m 644 -LOCAL_CFLAGS=-g -CFLAGS=-Wall -I. $(LOCAL_CFLAGS) -OBJ=list.o -LIBFILE=libl4bds.a -DESTDIR=/ -PREFIX=/usr/local -LIBDIR=$(DESTDIR)/$(PREFIX)/lib - -.PHONY: all clean - -all: $(LIBFILE) -$(LIBFILE): $(OBJ) - $(AR) rcs $(LIBFILE) $(OBJ) -clean: - $(RM) $(LIBFILE) $(OBJ) -install: - mkdir -p $(LIBDIR) - $(INSTALL) -c $(LIBFILE) $(LIBDIR) -uninstall: - $(RM) $(LIBDIR)/$(LIBFILE) diff --git a/l4bds/l4bds.h b/l4bds/l4bds.h deleted file mode 100644 index 2ad7199..0000000 --- a/l4bds/l4bds.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef L4LIB_BASIC_DATA_STRUCTURE -#define L4LIB_BASIC_DATA_STRUCTURE - -/*********** list ***********/ - -typedef struct l4lib_list_node{ /* list 中每一個項目用的資料結構,會有很多個 */ - struct l4lib_list_node* node_prev; - struct l4lib_list_node* node_next; - void* node_data; - int node_data_size; -} L4LLNODE; - -typedef struct l4lib_list{ /* 管理 list 用的,每個 list 只有一個 */ - struct l4lib_list_node* list_first; - struct l4lib_list_node* list_last; - int list_len; -} L4LL; - -L4LL* l4ll_create(void); -void l4ll_free(L4LL*); -#define l4ll_prev(node) ((node)->node_prev) -#define l4ll_next(node) ((node)->node_next) -#define l4ll_len(list) ((list)->list_len) -#define l4ll_node_back(list) ((list)->list_last) -#define l4ll_node_front(list) ((list)->list_first) -#define l4ll_data(node) ((node)->node_data) -#define l4ll_datasize(node) ((node)->node_data_size) -L4LLNODE* l4ll_insert_prev(L4LL*, L4LLNODE*, const void*, int); -L4LLNODE* l4ll_insert_next(L4LL*, L4LLNODE*, const void*, int); -void l4ll_remove(L4LL*, L4LLNODE*); -#define l4ll_pushback(list,data,size) \ - (l4ll_insert_next((list),(l4ll_node_back(list)),(data),(size))) -#define l4ll_pushfront(list,data,size) \ - (l4ll_insert_prev((list),(l4ll_node_front(list)),(data),(size))) -#define l4ll_popback(list) \ - (l4ll_remove((list),(l4ll_node_back((list))))) -#define l4ll_popfront(list) \ - (l4ll_remove((list),(l4ll_node_front((list))))) -L4LLNODE* l4ll_goto(L4LLNODE*, int); - -/*********** stack ***********/ - -typedef L4LL L4STACK; -#define l4stack_create() (l4ll_create()) -#define l4stack_free(list) (l4ll_free(list)) -#define l4stack_push(list,data,size) (l4ll_pushback((list),(data),(size))) -#define l4stack_pop(list) (l4ll_popback(list)) -#define l4stack_len(list) (l4ll_len(list)) -#define l4stack_data(list) (l4ll_data(l4ll_node_back(list))) -#define l4stack_datasize(list) (l4ll_datasize(l4ll_node_back(list))) - -/*********** queue ***********/ - -typedef L4LL L4QUEUE; -#define l4queue_create() (l4ll_create()) -#define l4queue_free(list) (l4ll_free(list)) -#define l4queue_push(list,data,size) (l4ll_pushback((list),(data),(size))) -#define l4queue_pop(list) (l4ll_popfront(list)) -#define l4queue_len(list) (l4ll_len(list)) -#define l4queue_frontdata(list) (l4ll_data(l4ll_node_front(list))) -#define l4queue_frontdatasize(list) (l4ll_datasize(l4ll_node_front(list))) -#define l4queue_backdata(list) (l4ll_data(l4ll_node_back(list))) -#define l4queue_backdatasize(list) (l4ll_datasize(l4ll_node_back(list))) -#define l4queue_data(list) (l4queue_frontdata(list)) -#define l4queue_datasize(list) (l4queue_frontdatasize(list)) -#endif diff --git a/l4bds/list.c b/l4bds/list.c deleted file mode 100644 index 09ec746..0000000 --- a/l4bds/list.c +++ /dev/null @@ -1,235 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <l4bds.h> - -L4LL* l4ll_create(void){ - L4LL* newlist = (L4LL*)malloc(sizeof(L4LL)); - if(newlist == NULL){ - return NULL; - } - newlist->list_first = NULL; - newlist->list_last = NULL; - newlist->list_len = 0; - return newlist; -} - -void l4ll_free(L4LL* oldlist){ - if(oldlist->list_len <= 0){ - free(oldlist); - return; - } - L4LLNODE* i; - L4LLNODE* next; - for(i=oldlist->list_first; i!=NULL; i=next){ - next = i->node_next; - if(i->node_data_size){ /* 只要資料大小不為零,就還要釋放資料區 */ - free(i->node_data); - } - free(i); - } - free(oldlist); -} - -static L4LLNODE* -l4ll_initfirst(L4LL* list, const void* data, int size){ - /* 插入第一個資料,如果 list 不是空的就別用! - * 否則會造成資料結構混亂和 memory leak */ - L4LLNODE* node = (L4LLNODE*)malloc(sizeof(L4LLNODE)); - if(node == NULL){ - return NULL; - } - void* newdata; - if(size != 0){ - newdata = malloc(size); - if(newdata == NULL){ - free(node); - return NULL; - } - memcpy(newdata, data, size); - } - list->list_first = node; - list->list_last = node; - list->list_len = 1; - node->node_prev = NULL; - node->node_next = NULL; - node->node_data = (size != 0) ? newdata : NULL; - node->node_data_size = size; - return node; -} - -L4LLNODE* l4ll_insert_prev(L4LL* list, L4LLNODE* node, - const void* data, int size){ - /* list 送 NULL 來的我不理它,就自己去 segfault 吧 - * node 送 NULL 來只能在 list 是空的時候用 */ - if(list->list_len == 0){ - return l4ll_initfirst(list, data, size); - } - L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE)); - if(newnode == NULL){ - return NULL; - } - void* newdata; - if(size != 0){ - newdata = malloc(size); - if(newdata == NULL){ - free(newnode); - return NULL; - } - memcpy(newdata, data, size); - } - list->list_len++; - if(list->list_first == node){ /* 如果是第一個,那要修改 list_first */ - list->list_first = newnode; - } - L4LLNODE* oldprev = node->node_prev; - node->node_prev = newnode; - newnode->node_next = node; - newnode->node_prev = oldprev; - if(oldprev != NULL){ - oldprev->node_next = newnode; - } - newnode->node_data = (size != 0) ? newdata : NULL; - newnode->node_data_size = size; - return newnode; -} - -L4LLNODE* l4ll_insert_next(L4LL* list, L4LLNODE* node, - const void* data, int size){ - /* 基本上同 l4ll_insert_prev */ - if(list->list_len == 0){ - return l4ll_initfirst(list, data, size); - } - L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE)); - if(newnode == NULL){ - return NULL; - } - void* newdata; - if(size != 0){ - newdata = malloc(size); - if(newdata == NULL){ - free(newnode); - return NULL; - } - memcpy(newdata, data, size); - } - list->list_len++; - if(list->list_last == node){ - list->list_last = newnode; - } - L4LLNODE* oldnext = node->node_next; - node->node_next = newnode; - newnode->node_prev = node; - newnode->node_next = oldnext; - if(oldnext != NULL){ - oldnext->node_prev = newnode; - } - newnode->node_data = (size != 0) ? newdata : NULL; - newnode->node_data_size = size; - return newnode; -} - -void l4ll_remove(L4LL* list, L4LLNODE* node){ - /* 不要在 node 傳 NULL,這一點意義也沒有且我不知道會發生什麼事 */ - if(list->list_first == node){ - list->list_first = node->node_next; - } - if(list->list_last == node){ - list->list_last = node->node_prev; - } - list->list_len--; /* 不考慮長度為零的情況,空白是想要刪什麼? */ - L4LLNODE* oldnext = node->node_next; - L4LLNODE* oldprev = node->node_prev; - if(node->node_data_size != 0){ - free(node->node_data); - } - free(node); - if(oldnext != NULL){ - oldnext->node_prev = oldprev; - } - if(oldprev != NULL){ - oldprev->node_next = oldnext; - } -} - -L4LLNODE* l4ll_goto(L4LLNODE* node, int count){ - int i; - if(count == 0){ - return node; - }else if(count > 0){ - for(i=1; i<=count; i++){ - node = node->node_next; - if(node == NULL){ - return NULL; - } - } - }else{ - count = -count; - for(i=1; i<=count; i++){ - node = node->node_prev; - if(node == NULL){ - return NULL; - } - } - } - return node; -} - -#if 0 -int l4ll_pushback(L4LL* list, void* data, int size){ - L4LLNODE* cur_save = list->list_current; /* 等一下要把現在位置搬回去 */ - list->list_current = list->list_last; - int result = l4ll_insnext(list, data, size); - if(result == 0){ /* 成功 */ - if(cur_save != NULL){ /* 原先的現在位置若為空就無意義了 */ - list->list_current = cur_save; - } - }else{ /* 失敗 */ - list->list_current = cur_save; - } - return result; -} - - -int l4ll_pushfront(L4LL*, void*){ /* 取自 l4ll_pushback */ - L4LLNODE* cur_save = list->list_current; - list->list_current = list->list_front; - int result = l4ll_insprev(list, data, size); - if(result == 0){ - if(cur_save != NULL){ - list->list_current = cur_save; - } - }else{ - list->list_current = cur_save; - } - return result; -} - -int l4ll_popback(L4LL*){ - L4LLNODE* cur_save = list->list_current; - L4LLNODE* last_save = list->list_last - list->list_current = last_save; - int result = l4ll_remove(list, L4LL_PREV); - if(result == 0){ - if(cur_save != NULL && ){ - list->list_current = cur_save; - } - }else{ - list->list_current = cur_save; - } - return result; -} - -int l4ll_popfront(L4LL*){ - L4LLNODE* cur_save = list->list_current; - list->list_current = list->list_first; - int result = l4ll_remove(list, L4LL_NEXT); - if(result == 0){ - if(cur_save != NULL){ - list->list_current = cur_save; - } - }else{ - list->list_current = cur_save; - } - return result; -} -#endif diff --git a/l4darr/Makefile b/l4darr/Makefile deleted file mode 100644 index 4593ccf..0000000 --- a/l4darr/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC=cc -AR=ar -RM=rm -f -INSTALL=install -m 644 -LOCAL_CFLAGS=-g -CFLAGS=-Wall -I. $(LOCAL_CFLAGS) -OBJ=d1array.o d1arrstr.o d2array.o -LIBFILE=libl4darr.a -DESTDIR=/ -PREFIX=/usr/local -LIBDIR=$(DESTDIR)/$(PREFIX)/lib - -.PHONY: all clean - -all: $(LIBFILE) -$(LIBFILE): $(OBJ) - $(AR) rcs $(LIBFILE) $(OBJ) -clean: - $(RM) $(LIBFILE) $(OBJ) -install: - mkdir -p $(LIBDIR) - $(INSTALL) -c $(LIBFILE) $(LIBDIR) -uninstall: - $(RM) $(LIBDIR)/$(LIBFILE) diff --git a/l4darr/d1array.c b/l4darr/d1array.c deleted file mode 100644 index b14bbea..0000000 --- a/l4darr/d1array.c +++ /dev/null @@ -1,132 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <l4darr.h> - -L4DA* l4da_create_setmax(int itemsize, int len, int maxlen){ - if(itemsize <= 0 || len < 0 || maxlen < len){ - return NULL; - } - L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); - if(arr == 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); - return NULL; - } - }else{ - arr->arr_data = NULL; - } - return arr; -} - -L4DA* l4da_create(int itemsize, int len){ - return l4da_create_setmax(itemsize, len, len); -} - -void l4da_free(L4DA* arr){ - if(arr->arr_data != NULL){ - free(arr->arr_data); - } - 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; - } - } - } - memcpy(l4da_vp(arr, arr->arr_curlen), data, arr->arr_itemsize); - arr->arr_curlen++; - 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; - } - }else{ - arr->arr_curlen = len; - return 0; - } - return 0; -} - -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; - } - } - newptr = realloc(arr->arr_data, (arr->arr_itemsize)*max); - if(newptr == NULL){ - return -1; - }else{ - arr->arr_maxlen = max; - arr->arr_data = newptr; - } - return 0; -} - -int l4da_strip(L4DA* arr){ - if(arr->arr_data == NULL){ - return 0; - } - 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; - } - arr->arr_data = newptr; - } - return 0; -} - -/* 基本上直接玩 struct 的函式還是少用吧 */ -void* l4da_drop_struct(L4DA* arr){ - void* toreturn = arr->arr_data; - free(arr); - return toreturn; -} - -L4DA* l4da_make_struct(void* data, int itemsize, int len, int maxlen){ - if(itemsize <= 0 || len < 0 || maxlen < len){ - return NULL; - } - L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); - if(arr == NULL){ - return NULL; - } - arr->arr_itemsize = itemsize; - arr->arr_curlen = len; - arr->arr_maxlen = maxlen; - arr->arr_data = data; - return arr; -} diff --git a/l4darr/d1arrstr.c b/l4darr/d1arrstr.c deleted file mode 100644 index 2c6e631..0000000 --- a/l4darr/d1arrstr.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <string.h> -#include <l4darr.h> - -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; - } - memcpy(newarr->arr_data, arr->arr_data, - l4da_getlen(arr) * l4da_itemsize(arr)); - return newarr; -} - -int l4da_combine(L4DA* arr, const L4DA* att){ - if(l4da_itemsize(arr) != l4da_itemsize(att)){ - return -2; - } - if(l4da_setlen(arr, l4da_getlen(arr) + l4da_getlen(att)) < 0){ - return -1; - } - memcpy(l4da_vp(arr, l4da_getlen(arr)), att->arr_data, - l4da_getlen(att) * l4da_itemsize(att)); - 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; - } - } - towrite = '\0'; - if(l4da_pushback(newarr, (void*)&towrite) < 0){ - l4da_free(newarr); - return NULL; - } - return newarr; -} diff --git a/l4darr/d2array.c b/l4darr/d2array.c deleted file mode 100644 index c2d6e69..0000000 --- a/l4darr/d2array.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <stdlib.h> -#include <l4darr.h> - -L4DA2* l4da2_create(int itemsize, int lenx, int leny){ - if(lenx <= 0 || leny <= 0 || itemsize <= 0){ - return NULL; - } - L4DA2* arr = (L4DA2*)malloc(sizeof(L4DA2)); - if(arr == NULL){ - return NULL; - } - arr->arr_itemsize = itemsize; - arr->arr_lenx = lenx; - arr->arr_leny = leny; - arr->arr_data = malloc(itemsize*lenx*leny); - if(arr->arr_data == NULL){ - free(arr); - return NULL; - } - return arr; -} - -void l4da2_free(L4DA2* arr){ - free(arr->arr_data); - free(arr); -} diff --git a/l4darr/l4darr.h b/l4darr/l4darr.h deleted file mode 100644 index 860f9b9..0000000 --- a/l4darr/l4darr.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef L4LIB_DYNAMIC_ARRAY -#define L4LIB_DYNAMIC_ARRAY - -#include <stdio.h> /* 取得 FILE */ - -/*********** 一維陣列 ***********/ - -typedef struct l4lib_dyn_arr{ - int arr_itemsize; /* 每個項目的大小 */ - int arr_curlen; /* 陣列總長度 */ - int arr_maxlen; /* 陣列最大長度 */ - void* arr_data; /* 資料區 */ -} L4DA ; - -L4DA* l4da_create_setmax(int, int, int); -L4DA* l4da_create(int, int); -void l4da_free(L4DA*); -int l4da_pushback(L4DA*, const void*); -#define l4da_popback(arr) (((arr)->arr_curlen)--) -#define l4da_getlen(arr) ((arr)->arr_curlen) -int l4da_setlen(L4DA*, int); -#define l4da_getmax(arr) ((arr)->arr_maxlen) -int l4da_setmax(L4DA*, int); -int l4da_strip(L4DA*); -#define l4da_itemsize(arr) ((arr)->arr_itemsize) -#define l4da_data(arr) ((arr)->arr_data) -#define l4da_v(arr, type, num) \ - (*(((type*)((arr)->arr_data))+(num))) -#define l4da_vp(arr, num) \ - ((void*)(((char*)((arr)->arr_data))+(((arr)->arr_itemsize)*(num)))) - -#define l4da_readline() (l4da_filereadline_delim(stdin, '\n')) -#define l4da_readline_delim(delim) (l4da_filereadline_delim(stdin, (delim))) -#define l4da_filereadline(infile) (l4da_filereadline_delim((infile), '\n')) -L4DA* l4da_filereadline_delim(FILE*, int); - -L4DA* l4da_dup(const L4DA*); -int l4da_combine(L4DA*, const L4DA*); - -void* l4da_drop_struct(L4DA*); -L4DA* l4da_make_struct(void*, int, int, int); - -/*********** 二維陣列 (其實是用一維陣列來模擬,功能有限) ***********/ - -typedef struct l4lib_dyn_2darr{ - int arr_itemsize; /* 每個項目的大小 */ - int arr_lenx; /* 陣列 x 方向長度 */ - int arr_leny; /* 陣列 y 方向長度 */ - void* arr_data; /* 資料區 */ -} L4DA2 ; - -L4DA2* l4da2_create(int, int, int); -void l4da2_free(L4DA2*); -#define l4da2_getlenx(arr) ((arr)->arr_lenx) -#define l4da2_getleny(arr) ((arr)->arr_leny) -#define l4da2_itemsize(arr) ((arr)->arr_itemsize) -#define l4da2_data(arr) ((arr)->arr_data) -#define l4da2_v(arr, type, numx, numy) \ - (*(((type*)((arr)->arr_data))+((numx)*(l4da2_getleny(arr)))+(numy))) -#define l4da2_vp(arr, numx, numy) \ - ((void*)(((char*)((arr)->arr_data))+ \ - ((arr)->arr_itemsize)*((numx)*(l4da2_getleny(arr))+(numy)))) - -#endif diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..35de0e9 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,67 @@ +# Programs +HOST= +CC= $(HOST)c99 +AR= $(HOST)ar +RANLIB= $(HOST)ranlib +RM= rm -f +MKDIR= mkdir +MKDIR_P= $(MKDIR) -p +INSTALL= install -c -m 644 + +# User flags +CFLAGS= -g -O2 -pipe +LDFLAGS= + +# Internal flags +L4B_CFLAGS= -Wall -I. $(CFLAGS) +L4B_LDFLAGS= $(LDFLAGS) + +# Installation +DESTDIR= +PREFIX= /usr/local +LIBDIR= $(DESTDIR)$(PREFIX)/lib +INCLUDEDIR= $(DESTDIR)$(PREFIX)/include + +# Tasks definition +lib_LIBRARIES= libl4basic.a +libl4basic_a_OBJECTS= l4array.o l4array2.o l4list.o l4arg.o +libl4basic_a_HEADERS= $(libl4basic_a_OBJECTS:.o=.h) + +# Build dependencies +l4array_o_DEPENDS= +l4array2_o_DEPENDS= +l4list_o_DEPENDS= +l4arg_o_DEPENDS= l4array.o + +.POSIX: +.PHONY: all clean install install-HEADERS install-LIB \ + uninstall deinstall remove +.SUFFIXES: .c.o +.c.o: + $(CC) $(L4B_CFLAGS) -c $< -o $@ + +all: $(lib_LIBRARIES) +libl4basic.a: $(libl4basic_a_OBJECTS) + $(AR) rcs $@ $(libl4basic_a_OBJECTS) + $(RANLIB) $@ +l4array.o: l4array.c l4array.h $(l4array_o_DEPENDS) +l4array2.o: l4array2.c l4array2.h $(l4array2_o_DEPENDS) +l4list.o: l4list.c l4list.h $(l4list_o_DEPENDS) +l4arg.o: l4arg.c l4arg.h $(l4arg_o_DEPENDS) + +clean: + $(RM) $(lib_LIBRARIES) $(libl4basic_a_OBJECTS) + +install: all install-HEADERS install-LIB +install-LIB: + -$(MKDIR_P) $(LIBDIR) + $(INSTALL) $(lib_LIBRARIES) $(LIBDIR) +install-HEADERS: + -$(MKDIR_P) $(INCLUDEDIR) + $(INSTALL) $(libl4basic_a_HEADERS) $(INCLUDEDIR) + +deinstall: uninstall +remove: uninstall +uninstall: + for i in $(lib_LIBRARIES); do $(RM) $(LIBDIR)/$$i; done + for i in $(libl4basic_a_HEADERS); do $(RM) $(INCLUDEDIR)/$$i; done diff --git a/src/l4arg.c b/src/l4arg.c new file mode 100644 index 0000000..9908665 --- /dev/null +++ b/src/l4arg.c @@ -0,0 +1,163 @@ +#include "l4arg.h" +#include "l4array.h" + +#include <string.h> +#include <stdlib.h> + +/* 基本上優先順序是 escape -> quoting -> delimiter */ + +#define abort_l4arg_toargv \ + do{ \ + l4da_free(parr); \ + l4da_free(tmpstr); \ + return NULL; \ + }while(0) + +char** l4arg_toargv(const char* str, + const char* delim, const char* quoting, const char* esc){ + int i; + char escaped = 0, quoted = 0, delimed = 0; + L4DA* parr; + L4DA* tmpstr; + char* addstr, tmpchar; + char** rval; + parr = l4da_create(sizeof(char*), 0); + if(parr == NULL){ + return NULL; + } + tmpstr = l4da_create(sizeof(char), 0); + if(tmpstr == NULL){ + l4da_free(parr); + return NULL; + } + for(i=0; str[i]!='\0'; i++){ + if(escaped){ + if(l4da_pushback(tmpstr, &str[i]) < 0){ + abort_l4arg_toargv; + } + escaped = 0; + delimed = 0; + continue; + } + if(quoted){ + if(strchr(quoting, str[i]) != NULL){ + quoted = 0; + continue; + } + if(l4da_pushback(tmpstr, &str[i]) < 0){ + abort_l4arg_toargv; + } + delimed = 0; + continue; + } + if(strchr(esc, str[i]) != NULL){ + escaped = 1; + continue; + } + if(strchr(quoting, str[i]) != NULL){ + quoted = 1; + continue; + } + if(strchr(delim, str[i]) != NULL){ + if(l4da_getlen(tmpstr) > 0){ + tmpchar = '\0'; + if(l4da_pushback(tmpstr, &tmpchar) < 0){ + abort_l4arg_toargv; + } + addstr = (char*)l4da_drop_struct(tmpstr); + if(l4da_pushback(parr, &addstr) < 0){ + l4da_free(parr); + return NULL; + } + tmpstr = l4da_create(sizeof(char), 0); + if(tmpstr == NULL){ + l4da_free(parr); + return NULL; + } + } + delimed = 1; + continue; + } + if(l4da_pushback(tmpstr, &str[i]) < 0){ + abort_l4arg_toargv; + } + delimed = 0; + } + if(!delimed){ + tmpchar = '\0'; + if(l4da_pushback(tmpstr, &tmpchar) < 0){ + abort_l4arg_toargv; + } + addstr = (char*)l4da_drop_struct(tmpstr); + if(l4da_pushback(parr, &addstr) < 0){ + l4da_free(parr); + return NULL; + } + } + addstr = NULL; + if(l4da_pushback(parr, &addstr) < 0){ + l4da_free(parr); + return NULL; + } + rval = (char**)l4da_drop_struct(parr); + return rval; +} + +void l4arg_toargv_free(char** pargv){ + int i; + for(i=0; pargv[i]!=NULL; i++){ + free(pargv[i]); + } + free(pargv); +} + +/* 為什麼叫做 qarg 呢?因為這是用來解析很像 QEMU 命令列參數的參數 */ + +L4QARG* l4qarg_parse(const char* str){ + char** pargv = l4arg_toargv(str, ",", "\"\'", "\\"); + if(pargv == NULL){ + return NULL; + } + int i, allc; + L4QARG* qargarr; + char* pos; + for(i=0; pargv[i]!=NULL; i++); + allc = i + 1; + qargarr = (L4QARG*) malloc(sizeof(L4QARG) * allc); + if(qargarr == NULL){ + l4arg_toargv_free(pargv); + return NULL; + } + for(i=0; pargv[i]!=NULL; i++){ + pos = strchr(pargv[i], '='); + if(pos == NULL){ + qargarr[i].arg_name = pargv[i]; + qargarr[i].arg_value = NULL; + }else{ + *pos = '\0'; + qargarr[i].arg_name = pargv[i]; + pos++; + qargarr[i].arg_value = (char*) malloc(strlen(pos)+1); + if(qargarr[i].arg_value == NULL){ + l4arg_toargv_free(pargv); + return NULL; + } + strcpy(qargarr[i].arg_value, pos); + } + } + free(pargv); + qargarr[i].arg_name = NULL; + qargarr[i].arg_value = NULL; + return qargarr; +} + +void l4qarg_free(L4QARG* qarg){ + int i; + for(i=0; !(qarg[i].arg_name == NULL && qarg[i].arg_value == NULL); i++){ + free(qarg[i].arg_name); + if(qarg[i].arg_value != NULL){ + free(qarg[i].arg_value); + } + } + free(qarg); +} diff --git a/src/l4arg.h b/src/l4arg.h new file mode 100644 index 0000000..68352c8 --- /dev/null +++ b/src/l4arg.h @@ -0,0 +1,28 @@ +#ifndef L4LIB_ARG_PARSER +#define L4LIB_ARG_PARSER + +#ifdef __cplusplus +extern "C" { +#endif + +char** l4arg_toargv(const char*, const char*, const char*, const char*); +void l4arg_toargv_free(char**); + +typedef struct l4lib_qarg { + char* arg_name; + char* arg_value; +} L4QARG; + +L4QARG* l4qarg_parse(const char*); +void l4qarg_free(L4QARG*); +#define l4qarg_n(qargitem) ((qargitem).arg_name) +#define l4qarg_v(qargitem) ((qargitem).arg_value) +#define l4qarg_hasvalue(qargitem) (((qargitem).arg_value != NULL)) +#define l4qarg_end(qargitem) \ + ((((qargitem).arg_name) == NULL) && (((qargitem).arg_value) == NULL)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/l4array.c b/src/l4array.c new file mode 100644 index 0000000..b57c021 --- /dev/null +++ b/src/l4array.c @@ -0,0 +1,178 @@ +#include "l4array.h" + +#include <stdlib.h> +#include <string.h> + +L4DA* l4da_create_setmax(int itemsize, int len, int maxlen){ + if(itemsize <= 0 || len < 0 || maxlen < len){ + return NULL; + } + L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); + if(arr == 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); + return NULL; + } + }else{ + arr->arr_data = NULL; + } + return arr; +} + +L4DA* l4da_create(int itemsize, int len){ + return l4da_create_setmax(itemsize, len, len); +} + +void l4da_free(L4DA* arr){ + if(arr->arr_data != NULL){ + free(arr->arr_data); + } + 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; + } + } + } + memcpy(l4da_vp(arr, arr->arr_curlen), data, arr->arr_itemsize); + arr->arr_curlen++; + 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; + } + }else{ + arr->arr_curlen = len; + return 0; + } + return 0; +} + +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; + } + } + newptr = realloc(arr->arr_data, (arr->arr_itemsize)*max); + if(newptr == NULL){ + return -1; + }else{ + arr->arr_maxlen = max; + arr->arr_data = newptr; + } + return 0; +} + +int l4da_strip(L4DA* arr){ + if(arr->arr_data == NULL){ + return 0; + } + 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; + } + arr->arr_data = newptr; + } + return 0; +} + +/* 基本上直接玩 struct 的函式還是少用吧 */ +void* l4da_drop_struct(L4DA* arr){ + void* toreturn = arr->arr_data; + free(arr); + return toreturn; +} + +L4DA* l4da_make_struct(void* data, int itemsize, int len, int maxlen){ + if(itemsize <= 0 || len < 0 || maxlen < len){ + return NULL; + } + L4DA* arr = (L4DA*)malloc(sizeof(L4DA)); + if(arr == NULL){ + return NULL; + } + arr->arr_itemsize = itemsize; + arr->arr_curlen = len; + arr->arr_maxlen = maxlen; + arr->arr_data = data; + return arr; +} + +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; + } + memcpy(newarr->arr_data, arr->arr_data, + l4da_getlen(arr) * l4da_itemsize(arr)); + return newarr; +} + +int l4da_combine(L4DA* arr, const L4DA* att){ + if(l4da_itemsize(arr) != l4da_itemsize(att)){ + return -2; + } + if(l4da_setlen(arr, l4da_getlen(arr) + l4da_getlen(att)) < 0){ + return -1; + } + memcpy(l4da_vp(arr, l4da_getlen(arr)), att->arr_data, + l4da_getlen(att) * l4da_itemsize(att)); + 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; + } + } + towrite = '\0'; + if(l4da_pushback(newarr, (void*)&towrite) < 0){ + l4da_free(newarr); + return NULL; + } + return newarr; +} diff --git a/src/l4array.h b/src/l4array.h new file mode 100644 index 0000000..192f49d --- /dev/null +++ b/src/l4array.h @@ -0,0 +1,43 @@ +#ifndef L4LIB_DYNAMIC_ARRAY +#define L4LIB_DYNAMIC_ARRAY + +#include <stdio.h> /* 取得 FILE */ + +/*********** 一維陣列 ***********/ + +typedef struct l4lib_dyn_arr{ + int arr_itemsize; /* 每個項目的大小 */ + int arr_curlen; /* 陣列總長度 */ + int arr_maxlen; /* 陣列最大長度 */ + void* arr_data; /* 資料區 */ +} L4DA ; + +L4DA* l4da_create_setmax(int, int, int); +L4DA* l4da_create(int, int); +void l4da_free(L4DA*); +int l4da_pushback(L4DA*, const void*); +#define l4da_popback(arr) (((arr)->arr_curlen)--) +#define l4da_getlen(arr) ((arr)->arr_curlen) +int l4da_setlen(L4DA*, int); +#define l4da_getmax(arr) ((arr)->arr_maxlen) +int l4da_setmax(L4DA*, int); +int l4da_strip(L4DA*); +#define l4da_itemsize(arr) ((arr)->arr_itemsize) +#define l4da_data(arr) ((arr)->arr_data) +#define l4da_v(arr, type, num) \ + (*(((type*)((arr)->arr_data))+(num))) +#define l4da_vp(arr, num) \ + ((void*)(((char*)((arr)->arr_data))+(((arr)->arr_itemsize)*(num)))) + +#define l4da_readline() (l4da_filereadline_delim(stdin, '\n')) +#define l4da_readline_delim(delim) (l4da_filereadline_delim(stdin, (delim))) +#define l4da_filereadline(infile) (l4da_filereadline_delim((infile), '\n')) +L4DA* l4da_filereadline_delim(FILE*, int); + +L4DA* l4da_dup(const L4DA*); +int l4da_combine(L4DA*, const L4DA*); + +void* l4da_drop_struct(L4DA*); +L4DA* l4da_make_struct(void*, int, int, int); + +#endif diff --git a/src/l4array2.c b/src/l4array2.c new file mode 100644 index 0000000..24d6db0 --- /dev/null +++ b/src/l4array2.c @@ -0,0 +1,26 @@ +#include "l4array2.h" +#include <stdlib.h> + +L4DA2* l4da2_create(int itemsize, int lenx, int leny){ + if(lenx <= 0 || leny <= 0 || itemsize <= 0){ + return NULL; + } + L4DA2* arr = (L4DA2*)malloc(sizeof(L4DA2)); + if(arr == NULL){ + return NULL; + } + arr->arr_itemsize = itemsize; + arr->arr_lenx = lenx; + arr->arr_leny = leny; + arr->arr_data = malloc(itemsize*lenx*leny); + if(arr->arr_data == NULL){ + free(arr); + return NULL; + } + return arr; +} + +void l4da2_free(L4DA2* arr){ + free(arr->arr_data); + free(arr); +} diff --git a/src/l4array2.h b/src/l4array2.h new file mode 100644 index 0000000..e10fc0b --- /dev/null +++ b/src/l4array2.h @@ -0,0 +1,25 @@ +#ifndef L4LIB_DYNAMIC_ARRAY_D2 +#define L4LIB_DYNAMIC_ARRAY_D2 + +/*********** 二維陣列 (其實是用一維陣列來模擬,功能有限) ***********/ + +typedef struct l4lib_dyn_2darr{ + int arr_itemsize; /* 每個項目的大小 */ + int arr_lenx; /* 陣列 x 方向長度 */ + int arr_leny; /* 陣列 y 方向長度 */ + void* arr_data; /* 資料區 */ +} L4DA2 ; + +L4DA2* l4da2_create(int, int, int); +void l4da2_free(L4DA2*); +#define l4da2_getlenx(arr) ((arr)->arr_lenx) +#define l4da2_getleny(arr) ((arr)->arr_leny) +#define l4da2_itemsize(arr) ((arr)->arr_itemsize) +#define l4da2_data(arr) ((arr)->arr_data) +#define l4da2_v(arr, type, numx, numy) \ + (*(((type*)((arr)->arr_data))+((numx)*(l4da2_getleny(arr)))+(numy))) +#define l4da2_vp(arr, numx, numy) \ + ((void*)(((char*)((arr)->arr_data))+ \ + ((arr)->arr_itemsize)*((numx)*(l4da2_getleny(arr))+(numy)))) + +#endif diff --git a/src/l4list.c b/src/l4list.c new file mode 100644 index 0000000..bcde31b --- /dev/null +++ b/src/l4list.c @@ -0,0 +1,236 @@ +#include "l4list.h" + +#include <stdlib.h> +#include <string.h> + +L4LL* l4ll_create(void){ + L4LL* newlist = (L4LL*)malloc(sizeof(L4LL)); + if(newlist == NULL){ + return NULL; + } + newlist->list_first = NULL; + newlist->list_last = NULL; + newlist->list_len = 0; + return newlist; +} + +void l4ll_free(L4LL* oldlist){ + if(oldlist->list_len <= 0){ + free(oldlist); + return; + } + L4LLNODE* i; + L4LLNODE* next; + for(i=oldlist->list_first; i!=NULL; i=next){ + next = i->node_next; + if(i->node_data_size){ /* 只要資料大小不為零,就還要釋放資料區 */ + free(i->node_data); + } + free(i); + } + free(oldlist); +} + +static L4LLNODE* +l4ll_initfirst(L4LL* list, const void* data, int size){ + /* 插入第一個資料,如果 list 不是空的就別用! + * 否則會造成資料結構混亂和 memory leak */ + L4LLNODE* node = (L4LLNODE*)malloc(sizeof(L4LLNODE)); + if(node == NULL){ + return NULL; + } + void* newdata; + if(size != 0){ + newdata = malloc(size); + if(newdata == NULL){ + free(node); + return NULL; + } + memcpy(newdata, data, size); + } + list->list_first = node; + list->list_last = node; + list->list_len = 1; + node->node_prev = NULL; + node->node_next = NULL; + node->node_data = (size != 0) ? newdata : NULL; + node->node_data_size = size; + return node; +} + +L4LLNODE* l4ll_insert_prev(L4LL* list, L4LLNODE* node, + const void* data, int size){ + /* list 送 NULL 來的我不理它,就自己去 segfault 吧 + * node 送 NULL 來只能在 list 是空的時候用 */ + if(list->list_len == 0){ + return l4ll_initfirst(list, data, size); + } + L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE)); + if(newnode == NULL){ + return NULL; + } + void* newdata; + if(size != 0){ + newdata = malloc(size); + if(newdata == NULL){ + free(newnode); + return NULL; + } + memcpy(newdata, data, size); + } + list->list_len++; + if(list->list_first == node){ /* 如果是第一個,那要修改 list_first */ + list->list_first = newnode; + } + L4LLNODE* oldprev = node->node_prev; + node->node_prev = newnode; + newnode->node_next = node; + newnode->node_prev = oldprev; + if(oldprev != NULL){ + oldprev->node_next = newnode; + } + newnode->node_data = (size != 0) ? newdata : NULL; + newnode->node_data_size = size; + return newnode; +} + +L4LLNODE* l4ll_insert_next(L4LL* list, L4LLNODE* node, + const void* data, int size){ + /* 基本上同 l4ll_insert_prev */ + if(list->list_len == 0){ + return l4ll_initfirst(list, data, size); + } + L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE)); + if(newnode == NULL){ + return NULL; + } + void* newdata; + if(size != 0){ + newdata = malloc(size); + if(newdata == NULL){ + free(newnode); + return NULL; + } + memcpy(newdata, data, size); + } + list->list_len++; + if(list->list_last == node){ + list->list_last = newnode; + } + L4LLNODE* oldnext = node->node_next; + node->node_next = newnode; + newnode->node_prev = node; + newnode->node_next = oldnext; + if(oldnext != NULL){ + oldnext->node_prev = newnode; + } + newnode->node_data = (size != 0) ? newdata : NULL; + newnode->node_data_size = size; + return newnode; +} + +void l4ll_remove(L4LL* list, L4LLNODE* node){ + /* 不要在 node 傳 NULL,這一點意義也沒有且我不知道會發生什麼事 */ + if(list->list_first == node){ + list->list_first = node->node_next; + } + if(list->list_last == node){ + list->list_last = node->node_prev; + } + list->list_len--; /* 不考慮長度為零的情況,空白是想要刪什麼? */ + L4LLNODE* oldnext = node->node_next; + L4LLNODE* oldprev = node->node_prev; + if(node->node_data_size != 0){ + free(node->node_data); + } + free(node); + if(oldnext != NULL){ + oldnext->node_prev = oldprev; + } + if(oldprev != NULL){ + oldprev->node_next = oldnext; + } +} + +L4LLNODE* l4ll_goto(L4LLNODE* node, int count){ + int i; + if(count == 0){ + return node; + }else if(count > 0){ + for(i=1; i<=count; i++){ + node = node->node_next; + if(node == NULL){ + return NULL; + } + } + }else{ + count = -count; + for(i=1; i<=count; i++){ + node = node->node_prev; + if(node == NULL){ + return NULL; + } + } + } + return node; +} + +#if 0 +int l4ll_pushback(L4LL* list, void* data, int size){ + L4LLNODE* cur_save = list->list_current; /* 等一下要把現在位置搬回去 */ + list->list_current = list->list_last; + int result = l4ll_insnext(list, data, size); + if(result == 0){ /* 成功 */ + if(cur_save != NULL){ /* 原先的現在位置若為空就無意義了 */ + list->list_current = cur_save; + } + }else{ /* 失敗 */ + list->list_current = cur_save; + } + return result; +} + + +int l4ll_pushfront(L4LL*, void*){ /* 取自 l4ll_pushback */ + L4LLNODE* cur_save = list->list_current; + list->list_current = list->list_front; + int result = l4ll_insprev(list, data, size); + if(result == 0){ + if(cur_save != NULL){ + list->list_current = cur_save; + } + }else{ + list->list_current = cur_save; + } + return result; +} + +int l4ll_popback(L4LL*){ + L4LLNODE* cur_save = list->list_current; + L4LLNODE* last_save = list->list_last + list->list_current = last_save; + int result = l4ll_remove(list, L4LL_PREV); + if(result == 0){ + if(cur_save != NULL && ){ + list->list_current = cur_save; + } + }else{ + list->list_current = cur_save; + } + return result; +} + +int l4ll_popfront(L4LL*){ + L4LLNODE* cur_save = list->list_current; + list->list_current = list->list_first; + int result = l4ll_remove(list, L4LL_NEXT); + if(result == 0){ + if(cur_save != NULL){ + list->list_current = cur_save; + } + }else{ + list->list_current = cur_save; + } + return result; +} +#endif diff --git a/src/l4list.h b/src/l4list.h new file mode 100644 index 0000000..2ad7199 --- /dev/null +++ b/src/l4list.h @@ -0,0 +1,66 @@ +#ifndef L4LIB_BASIC_DATA_STRUCTURE +#define L4LIB_BASIC_DATA_STRUCTURE + +/*********** list ***********/ + +typedef struct l4lib_list_node{ /* list 中每一個項目用的資料結構,會有很多個 */ + struct l4lib_list_node* node_prev; + struct l4lib_list_node* node_next; + void* node_data; + int node_data_size; +} L4LLNODE; + +typedef struct l4lib_list{ /* 管理 list 用的,每個 list 只有一個 */ + struct l4lib_list_node* list_first; + struct l4lib_list_node* list_last; + int list_len; +} L4LL; + +L4LL* l4ll_create(void); +void l4ll_free(L4LL*); +#define l4ll_prev(node) ((node)->node_prev) +#define l4ll_next(node) ((node)->node_next) +#define l4ll_len(list) ((list)->list_len) +#define l4ll_node_back(list) ((list)->list_last) +#define l4ll_node_front(list) ((list)->list_first) +#define l4ll_data(node) ((node)->node_data) +#define l4ll_datasize(node) ((node)->node_data_size) +L4LLNODE* l4ll_insert_prev(L4LL*, L4LLNODE*, const void*, int); +L4LLNODE* l4ll_insert_next(L4LL*, L4LLNODE*, const void*, int); +void l4ll_remove(L4LL*, L4LLNODE*); +#define l4ll_pushback(list,data,size) \ + (l4ll_insert_next((list),(l4ll_node_back(list)),(data),(size))) +#define l4ll_pushfront(list,data,size) \ + (l4ll_insert_prev((list),(l4ll_node_front(list)),(data),(size))) +#define l4ll_popback(list) \ + (l4ll_remove((list),(l4ll_node_back((list))))) +#define l4ll_popfront(list) \ + (l4ll_remove((list),(l4ll_node_front((list))))) +L4LLNODE* l4ll_goto(L4LLNODE*, int); + +/*********** stack ***********/ + +typedef L4LL L4STACK; +#define l4stack_create() (l4ll_create()) +#define l4stack_free(list) (l4ll_free(list)) +#define l4stack_push(list,data,size) (l4ll_pushback((list),(data),(size))) +#define l4stack_pop(list) (l4ll_popback(list)) +#define l4stack_len(list) (l4ll_len(list)) +#define l4stack_data(list) (l4ll_data(l4ll_node_back(list))) +#define l4stack_datasize(list) (l4ll_datasize(l4ll_node_back(list))) + +/*********** queue ***********/ + +typedef L4LL L4QUEUE; +#define l4queue_create() (l4ll_create()) +#define l4queue_free(list) (l4ll_free(list)) +#define l4queue_push(list,data,size) (l4ll_pushback((list),(data),(size))) +#define l4queue_pop(list) (l4ll_popfront(list)) +#define l4queue_len(list) (l4ll_len(list)) +#define l4queue_frontdata(list) (l4ll_data(l4ll_node_front(list))) +#define l4queue_frontdatasize(list) (l4ll_datasize(l4ll_node_front(list))) +#define l4queue_backdata(list) (l4ll_data(l4ll_node_back(list))) +#define l4queue_backdatasize(list) (l4ll_datasize(l4ll_node_back(list))) +#define l4queue_data(list) (l4queue_frontdata(list)) +#define l4queue_datasize(list) (l4queue_frontdatasize(list)) +#endif -- cgit