aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2014-01-11 21:27:51 +0800
committerLAN-TW <lantw44@gmail.com>2014-01-11 21:30:49 +0800
commit600e2e611f426308bfb25601c62417f38198c1a6 (patch)
tree43edb14151ad72939bc11d978fb77f13a87c6111
parente6333b32e01bc3e7541e2359bf3854a72837b6c3 (diff)
downloadl4basic-unstable-1.93.tar.gz
l4basic-unstable-1.93.tar.zst
l4basic-unstable-1.93.zip
Rewrite linked-list (LbsList) and add test suitel4basic-unstable-1.93
-rw-r--r--VERSION2
-rw-r--r--l4list.c389
-rw-r--r--l4list.h180
-rw-r--r--test-list.c206
4 files changed, 497 insertions, 280 deletions
diff --git a/VERSION b/VERSION
index 7f229af..95784ef 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.92.0
+1.93.0
diff --git a/l4list.c b/l4list.c
index bcde31b..cba3496 100644
--- a/l4list.c
+++ b/l4list.c
@@ -1,236 +1,199 @@
+/* vim: set sw=4 ts=4 sts=4 et: */
#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;
-}
+LbsListMeta* lbs_list_meta_new (void (*free_func) (void*)) {
+ LbsListMeta* list = malloc (sizeof (LbsListMeta));
+ if (list == NULL) {
+ return NULL;
+ }
-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);
-}
+ list->first = NULL;
+ list->last = NULL;
+ list->len = 0;
+ list->free_func = free_func;
-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;
+ return list;
}
-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;
-}
+void lbs_list_meta_free (LbsListMeta* list) {
+ if (list == NULL) {
+ return;
+ }
+ if (list->len <= 0) {
+ free (list);
+ return;
+ }
-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;
+ LbsList *iter, *next;
+ for (iter = list->first; iter != NULL; iter = next) {
+ next = iter->next;
+ if (iter->free_func != NULL) {
+ (*(iter->free_func)) (iter->data);
+ } else if (list->free_func != NULL) {
+ (*(list->free_func)) (iter->data);
+ }
+ free (iter);
+ }
+ free (list);
}
-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;
- }
-}
+static LbsList* init_first_node (LbsListMeta* list,
+ void* data, void (*free_func) (void*)) {
+
+ /* Warning: This function assumes the list is empty! */
+ LbsList* node = malloc (sizeof (LbsList));
+ if (node == NULL) {
+ return NULL;
+ }
+
+ if (list != NULL) {
+ list->first = node;
+ list->last = node;
+ list->len = 1;
+ }
-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;
+ node->prev = NULL;
+ node->next = NULL;
+ node->data = data;
+ node->free_func = free_func;
+
+ 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;
+LbsList* lbs_list_insert_prev (LbsListMeta* list, LbsList* node,
+ void* data, void (*free_func) (void*)) {
+
+ if (list != NULL && list->len <= 0) {
+ return init_first_node (list, data, free_func);
+ }
+
+ LbsList* new_node = malloc (sizeof (LbsList));
+ if (new_node == NULL) {
+ return NULL;
+ }
+
+ if (node == NULL) {
+ new_node->prev = NULL;
+ new_node->next = NULL;
+ new_node->data = data;
+ new_node->free_func = free_func;
+ return new_node;
+ }
+
+ if (list != NULL) {
+ list->len++;
+ if (list->first == node) {
+ list->first = new_node;
+ }
+ }
+
+ LbsList* old_prev = node->prev;
+ node->prev = new_node;
+ new_node->next = node;
+ new_node->prev = old_prev;
+ if (old_prev != NULL) {
+ old_prev->next = new_node;
+ }
+
+ new_node->data = data;
+ new_node->free_func = free_func;
+ return new_node;
}
+LbsList* lbs_list_insert_next (LbsListMeta* list, LbsList* node,
+ void* data, void (*free_func) (void*)) {
+
+ if (list != NULL && list->len <= 0) {
+ return init_first_node (list, data, free_func);
+ }
+
+ LbsList* new_node = malloc (sizeof (LbsList));
+ if (new_node == NULL) {
+ return NULL;
+ }
+
+ if (node == NULL) {
+ new_node->prev = NULL;
+ new_node->next = NULL;
+ new_node->data = data;
+ new_node->free_func = free_func;
+ return new_node;
+ }
+
+ if (list != NULL) {
+ list->len++;
+ if(list->last == node){
+ list->last = new_node;
+ }
+ }
+
+ LbsList* old_next = node->next;
+ node->next = new_node;
+ new_node->prev = node;
+ new_node->next = old_next;
+ if (old_next != NULL) {
+ old_next->prev = new_node;
+ }
-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;
+ new_node->data = data;
+ new_node->free_func = free_func;
+ return new_node;
}
-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;
+void lbs_list_remove (LbsListMeta* list, LbsList* node) {
+ /* node must not be NULL! */
+ if (list != NULL) {
+ if (list->first == node) {
+ list->first = node->next;
+ }
+ if (list->last == node) {
+ list->last = node->prev;
+ }
+ if (list->len > 0) {
+ list->len--;
+ }
+ }
+
+ LbsList* old_next = node->next;
+ LbsList* old_prev = node->prev;
+
+ if (node->free_func != NULL) {
+ (*(node->free_func)) (node->data);
+ } else if (list != NULL && list->free_func != NULL) {
+ (*(list->free_func)) (node->data);
+ }
+ free (node);
+
+ if (old_next != NULL) {
+ old_next->prev = old_prev;
+ }
+ if (old_prev != NULL) {
+ old_prev->next = old_next;
+ }
}
-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;
+LbsList* lbs_list_goto (LbsList* node, int count) {
+ int i;
+
+ if (count > 0) { /* positive */
+ for (i = 0; i < count; i++) {
+ node = node->next;
+ if (node == NULL) {
+ return NULL;
+ }
+ }
+ } else if (count < 0) { /* negative */
+ count = -count;
+ for (i = 0; i < count; i++) {
+ node = node->prev;
+ if (node == NULL) {
+ return NULL;
+ }
+ }
+ }
+
+ return node;
}
-#endif
diff --git a/l4list.h b/l4list.h
index 2ad7199..3def6e6 100644
--- a/l4list.h
+++ b/l4list.h
@@ -1,66 +1,114 @@
-#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
+/* vim: set sw=4 ts=4 sts=4 et: */
+#ifndef LBS_LIST_H
+#define LBS_LIST_H
+
+#include <l4common.h>
+
+typedef struct LbsListStruct { /* list node */
+ /*< private >*/
+ struct LbsListStruct* prev; /* pointer to the previous node */
+ struct LbsListStruct* next; /* pointer to the next node */
+
+ /*< public >*/
+ void (*free_func) (void* data); /* function to free the data pointer */
+ void* data; /* data pointer */
+} LbsList;
+
+typedef struct LbsListMetaStruct { /* list wrapper */
+ /*< private >*/
+ struct LbsListStruct* first; /* pointer to the first node in the list */
+ struct LbsListStruct* last; /* pointer to the last node in the list */
+ size_t len; /* current length of the list */
+
+ /*< public >*/
+ void (*free_func) (void* data);
+ /* Function to free the data pointer. This function is used only if
+ * the free_func field in the node is set to NULL */
+} LbsListMeta;
+
+#define LBS_LIST(x) ((LbsList*)(x))
+#define LBS_LIST_META(x) ((LbsListMeta*)(x))
+
+LbsListMeta* lbs_list_meta_new (void (*free_func) (void*));
+void lbs_list_meta_free (LbsListMeta* list);
+
+#define lbs_list_meta_get_first(list) \
+ (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->first)
+#define lbs_list_meta_get_last(list) \
+ (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->last)
+#define lbs_list_meta_get_len(list) \
+ (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->len)
+#define lbs_list_meta_get_free_func(list) \
+ (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->free_func)
+
+#define lbs_list_meta_set_free_func(list,value) \
+ ((LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->free_func) = (value))
+
+#define lbs_list_get_prev(node) \
+ (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->prev)
+#define lbs_list_get_next(node) \
+ (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->next)
+#define lbs_list_get_data(node) \
+ (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->data)
+#define lbs_list_get_free_func(node) \
+ (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->free_func)
+
+#define lbs_list_set_data(node,value) \
+ ((LBS_COMMON_CHECK_TYPE ((node), LbsList*)->data) = (value))
+#define lbs_list_set_free_func(node,value) \
+ ((LBS_COMMON_CHECK_TYPE ((node), LbsList*)->free_func) = (value))
+
+LbsList* lbs_list_insert_prev (LbsListMeta* list, LbsList* node,
+ void* data, void (*free_func) (void*));
+LbsList* lbs_list_insert_next (LbsListMeta* list, LbsList* node,
+ void* data, void (*free_func) (void*));
+void lbs_list_remove (LbsListMeta* list, LbsList* node);
+
+#define lbs_list_push_back(list,data,f) \
+ (lbs_list_insert_next ((list), (lbs_list_meta_get_last (list)), (data), (f)))
+#define lbs_list_push_front(list,data,f) \
+ (lbs_list_insert_prev ((list), (lbs_list_meta_get_first (list)), (data), (f)))
+#define lbs_list_pop_back(list) \
+ (lbs_list_remove ((list), (lbs_list_meta_get_last ((list)))))
+#define lbs_list_pop_front(list) \
+ (lbs_list_remove ((list), (lbs_list_meta_get_first ((list)))))
+
+LbsList* lbs_list_goto (LbsList* node, int count);
+#define lbs_list_meta_goto(list,count) \
+ (lbs_list_goto ((lbs_list_meta_get_first (list)), (count)))
+
+
+#ifndef LBS_LIST_DISABLE_STACK
+
+typedef LbsListMeta LbsStack;
+#define lbs_stack_new(f) (lbs_list_meta_new (f))
+#define lbs_stack_free(stack) (lbs_list_meta_free (stack))
+#define lbs_stack_push(stack,data,f) \
+ (lbs_list_push_back ((stack), (data), (f)))
+#define lbs_stack_pop(stack) (lbs_list_pop_back (stack))
+#define lbs_stack_get_len(stack) (lbs_list_meta_get_len (stack))
+#define lbs_stack_get_data(stack) \
+ (lbs_list_get_data (lbs_list_meta_get_last (stack)))
+
+#endif /* LBS_LIST_DISABLE_STACK */
+
+
+#ifndef LBS_LIST_DISABLE_QUEUE
+
+typedef LbsListMeta LbsQueue;
+#define lbs_queue_new(f) (lbs_list_meta_new (f))
+#define lbs_queue_free(queue) (lbs_list_meta_free (queue))
+#define lbs_queue_enqueue(queue,data,f) \
+ (lbs_list_push_back ((queue), (data), (f)))
+#define lbs_queue_dequeue(queue) (lbs_list_pop_front (queue))
+#define lbs_queue_get_len(queue) (lbs_list_meta_get_len (queue))
+#define lbs_queue_get_front(queue) \
+ (lbs_list_get_data (lbs_list_meta_get_first (queue)))
+#define lbs_queue_get_back(queue) \
+ (lbs_list_get_data (lbs_list_meta_get_last (queue)))
+#define lbs_queue_get_data(queue) (lbs_queue_get_front (queue))
+
+#endif /* LBS_LIST_DISABLE_QUEUE */
+
+
+#endif /* LBS_LIST_H */
diff --git a/test-list.c b/test-list.c
new file mode 100644
index 0000000..71c26d3
--- /dev/null
+++ b/test-list.c
@@ -0,0 +1,206 @@
+/* vim: set sw=4 ts=4 sts=4 et: */
+#undef NDEBUG
+#define _POSIX_C_SOURCE 200809L
+#define _NETBSD_SOURCE
+
+#include <l4list.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define INT_TO_PTR(x) ((void*)((intptr_t)(x)))
+#define PTR_TO_INT(x) ((int)((intptr_t)((void*)(x))))
+
+void test_list_empty (void) {
+ LbsListMeta* list = lbs_list_meta_new (NULL);
+ LbsList* node = NULL;
+
+ for (int i = 1; i <= 10; i++) {
+ node = lbs_list_insert_next (list, node, INT_TO_PTR (i), NULL);
+ }
+
+ assert (lbs_list_meta_get_len (list) == 10);
+
+ node = lbs_list_meta_goto (list, 5);
+ lbs_list_remove (list, node);
+ assert (lbs_list_meta_get_len (list) == 9);
+
+ node = lbs_list_meta_get_first (list);
+ for (int i = 1; i <= 10; i++) {
+ if (i == 6) {
+ continue;
+ }
+ assert (PTR_TO_INT (lbs_list_get_data (node)) == i);
+ node = node->next;
+ }
+
+ lbs_list_meta_free (list);
+
+ printf ("%s => PASS!\n", __func__);
+}
+
+void test_list_free_func (void) {
+ LbsListMeta* list = lbs_list_meta_new (free);
+ LbsList* node = NULL;
+ LbsList* node_next;
+ const char* a[] = {
+ "1 Good",
+ "2 Test",
+ "3 Free",
+ "4 Tree",
+ "5 Book",
+ "6 GGGGOOOOOOOODDDD",
+ "7 OOOOOOOOKKKKKKKKKKKK",
+ "8 QQQQQQQQAAAAAAAAAAAAAAAAAA",
+ "9 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSHHHHHHHHHHHHHH",
+ "10 !!"
+ };
+
+ for (int i = 0; i < 10; i++) {
+ node = lbs_list_insert_next (list, node, strdup (a[i]), NULL);
+ }
+
+ assert (lbs_list_meta_get_len (list) == 10);
+
+ node = lbs_list_meta_goto (list, 5);
+ node_next = node->next;
+ lbs_list_remove (list, node);
+ assert (lbs_list_meta_get_len (list) == 9);
+
+ lbs_list_insert_prev (list, node_next, INT_TO_PTR (0), NULL);
+ assert (lbs_list_meta_get_len (list) == 10);
+
+ node = lbs_list_meta_get_first (list);
+ for (int i = 0; i < 10; i++) {
+ if (i == 5) {
+ assert (PTR_TO_INT (lbs_list_get_data (node)) == 0);
+ node = node->next;
+ continue;
+ }
+ assert (strcmp (lbs_list_get_data (node), a[i]) == 0);
+ node = node->next;
+ }
+
+ lbs_list_meta_free (list);
+ printf ("%s => PASS!\n", __func__);
+}
+
+void test_list_op (void) {
+ LbsListMeta* list = lbs_list_meta_new (NULL);
+ LbsList* node;
+
+ node = lbs_list_insert_next (list, NULL, INT_TO_PTR (2), NULL);
+ node = lbs_list_insert_prev (list, node, INT_TO_PTR (1), NULL);
+ lbs_list_push_back (list, INT_TO_PTR (2), NULL);
+ lbs_list_push_front (list, INT_TO_PTR (0), NULL);
+
+ lbs_list_insert_prev (list, lbs_list_meta_get_last (list),
+ INT_TO_PTR (3), NULL);
+ lbs_list_pop_back (list);
+ lbs_list_pop_front (list);
+
+ lbs_list_push_front (list, INT_TO_PTR (-1), NULL);
+ node = lbs_list_meta_goto (list, 0);
+ lbs_list_remove (list, node);
+ lbs_list_meta_set_free_func (list, NULL);
+
+ node = NULL;
+ for (int i = 1; node != NULL; i++, node = node->next) {
+ assert (PTR_TO_INT (lbs_list_get_data (node)) == i);
+ }
+
+ lbs_list_meta_free (list);
+ printf ("%s => PASS!\n", __func__);
+}
+
+void test_list_op_no_meta (void) {
+ LbsList* node_first;
+ LbsList* node_last;
+ LbsList* node;
+ LbsList* tmp;
+
+ node_last = lbs_list_insert_next (NULL, NULL, INT_TO_PTR (2), NULL);
+ node_first = lbs_list_insert_prev (NULL, node_last, INT_TO_PTR (1), NULL);
+ node_last = lbs_list_insert_next (NULL, node_last, INT_TO_PTR (2), NULL);
+ node_first = lbs_list_insert_prev (NULL, node_first, INT_TO_PTR (0), NULL);
+
+ lbs_list_insert_prev (NULL, node_last, INT_TO_PTR (3), NULL);
+ tmp = node_last->prev;
+ lbs_list_remove (NULL, node_last);
+ node_last = tmp;
+ tmp = node_first->next;
+ lbs_list_remove (NULL, node_first);
+ node_first = tmp;
+
+ lbs_list_insert_prev (NULL, node_first, INT_TO_PTR (-1), NULL);
+ node = lbs_list_goto (node_first, -1);
+ lbs_list_remove (NULL, node);
+
+ node = NULL;
+ for (int i = 1; node != NULL; i++, node = node->next) {
+ assert (PTR_TO_INT (lbs_list_get_data (node)) == i);
+ }
+
+ free (lbs_list_goto (node_first, 1));
+ free (node_first);
+ free (node_last);
+
+ printf ("%s => PASS!\n", __func__);
+}
+
+void test_stack (void) {
+ LbsStack* stk = lbs_stack_new (NULL);
+
+ lbs_stack_push (stk, INT_TO_PTR (1), NULL);
+ lbs_stack_push (stk, INT_TO_PTR (2), NULL);
+ lbs_stack_push (stk, INT_TO_PTR (3), NULL);
+
+ assert (lbs_stack_get_len (stk) == 3);
+ assert (lbs_stack_get_data (stk) == INT_TO_PTR (3));
+
+ lbs_stack_pop (stk);
+ assert (lbs_stack_get_len (stk) == 2);
+ assert (lbs_stack_get_data (stk) == INT_TO_PTR (2));
+
+ lbs_stack_pop (stk);
+ assert (lbs_stack_get_len (stk) == 1);
+ assert (lbs_stack_get_data (stk) == INT_TO_PTR (1));
+
+ lbs_stack_free (stk);
+ printf ("%s => PASS!\n", __func__);
+}
+
+void test_queue (void) {
+ LbsQueue* q = lbs_queue_new (NULL);
+
+ lbs_queue_enqueue (q, INT_TO_PTR (1), NULL);
+ lbs_queue_enqueue (q, INT_TO_PTR (2), NULL);
+ lbs_queue_enqueue (q, INT_TO_PTR (3), NULL);
+
+ assert (lbs_queue_get_len (q) == 3);
+ assert (lbs_queue_get_front (q) == INT_TO_PTR (1));
+ assert (lbs_queue_get_back (q) == INT_TO_PTR (3));
+ assert (lbs_queue_get_data (q) == INT_TO_PTR (1));
+
+ lbs_queue_dequeue (q);
+ assert (lbs_queue_get_len (q) == 2);
+ assert (lbs_queue_get_front (q) == INT_TO_PTR (2));
+ assert (lbs_queue_get_back (q) == INT_TO_PTR (3));
+ assert (lbs_queue_get_data (q) == INT_TO_PTR (2));
+
+ lbs_queue_free (q);
+ printf ("%s => PASS!\n", __func__);
+}
+
+int main () {
+ test_list_empty ();
+ test_list_free_func ();
+ test_list_op ();
+ test_list_op_no_meta ();
+ test_stack ();
+ test_queue ();
+ return 0;
+}