Rewrite linked list library. Much more APIs, more graceful code and better test cases.

This commit is contained in:
secXsQuared 2016-05-17 22:43:48 -07:00
parent 9ca5b1aa16
commit d6f2342d05
6 changed files with 638 additions and 129 deletions

365
Test/linked_list_test.c Normal file
View File

@ -0,0 +1,365 @@
#include <stdlib.h>
#include <printf.h>
#include "linked_list.h"
typedef struct
{
linked_list_node_t lnode;
int val;
} my_list;
void 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;
if(list->head != NULL)
good += list->head->prev == NULL;
if(list->tail != NULL)
good += list->tail->next == NULL;
printf(good == 2 ? " good" : " bad");
}
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));
a->val = val;
linked_list_insert_idx(list, index, &a->lnode);
}
void push_back_val(linked_list_t* list, int val)
{
my_list *a = (my_list*)malloc(sizeof(my_list));
a->val = val;
linked_list_push_back(list, &a->lnode);
}
void push_front_val(linked_list_t* list, int val)
{
my_list *a = (my_list*)malloc(sizeof(my_list));
a->val = val;
linked_list_push_front(list, &a->lnode);
}
void insert_test_beginning()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 0, 1);
insert_val(&list, 0, 2);
insert_val(&list, 0, 3);
// 3210==0123
print_validate(&list);
}
void insert_test_middle()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 0, 1);
insert_val(&list, 0, 2);
insert_val(&list, 1, 4);
insert_val(&list, 1, 5);
insert_val(&list, 2, 6);
// 256410=====014652
print_validate(&list);
}
void insert_test_end()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
// 0123=====3210
print_validate(&list);
}
void insert_test_invalid()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 3);
insert_val(&list, 0, 2);
insert_val(&list, 0, 1);
insert_val(&list, 0, 0);
// large index
insert_val(&list, 5, 9);
insert_val(&list, 6, 9);
insert_val(&list, 999, 9);
// small index
insert_val(&list, -1, 8);
insert_val(&list, -2, 8);
insert_val(&list, -999, 8);
// NULL
insert_val(NULL, 1, 4);
linked_list_insert_ref(NULL, list.head, list.tail);
linked_list_insert_ref(&list, list.head, NULL);
// 0123=====3210
print_validate(&list);
}
void remove_test_beginning()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 0, 1);
insert_val(&list, 0, 2);
insert_val(&list, 0, 3);
linked_list_remove_idx(&list, 0);
linked_list_remove_idx(&list, 0);
// 10==01
print_validate(&list);
}
void remove_test_middle()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 0, 1);
insert_val(&list, 0, 2);
insert_val(&list, 0, 3);
insert_val(&list, 0, 4);
insert_val(&list, 0, 5);
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 2);
// 5310=====0135
print_validate(&list);
}
void remove_test_end()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
linked_list_remove_idx(&list, 3);
linked_list_remove_idx(&list, 2);
// 01=====10
print_validate(&list);
}
void remove_test_all()
{
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);
insert_val(&list, 3, 3);
linked_list_remove_idx(&list, 0);
linked_list_remove_idx(&list, 0);
linked_list_remove_idx(&list, 0);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
linked_list_remove_idx(&list, 3);
linked_list_remove_idx(&list, 2);
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
insert_val(&list, 2, 2);
insert_val(&list, 3, 3);
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 1);
linked_list_remove_idx(&list, 0);
printf(linked_list_size(&list) == 0 ? " YEAH" : " NO");
validate_list(&list);
printf("\n");
}
void remove_test_invalid()
{
linked_list_t list;
linked_list_init(&list);
insert_val(&list, 0, 3);
insert_val(&list, 0, 2);
insert_val(&list, 0, 1);
insert_val(&list, 0, 0);
// large index
linked_list_remove_idx(&list, 5);
linked_list_remove_idx(&list, 6);
linked_list_remove_idx(&list, 999);
// small index
linked_list_remove_idx(&list, -1);
linked_list_remove_idx(&list, -2);
linked_list_remove_idx(&list, -999);
// NULL
linked_list_remove_idx(NULL, 1);
linked_list_remove_ref(NULL, list.head);
linked_list_remove_ref(&list, NULL);
// 0123=====3210
print_validate(&list);
}
void size_test()
{
linked_list_t list;
linked_list_init(&list);
linked_list_t list2;
linked_list_init(&list2);
insert_val(&list, 0, 0);
insert_val(&list, 1, 1);
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");
}
void push_pop_front_test()
{
linked_list_t list;
linked_list_init(&list);
push_front_val(&list, 1);
push_front_val(&list, 2);
push_front_val(&list, 3);
push_front_val(&list, 4);
//4321==1234
print_validate(&list);
linked_list_pop_front(&list);
//321==123
print_validate(&list);
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");
}
void push_pop_back_test()
{
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);
//1234==4321
print_validate(&list);
linked_list_pop_back(&list);
//123==321
print_validate(&list);
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");
}
int main(void)
{
insert_test_beginning();
insert_test_middle();
insert_test_end();
insert_test_invalid();
remove_test_beginning();
remove_test_middle();
remove_test_end();
remove_test_invalid();
size_test();
remove_test_all();
push_pop_front_test();
push_pop_back_test();
return 0;
}

View File

@ -0,0 +1,16 @@
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

@ -1,156 +1,262 @@
#include "../../../sys/kdef.h"
#include "linked_list.h"
static void SAPI linked_list_node_init(linked_list_node_t * node)
static void SAPI _init_linked_list_node(linked_list_node_t *node)
{
if(node != NULL)
if (node != NULL)
{
node->prev = NULL;
node->next = NULL;
}
return;
}
static linked_list_node_t *SAPI linked_list_node_get(linked_list_node_t * head, int index)
{
if(head == NULL || index < 0)
return NULL;
while(index--)
{
head = head->next;
if(head == NULL)
break;
}
return head;
}
static int SAPI linked_list_node_size(linked_list_node_t * head)
{
int i = 0;
while(head != NULL)
{
i++;
head = head->next;
}
return i;
}
//returns new head
static linked_list_node_t *SAPI linked_list_node_insert(linked_list_node_t * head, int index, linked_list_node_t * node)
{
if(head == NULL)
return node;
if(node == NULL || index < 0)
return head;
//@ head != NULL
if(index == 0)
{
//insert at head
node->prev = NULL;
node->next = head;
head->prev = node;
return node;
}
else
{
linked_list_node_t * target = linked_list_node_get(head, index-1);
if(target == NULL)
return NULL;
node->prev = target;
node->next = target->next;
if(target->next != NULL)
target->next->prev = node;
target->next = node;
return head;
}
}
static void SAPI linked_list_node_push_back(linked_list_node_t *head, linked_list_node_t *node)
{
if(head == NULL || node == NULL)
return;
int size = linked_list_node_size(head);
linked_list_node_insert(head,size,node);
return;
}
//returns new head
static linked_list_node_t *SAPI linked_list_node_remove(linked_list_node_t *head, int index)
void SAPI linked_list_init(linked_list_t *list)
{
if(head == NULL || index < 0)
return head;
if(index == 0)
if (list != NULL)
{
linked_list_node_t * next = head->next;
linked_list_node_init(head);
if(next != NULL)
next->prev = NULL;
return next;
}
else
{
linked_list_node_t *target = linked_list_node_get(head, index);
if (target->prev != NULL)
target->prev->next = target->next;
if (target->next != NULL)
target->next->prev = target->prev;
linked_list_node_init(target);
return head;
list->head = NULL;
list->tail = NULL;
}
return;
}
void SAPI linked_list_init(linked_list_t * list)
int SAPI linked_list_size(linked_list_t *list)
{
if(list != NULL)
if (list == NULL)
return -1;
if (list->head == NULL)
return 0;
int 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))
{
list->size = 0;
list->head = NULL;
size++;
}
return size;
}
void SAPI linked_list_push_front(linked_list_t *list, linked_list_node_t *node)
{
if (list == NULL || node == NULL)
return;
_init_linked_list_node(node);
linked_list_insert_ref(list, NULL, node);
return;
}
void SAPI linked_list_push_back(linked_list_t *list, linked_list_node_t *node)
{
if(list != NULL && node != NULL)
if (list == NULL || node == NULL)
return;
_init_linked_list_node(node);
linked_list_insert_ref(list, list->tail, node);
return;
}
linked_list_node_t *SAPI linked_list_pop_front(linked_list_t *list)
{
if (list == NULL)
return NULL;
return linked_list_remove_ref(list, list->head);
}
linked_list_node_t *SAPI linked_list_pop_back(linked_list_t *list)
{
if (list == NULL)
return NULL;
return linked_list_remove_ref(list, list->tail);
}
void SAPI linked_list_insert_ref(linked_list_t *list, linked_list_node_t *prev_node, linked_list_node_t *node)
{
if (list == NULL || node == NULL)
return;
_init_linked_list_node(node);
if (prev_node == NULL)
{
//@ node != NULL
linked_list_node_init(node);
// if prev_node is NULL, then we are inserting to the head
if (list->head == NULL)
{
// if the list is empty
list->head = node;
list->tail = node;
}
else
linked_list_node_push_back(list->head, node);
list->size++;
{
// 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;
}
}
return;
}
void SAPI linked_list_insert(linked_list_t * list, int index, linked_list_node_t * node)
{
if(list != NULL && index > 0 && node != NULL)
else
{
linked_list_node_init(node);
list->head = linked_list_node_insert(list->head, index, node);
list->size++;
// 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
{
// we are inserting at the end of the list
prev_node->next = node;
node->prev = prev_node;
list->tail = node;
}
}
}
void SAPI linked_list_insert_idx(linked_list_t *list, int index, linked_list_node_t *node)
{
if (list == NULL || index < 0 || node == NULL)
return;
linked_list_node_t *prev_node = linked_list_get(list, index - 1);
_init_linked_list_node(node);
if (prev_node == NULL)
{
if (index == 0)
{
linked_list_insert_ref(list, NULL, node);
}
}
else
{
linked_list_insert_ref(list, prev_node, node);
}
return;
}
linked_list_node_t *SAPI linked_list_get(linked_list_t * list, int index)
linked_list_node_t *SAPI linked_list_remove_idx(linked_list_t *list, int index)
{
if(list == NULL || index < 0 || index >= list->size)
if (list == NULL || index < 0)
return NULL;
return linked_list_node_get(list->head,index);
linked_list_node_t *cur_node = linked_list_get(list, index);
if (cur_node == NULL)
return NULL;
return linked_list_remove_ref(list, cur_node);
}
void SAPI linked_list_remove(linked_list_t *list, int index)
linked_list_node_t *SAPI linked_list_remove_ref(linked_list_t *list, linked_list_node_t *node)
{
if(list != NULL && index >= 0 && index < list->size)
if (list == NULL || node == NULL)
return NULL;
if (node->next == NULL && node->prev == NULL)
{
list->head = linked_list_node_remove(list->head, index);
list->size--;
// the only node
list->head = NULL;
list->tail = NULL;
}
return;
}
if (node->next != 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;
}
}
_init_linked_list_node(node);
return node;
}
linked_list_node_t *SAPI linked_list_get(linked_list_t *list, int index)
{
if (list == NULL || index < 0 || list->head == NULL)
return NULL;
linked_list_node_t *cur_node = list->head;
while (index-- && (cur_node = cur_node->next) != NULL);
return cur_node;
}
linked_list_node_t *SAPI linked_list_next(linked_list_node_t *node)
{
if (node != NULL)
{
node = node->next;
}
return node;
}
linked_list_node_t *SAPI linked_list_prev(linked_list_node_t *node)
{
if (node != NULL)
{
node = node->prev;
}
return node;
}
linked_list_node_t *SAPI linked_list_first(linked_list_t *list)
{
linked_list_node_t *result = NULL;
if (list != NULL)
{
result = list->head;
}
return result;
}
linked_list_node_t *SAPI linked_list_last(linked_list_t *list)
{
linked_list_node_t *result = NULL;
if (list != NULL)
{
result = list->tail;
}
return result;
}

View File

@ -1,26 +1,48 @@
#ifndef _LINKED_LIST_H_
#define _LINKED_LIST_H_
#include "../../../sys/kdef.h"
typedef struct _linked_list_node_t
{
struct _linked_list_node_t * prev;
struct _linked_list_node_t * next;
struct _linked_list_node_t *prev;
struct _linked_list_node_t *next;
} linked_list_node_t;
typedef struct
typedef struct _linked_list_t
{
linked_list_node_t * head;
int size;
linked_list_node_t *head;
linked_list_node_t *tail;
} linked_list_t;
void SAPI linked_list_init(linked_list_t * list);
void SAPI linked_list_init(linked_list_t *list);
int SAPI linked_list_size(linked_list_t *list);
void SAPI linked_list_push_front(linked_list_t *list, linked_list_node_t *node);
void SAPI linked_list_push_back(linked_list_t *list, linked_list_node_t *node);
void SAPI linked_list_insert(linked_list_t * list, int index, linked_list_node_t * node);
linked_list_node_t *SAPI linked_list_pop_front(linked_list_t *list);
linked_list_node_t *SAPI linked_list_get(linked_list_t * list, int index);
linked_list_node_t *SAPI linked_list_pop_back(linked_list_t *list);
void SAPI linked_list_remove(linked_list_t *list, int index);
void SAPI linked_list_insert_idx(linked_list_t *list, int index, linked_list_node_t *node);
#endif
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_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_next(linked_list_node_t *node);
linked_list_node_t *SAPI linked_list_prev(linked_list_node_t *node);
linked_list_node_t *SAPI linked_list_first(linked_list_t *list);
linked_list_node_t *SAPI linked_list_last(linked_list_t *list);
#endif

View File

@ -14,7 +14,7 @@ void SAPI kmain(multiboot_info_t *multiboot_info)
{
hal_printf("Installed Memory: %uB\n", boot_info->mem_info->mem_installed);
hal_printf("Useable Memory: %uB\n", boot_info->mem_info->mem_available);
for(int i = 0; i < boot_info->mem_info->free_page_list->size; i++)
for(int i = 0; i < linked_list_size(boot_info->mem_info->free_page_list); i++)
{
memory_descriptor_node_t* each_node = OBTAIN_STRUCT_ADDR(
linked_list_get(boot_info->mem_info->free_page_list,i),

View File

@ -17,13 +17,13 @@ void _pmm_add_page(linked_list_t* list,uint64_t base_addr, uint64_t size)
{
hal_assert(list != NULL,NULL);
base_addr = (base_addr >> 12) << 12;
if(list->size == 0)
if(linked_list_size(list) == 0)
{
return;
}
else
{
for (int i = 0; i < list->size; i++) {
for (int i = 0; i < linked_list_size(list); i++) {
memory_descriptor_node_t *each_node = OBTAIN_STRUCT_ADDR(linked_list_get(list, i), list_node,
memory_descriptor_node_t);
@ -34,9 +34,9 @@ void _pmm_add_page(linked_list_t* list,uint64_t base_addr, uint64_t size)
void* pmm_alloc_page()
{
hal_assert(occupied_mem != NULL && available_mem != NULL, NULL);
if(available_mem->size == 0)
if(linked_list_size(available_mem) == 0)
return NULL;
for(int i = 0; i < available_mem->size; i++)
for(int i = 0; i < linked_list_size(available_mem); i++)
{
// memory_descriptor_node_t* each_node = OBTAIN_STRUCT_ADDR(linked_list_get(available_mem,i),list_node,memory_descriptor_node_t);
// if(each_node->size >= PHYSICAL_PAGE_SIZE)