Added linked_list_search API. Refactored linked list implementation and testing (now much better).

This commit is contained in:
secXsQuared 2016-05-19 17:18:27 -07:00
parent d6f2342d05
commit 13843b16bc
5 changed files with 281 additions and 134 deletions

View File

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <printf.h>
#include <stdio.h>
#include <stdbool.h>
#include "linked_list.h"
typedef struct
@ -8,42 +9,94 @@ typedef struct
int val;
} my_list;
void validate_list(linked_list_t* list)
bool validate_list(linked_list_t* list)
{
int good = 0;
if(list->head == NULL)
good += list->tail == NULL;
if(list->tail == NULL)
good += list->head == NULL;
bool result = true;
// list_head_test
if(list->head != NULL)
good += list->head->prev == NULL;
{
result = result && (list->head->prev == NULL);
}
else
{
result = result && (list->tail == NULL);
}
if(list->tail != NULL)
good += list->tail->next == NULL;
printf(good == 2 ? " good" : " bad");
{
result = result && (list->tail->next == NULL);
}
else
{
result = result && (list->head == NULL);
}
return result;
}
void print_validate(linked_list_t *list)
bool assert_list(linked_list_t* list, int val[], int size)
{
my_list* node = (my_list*) linked_list_first(list);
while(node != NULL)
linked_list_node_t* node = linked_list_first(list);
unsigned int i = 0;
if(!validate_list(list))
return false;
while(node != NULL && i < size)
{
printf("%d", node->val);
node = (my_list*) linked_list_next((linked_list_node_t *) node);
my_list* enode = OBTAIN_STRUCT_ADDR(node, lnode, my_list);
if(enode->val != val[i])
{
return false;
}
i++;
node = linked_list_next(node);
}
printf("======");
node = (my_list*) linked_list_last(list);
while(node != NULL)
if(i != size)
{
printf("%d", node->val);
node = (my_list*) linked_list_prev((linked_list_node_t *) node);
return false;
}
validate_list(list);
printf("\n");
return;
node = linked_list_last(list);
while(node != NULL && i >= 0)
{
my_list* enode = OBTAIN_STRUCT_ADDR(node, lnode, my_list);
if(enode->val != val[i-1])
{
return false;
}
i--;
node = linked_list_prev(node);
}
return i == 0;
}
//void print_validate(linked_list_t *list)
//{
// my_list* node = (my_list*) linked_list_first(list);
// while(node != NULL)
// {
// printf("%d", node->val);
// node = (my_list*) linked_list_next((linked_list_node_t *) node);
// }
//
// printf("======");
// node = (my_list*) linked_list_last(list);
// while(node != NULL)
// {
// printf("%d", node->val);
// node = (my_list*) linked_list_prev((linked_list_node_t *) node);
// }
//
// validate_list(list);
// printf("\n");
// return;
//}
void insert_val(linked_list_t* list, int index, int val)
{
my_list *a = (my_list*)malloc(sizeof(my_list));
@ -76,7 +129,8 @@ void insert_test_beginning()
insert_val(&list, 0, 3);
// 3210==0123
print_validate(&list);
int val[4] = {3,2,1,0};
printf("insert_test_beginning %s\n",assert_list(&list, val, 4) ? "PASS" : "FAIL");
}
void insert_test_middle()
@ -92,8 +146,8 @@ void insert_test_middle()
insert_val(&list, 1, 5);
insert_val(&list, 2, 6);
// 256410=====014652
print_validate(&list);
int val[] = {2,5,6,4,1,0};
printf("insert_test_middle %s\n",assert_list(&list, val, 6) ? "PASS" : "FAIL");
}
void insert_test_end()
@ -106,8 +160,8 @@ void insert_test_end()
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
// 0123=====3210
print_validate(&list);
int val[] = {0,1,2,3};
printf("insert_test_end %s\n",assert_list(&list, val, 4) ? "PASS" : "FAIL");
}
void insert_test_invalid()
@ -135,8 +189,8 @@ void insert_test_invalid()
linked_list_insert_ref(NULL, list.head, list.tail);
linked_list_insert_ref(&list, list.head, NULL);
// 0123=====3210
print_validate(&list);
int val[] = {0,1,2,3};
printf("insert_test_invalid %s\n",assert_list(&list, val, 4) ? "PASS" : "FAIL");
}
@ -153,7 +207,8 @@ void remove_test_beginning()
linked_list_remove_idx(&list, 0);
// 10==01
print_validate(&list);
int val[] = {1,0};
printf("remove_test_beginning %s\n",assert_list(&list, val, 2) ? "PASS" : "FAIL");
}
void remove_test_middle()
@ -173,7 +228,8 @@ void remove_test_middle()
linked_list_remove_idx(&list, 2);
// 5310=====0135
print_validate(&list);
int val[] = {5,3,1,0};
printf("remove_test_middle %s\n",assert_list(&list, val, 4) ? "PASS" : "FAIL");
}
void remove_test_end()
@ -189,17 +245,16 @@ void remove_test_end()
linked_list_remove_idx(&list, 3);
linked_list_remove_idx(&list, 2);
// 01=====10
print_validate(&list);
int val[] = {0,1};
printf("remove_test_all %s\n",assert_list(&list, val, 2) ? "PASS" : "FAIL");
}
void remove_test_all()
{
bool result = true;
linked_list_t list;
linked_list_init(&list);
printf("remove all:");
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
insert_val(&list, 2, 2);
@ -210,8 +265,7 @@ void remove_test_all()
linked_list_remove_idx(&list, 0);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
result = result && assert_list(&list, NULL, 0);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
@ -223,8 +277,7 @@ void remove_test_all()
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
result = result && assert_list(&list, NULL, 0);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
@ -236,10 +289,9 @@ void remove_test_all()
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
result = result && assert_list(&list, NULL, 0);
printf("\n");
printf("remove_test_end %s\n",result ? "PASS" : "FAIL");
}
void remove_test_invalid()
@ -268,11 +320,13 @@ void remove_test_invalid()
linked_list_remove_ref(&list, NULL);
// 0123=====3210
print_validate(&list);
int val[] = {0,1,2,3};
printf("remove_test_invalid %s\n",assert_list(&list, val, 4) ? "PASS" : "FAIL");
}
void size_test()
{
bool result = true;
linked_list_t list;
linked_list_init(&list);
linked_list_t list2;
@ -283,13 +337,15 @@ void size_test()
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
printf((linked_list_size(&list) == 4 && linked_list_size(&list2) == 0 && linked_list_size(NULL) == -1) ? "size: okay" : "size: oops");
validate_list(&list);
printf("\n");
result = result && (linked_list_size(&list) == 4 && linked_list_size(&list2) == 0 && linked_list_size(NULL) == -1);
int val[] = {0,1,2,3};
result = result && assert_list(&list, val, 4);
printf("size_test %s\n", result ? "PASS" : "FAIL");
}
void push_pop_front_test()
{
bool result = true;
linked_list_t list;
linked_list_init(&list);
@ -299,23 +355,25 @@ void push_pop_front_test()
push_front_val(&list, 4);
//4321==1234
print_validate(&list);
int val1[] = {4,3,2,1};
result = result && assert_list(&list, val1, 4);
linked_list_pop_front(&list);
//321==123
print_validate(&list);
int val2[] = {3,2,1};
result = result && assert_list(&list, val2, 3);
linked_list_pop_front(&list);
linked_list_pop_front(&list);
linked_list_pop_front(&list);
printf((linked_list_size(&list) == 0 )? " YEAH" : " NO");
validate_list(&list);
printf("\n");
result = result && assert_list(&list, NULL, 0);
printf("push_pop_front_test %s\n", result ? "PASS" : "FAIL");
}
void push_pop_back_test()
{
bool result = true;
linked_list_t list;
linked_list_init(&list);
@ -325,19 +383,56 @@ void push_pop_back_test()
push_back_val(&list, 4);
//1234==4321
print_validate(&list);
int val1[] = {1,2,3,4};
result = result && assert_list(&list, val1, 4);
linked_list_pop_back(&list);
//123==321
print_validate(&list);
int val2[] = {1,2,3};
result = result && assert_list(&list, val2, 3);
linked_list_pop_back(&list);
linked_list_pop_back(&list);
linked_list_pop_back(&list);
printf((linked_list_size(&list) == 0 )? " YEAH" : " NO");
validate_list(&list);
printf("\n");
result = result && assert_list(&list, NULL, 0);
printf("push_pop_back_test %s\n", result ? "PASS" : "FAIL");
}
bool equals(linked_list_node_t* a, linked_list_node_t* b)
{
return (int)a == OBTAIN_STRUCT_ADDR(b, lnode, my_list)->val;
}
void search_test()
{
bool result = true;
linked_list_t list;
linked_list_init(&list);
push_back_val(&list, 1);
push_back_val(&list, 2);
push_back_val(&list, 3);
push_back_val(&list, 4);
int val1[] = {1,2,3,4};
result = result && assert_list(&list, val1, 4);
result = result && (linked_list_search(&list, 4 ,equals) == 3);
result = result && (linked_list_search(&list, 3 ,equals) == 2);
result = result && (linked_list_search(&list, 2 ,equals) == 1);
result = result && (linked_list_search(&list, 1 ,equals) == 0);
result = result && (linked_list_search(&list, NULL ,equals) == -1);
result = result && (linked_list_search(NULL, 1 ,equals) == -1);
linked_list_node_t* node = linked_list_get(&list, 1);
result = result && (linked_list_search(&list, node , NULL) == 1);
result = result && assert_list(&list, val1, 4);
printf("search_test %s\n", result ? "PASS" : "FAIL");
}
@ -360,6 +455,8 @@ int main(void)
push_pop_front_test();
push_pop_back_test();
search_test();
return 0;
}

View File

@ -1,16 +0,0 @@
3210======0123 good
256410======014652 good
0123======3210 good
0123======3210 good
10======01 good
5310======0135 good
01======10 good
0123======3210 good
size: okay good
remove all: YEAH good YEAH good YEAH good
4321======1234 good
321======123 good
YEAH good
1234======4321 good
123======321 good
YEAH good

View File

@ -10,6 +10,69 @@ static void SAPI _init_linked_list_node(linked_list_node_t *node)
return;
}
static void SAPI _append_node(linked_list_node_t *target, linked_list_node_t *node)
{
if(target == NULL || node == NULL)
return;
linked_list_node_t* next = target->next;
// update the next node
if(next != NULL)
{
next->prev = node;
}
// update the target node
target->next = node;
// update the node itself
node->prev = target;
node->next = next;
return;
}
// link target with node, suppose target is in the current list
static void SAPI _prepend_node(linked_list_node_t *target, linked_list_node_t *node)
{
if(target == NULL || node == NULL)
return;
linked_list_node_t* prev = target->prev;
// update the prev node
if(prev != NULL)
{
prev->next = node;
}
// update the target node
target->prev = node;
// update the node itself
node->next = target;
node->prev = prev;
return;
}
static void SAPI _unlink_node(linked_list_node_t* node)
{
if(node == NULL)
return;
if(node->prev != NULL)
{
node->prev->next = node->next;
}
if(node->next != NULL)
{
node->next->prev = node->prev;
}
return;
}
void SAPI linked_list_init(linked_list_t *list)
{
if (list != NULL)
@ -20,14 +83,14 @@ void SAPI linked_list_init(linked_list_t *list)
return;
}
int SAPI linked_list_size(linked_list_t *list)
int32_t SAPI linked_list_size(linked_list_t *list)
{
if (list == NULL)
return -1;
if (list->head == NULL)
return 0;
int size = 1;
int32_t size = 1;
linked_list_node_t *cur_node = list->head;
linked_list_node_t *tail = list->tail;
while ((cur_node != tail) && ((cur_node = cur_node->next) != NULL))
@ -85,47 +148,34 @@ void SAPI linked_list_insert_ref(linked_list_t *list, linked_list_node_t *prev_n
if (prev_node == NULL)
{
// if prev_node is NULL, then we are inserting to the head
if (list->head == NULL)
// linked node with list->head
_prepend_node(list->head, node);
if (list->tail == NULL)
{
// if the list is empty
list->head = node;
// if the list is empty, we assign list->tail to node too
list->tail = node;
}
else
{
// not empty
linked_list_node_t *cur_node = list->head;
node->next = cur_node;
node->prev = cur_node->prev;
cur_node->prev = node;
list->head = node;
}
list->head = node;
}
else
{
// if prev_node is not NULL, we are inserting to the middle or the end
if (prev_node->next != NULL)
{
// if not the end
linked_list_node_t *next_node = prev_node->next;
// add to the chain
next_node->prev = node;
prev_node->next = node;
node->prev = prev_node;
node->next = next_node;
}
else
// linked node with the prev_node
_append_node(prev_node, node);
if (node->next == NULL)
{
// we are inserting at the end of the list
prev_node->next = node;
node->prev = prev_node;
// if it's the end
list->tail = node;
}
}
}
void SAPI linked_list_insert_idx(linked_list_t *list, int index, linked_list_node_t *node)
void SAPI linked_list_insert_idx(linked_list_t *list, int32_t index, linked_list_node_t *node)
{
if (list == NULL || index < 0 || node == NULL)
return;
@ -147,7 +197,7 @@ void SAPI linked_list_insert_idx(linked_list_t *list, int index, linked_list_nod
return;
}
linked_list_node_t *SAPI linked_list_remove_idx(linked_list_t *list, int index)
linked_list_node_t *SAPI linked_list_remove_idx(linked_list_t *list, int32_t index)
{
if (list == NULL || index < 0)
return NULL;
@ -164,36 +214,16 @@ linked_list_node_t *SAPI linked_list_remove_ref(linked_list_t *list, linked_list
if (list == NULL || node == NULL)
return NULL;
if (node->next == NULL && node->prev == NULL)
_unlink_node(node);
if(node->next == NULL)
{
// the only node
list->head = NULL;
list->tail = NULL;
list->tail = node->prev;
}
if (node->next != NULL)
if(node->prev == NULL)
{
// there is something after node
linked_list_node_t *next_node = node->next;
next_node->prev = node->prev;
if (node->prev == NULL)
{
// first element
list->head = next_node;
}
}
if (node->prev != NULL)
{
// there is something before the node
linked_list_node_t *prev_node = node->prev;
prev_node->next = node->next;
if (node->next == NULL)
{
// last element
list->tail = prev_node;
}
list->head = node->next;
}
_init_linked_list_node(node);
@ -201,7 +231,7 @@ linked_list_node_t *SAPI linked_list_remove_ref(linked_list_t *list, linked_list
return node;
}
linked_list_node_t *SAPI linked_list_get(linked_list_t *list, int index)
linked_list_node_t *SAPI linked_list_get(linked_list_t *list, int32_t index)
{
if (list == NULL || index < 0 || list->head == NULL)
return NULL;
@ -248,6 +278,37 @@ linked_list_node_t *SAPI linked_list_last(linked_list_t *list)
return result;
}
int32_t SAPI linked_list_search(linked_list_t *list, linked_list_node_t *target, bool (*equals)(linked_list_node_t *, linked_list_node_t *))
{
if(list == NULL || target == NULL)
return -1;
int32_t result = 0;
linked_list_node_t* node = linked_list_first(list);
while(node != NULL)
{
if(equals !=NULL)
{
if (equals(target, node))
{
return result;
}
}
else
{
if(target->next == node->next && target->prev == node->prev)
{
return result;
}
}
result++;
node = linked_list_next(node);
}
return -1;
}

View File

@ -27,15 +27,15 @@ linked_list_node_t *SAPI linked_list_pop_front(linked_list_t *list);
linked_list_node_t *SAPI linked_list_pop_back(linked_list_t *list);
void SAPI linked_list_insert_idx(linked_list_t *list, int index, linked_list_node_t *node);
void SAPI linked_list_insert_idx(linked_list_t *list, int32_t index, linked_list_node_t *node);
void SAPI linked_list_insert_ref(linked_list_t *list, linked_list_node_t *prev_node, linked_list_node_t *node);
linked_list_node_t *SAPI linked_list_remove_idx(linked_list_t *list, int index);
linked_list_node_t *SAPI linked_list_remove_idx(linked_list_t *list, int32_t index);
linked_list_node_t *SAPI linked_list_remove_ref(linked_list_t *list, linked_list_node_t *node);
linked_list_node_t *SAPI linked_list_get(linked_list_t *list, int index);
linked_list_node_t *SAPI linked_list_get(linked_list_t *list, int32_t index);
linked_list_node_t *SAPI linked_list_next(linked_list_node_t *node);
@ -45,4 +45,8 @@ linked_list_node_t *SAPI linked_list_first(linked_list_t *list);
linked_list_node_t *SAPI linked_list_last(linked_list_t *list);
int32_t SAPI linked_list_search(linked_list_t *list, linked_list_node_t* target, bool (*equals)(linked_list_node_t*, linked_list_node_t*));
#define OBTAIN_STRUCT_ADDR(member_addr, member_name, struct_name) ((struct_name*)((char*)(member_addr)-(char*)(&(((struct_name*)0)->member_name))))
#endif

View File

@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include "type.h"
#define SAPI __attribute__((sysv_abi))
@ -48,6 +49,6 @@ static inline uint32_t seg_selector(uint32_t index, uint32_t rpl)
return (index << 3) + rpl;
}
#define OBTAIN_STRUCT_ADDR(member_addr, member_name, struct_name) ((struct_name*)((char*)(member_addr)-(uint64_t)(&(((struct_name*)0)->member_name))))
#define OBTAIN_STRUCT_ADDR(member_addr, member_name, struct_name) ((struct_name*)((void*)(member_addr)-(void*)(&(((struct_name*)0)->member_name))))
#endif