diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 67 | ||||
-rw-r--r-- | src/l4arg.c | 163 | ||||
-rw-r--r-- | src/l4arg.h | 28 | ||||
-rw-r--r-- | src/l4array.c | 178 | ||||
-rw-r--r-- | src/l4array.h | 43 | ||||
-rw-r--r-- | src/l4array2.c | 26 | ||||
-rw-r--r-- | src/l4array2.h | 25 | ||||
-rw-r--r-- | src/l4list.c | 236 | ||||
-rw-r--r-- | src/l4list.h | 66 |
9 files changed, 832 insertions, 0 deletions
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 |