#include "l4list.h" #include #include 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