diff options
Diffstat (limited to 'l4basic/l4bds/list.c')
-rw-r--r-- | l4basic/l4bds/list.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/l4basic/l4bds/list.c b/l4basic/l4bds/list.c new file mode 100644 index 0000000..09ec746 --- /dev/null +++ b/l4basic/l4bds/list.c @@ -0,0 +1,235 @@ +#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 |