From d6f2342d056290c5f6bb1bf12698f8f68228dccc Mon Sep 17 00:00:00 2001 From: secXsQuared Date: Tue, 17 May 2016 22:43:48 -0700 Subject: [PATCH] Rewrite linked list library. Much more APIs, more graceful code and better test cases. --- Test/linked_list_test.c | 365 ++++++++++++++++++ Test/linked_list_test_output.txt | 16 + .../common/lib/list/linked_list/linked_list.c | 334 ++++++++++------ .../common/lib/list/linked_list/linked_list.h | 42 +- x64/src/c/kernel/entry.c | 2 +- x64/src/c/kernel/pmm.c | 8 +- 6 files changed, 638 insertions(+), 129 deletions(-) create mode 100644 Test/linked_list_test.c create mode 100644 Test/linked_list_test_output.txt diff --git a/Test/linked_list_test.c b/Test/linked_list_test.c new file mode 100644 index 0000000..a588d01 --- /dev/null +++ b/Test/linked_list_test.c @@ -0,0 +1,365 @@ +#include +#include +#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; +} + diff --git a/Test/linked_list_test_output.txt b/Test/linked_list_test_output.txt new file mode 100644 index 0000000..12e2540 --- /dev/null +++ b/Test/linked_list_test_output.txt @@ -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 diff --git a/x64/src/c/common/lib/list/linked_list/linked_list.c b/x64/src/c/common/lib/list/linked_list/linked_list.c index 1aee957..cdefd94 100644 --- a/x64/src/c/common/lib/list/linked_list/linked_list.c +++ b/x64/src/c/common/lib/list/linked_list/linked_list.c @@ -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; -} \ No newline at end of file + + 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; +} + + + + + + + + + + + + + diff --git a/x64/src/c/common/lib/list/linked_list/linked_list.h b/x64/src/c/common/lib/list/linked_list/linked_list.h index b96c51a..129f44c 100644 --- a/x64/src/c/common/lib/list/linked_list/linked_list.h +++ b/x64/src/c/common/lib/list/linked_list/linked_list.h @@ -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 \ No newline at end of file diff --git a/x64/src/c/kernel/entry.c b/x64/src/c/kernel/entry.c index 2355e59..b3bfe01 100644 --- a/x64/src/c/kernel/entry.c +++ b/x64/src/c/kernel/entry.c @@ -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), diff --git a/x64/src/c/kernel/pmm.c b/x64/src/c/kernel/pmm.c index dcfe47a..9e422eb 100644 --- a/x64/src/c/kernel/pmm.c +++ b/x64/src/c/kernel/pmm.c @@ -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)