aboutsummaryrefslogblamecommitdiffstats
path: root/l4bds/list.c
blob: 09ec746c8e61a18cb57bcfc369e1fe7d3a9c9c3a (plain) (tree)
































                                                                                                   
                                                       
























                                                                       

                                                       















                                                                       
                                            
















                                                                                        

                                                       














                                                                
                                            







































                                                                                                 






















                                               


























































                                                                                           
#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