#include "xwrap.h" #include <stdlib.h> #include <string.h> #include "basic-list.h" List* list_create(void){ List* newlist = (List*)xmalloc(sizeof(List)); if(newlist == NULL){ return NULL; } newlist->list_first = NULL; newlist->list_last = NULL; newlist->list_len = 0; return newlist; } void list_free(List* oldlist){ if(oldlist->list_len <= 0){ free(oldlist); return; } ListNode* i; ListNode* 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 ListNode* list_initfirst(List* list, const void* data, int size){ /* 插入第一個資料,如果 list 不是空的就別用! * 否則會造成資料結構混亂和 memory leak */ ListNode* node = (ListNode*)xmalloc(sizeof(ListNode)); if(node == NULL){ return NULL; } void* newdata; if(size != 0){ newdata = xmalloc(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; } ListNode* list_insert_prev(List* list, ListNode* node, const void* data, int size){ /* list 送 NULL 來的我不理它,就自己去 segfault 吧 * node 送 NULL 來只能在 list 是空的時候用 */ if(list->list_len == 0){ return list_initfirst(list, data, size); } ListNode* newnode = (ListNode*)xmalloc(sizeof(ListNode)); if(newnode == NULL){ return NULL; } void* newdata; if(size != 0){ newdata = xmalloc(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; } ListNode* 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; } ListNode* list_insert_next(List* list, ListNode* node, const void* data, int size){ /* 基本上同 list_insert_prev */ if(list->list_len == 0){ return list_initfirst(list, data, size); } ListNode* newnode = (ListNode*)xmalloc(sizeof(ListNode)); if(newnode == NULL){ return NULL; } void* newdata; if(size != 0){ newdata = xmalloc(size); if(newdata == NULL){ free(newnode); return NULL; } memcpy(newdata, data, size); } list->list_len++; if(list->list_last == node){ list->list_last = newnode; } ListNode* 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 list_remove(List* list, ListNode* 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--; /* 不考慮長度為零的情況,空白是想要刪什麼? */ ListNode* oldnext = node->node_next; ListNode* 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; } } ListNode* list_goto(ListNode* 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; }