Changed the interface for linked list and avl tree to a much more flexible one. The previous one was utter crap..

This commit is contained in:
HyperAssembler 2015-03-21 14:17:38 -07:00
parent ab103126b6
commit 7db4e9cf35
10 changed files with 524 additions and 459 deletions

84
Test/avl_tree_test.c Normal file
View File

@ -0,0 +1,84 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "avl_tree.h"
typedef struct __attribute__ ((packed))
{
avl_tree_node node;
int val;
} int_node;
int compare(void* a, void* b)
{
int_node* aa = (int_node*)a;
int_node* bb = (int_node*)b;
if(aa->val > bb->val)
return 1;
else if(aa->val < bb->val)
return -1;
return 0;
}
void in_order_print(avl_tree_node *tree)
{
if (tree == NULL)
return;
avl_tree_node* node = avl_tree_node_largest(tree);
while(node != NULL)
{
printf("%d ", ((int_node*)node)->val);
node = avl_tree_node_prev(node);
}
return;
}
int_node* create_int_node(int val)
{
int_node* node = (int_node*)malloc(sizeof(int_node));
avl_tree_node_init(&node->node);
node->val = val;
return node;
}
int main (void)
{
int_node* val[1000];
srand((unsigned int)time(NULL));
avl_tree* avlTree = (avl_tree*)malloc(sizeof(avl_tree));
avl_tree_init(avlTree);
//test INSERT general
int i = 0;
for(i = 0; i < 1000; i++)
{
val[i] = create_int_node(rand()%10000);
avl_tree_insert(avlTree,(avl_tree_node*)val[i],compare);
assert(avl_tree_node_test(avlTree->root,compare));
}
//test Delete general
for(i = 0; i < 1000; i++)
{
avl_tree_delete(avlTree,val[i],compare);
assert(avl_tree_node_test(avlTree->root,compare));
free(val[i]);
}
//test delete visualized
for(i = 0; i < 20; i++)
{
val[i] = create_int_node(rand()%2000);
avl_tree_insert(avlTree,(avl_tree_node*)val[i],compare);
assert(avl_tree_node_test(avlTree->root,compare));
}
in_order_print(avlTree->root);
for(i = 0; i < 20; i++)
{
avl_tree_delete(avlTree,(avl_tree_node*)val[i],compare);
printf("\nDeleting: %d\n",val[i]->val);
in_order_print(avlTree->root);
assert(avl_tree_node_test(avlTree->root,compare));
free(val[i]);
}
free(avlTree);
return 0;
}

View File

@ -1,99 +0,0 @@
#include <stdio.h>
#include <assert.h>
#include "linked_list.h"
void print_list(linked_list* list)
{
linked_list_iterator* it = linked_list_create_iterator(list);
it->current = list->tail;
while(it->current)
{
printf("%lu ", (unsigned long)it->current->data);
linked_list_prev(it);
}
printf("\n");
}
void insert_test(void)
{
printf("insert test\n");
linked_list* list;
//empty list at test
list = linked_list_create();
linked_list_insert_at(list,0,(void*)2);
assert(list->size == 1 && list->head == list->tail && (int)list->head->data == 2);
print_list(list);
//tail test
linked_list_insert_at(list,1,(void*)3);
assert(list->size == 2 && (int)list->tail->data == 3);
print_list(list);
//head test
linked_list_insert_at(list,0,(void*)1);
assert(list->size == 3 && (int)list->head->data == 1);
print_list(list);
//invalid index test
linked_list_insert_at(list,4,(void*)1);
assert(list->size == 3 && (int)list->head->data == 1 && (int)list->tail->data == 3);
print_list(list);
//normal test
linked_list_insert_at(list,1,(void*)5);
assert(list->size == 4 && (int)list->head->next->data == 5 && (int)list->head->next->next->data == 2);
print_list(list);
linked_list_free(list,NULL);
return;
}
void delete_test(void)
{
printf("delete test\n");
linked_list* list;
//empty list at test
list = linked_list_create();
linked_list_insert(list,(void*)1);
linked_list_insert(list,(void*)2);
linked_list_insert(list,(void*)3);
linked_list_insert(list,(void*)4);
linked_list_insert(list,(void*)5);
//head test
linked_list_delete_at(list,0);
assert(list->size == 4 && (int)list->head->data == 2);
print_list(list);
//tail test
linked_list_delete_at(list,list->size-1);
assert(list->size == 3 && (int)list->tail->data == 4);
print_list(list);
//normal test
linked_list_delete_at(list,1);
assert(list->size == 2 && (int)list->head->data == 2 && (int)list->head->next->data==4);
print_list(list);
//invalid index test
linked_list_delete_at(list,2);
assert(list->size == 2 && (int)list->head->data == 2 && (int)list->head->next->data==4);
print_list(list);
//delete last test
linked_list_delete_at(list,0);
linked_list_delete_at(list,0);
assert(list->size == 0 && list->head == NULL && list->tail == NULL);
linked_list_free(list,NULL);
return;
}
int main(void)
{
insert_test();
delete_test();
return 0;
}

View File

@ -1,23 +1,21 @@
#include "kdef.h" #include "kdef.h"
#include "mm.h"
#include "avl_tree.h" #include "avl_tree.h"
#define MAX(a, b) (((a) > (b) ? (a) : (b))) #define MAX(a, b) (((a) > (b) ? (a) : (b)))
// internal int NATIVE64 _avl_tree_node_get_height(avl_tree_node *node)
int NATIVE64 _avl_tree_get_height(avl_tree_node *node)
{ {
return node == NULL ? -1 : node->height; return node == NULL ? -1 : node->height;
} }
int NATIVE64 _avl_tree_get_balance_factor(avl_tree_node *node) int NATIVE64 _avl_tree_node_get_balance_factor(avl_tree_node *node)
{ {
if (node == NULL) if (node == NULL)
return 0; return 0;
return _avl_tree_get_height(node->left) - _avl_tree_get_height(node->right); return _avl_tree_node_get_height(node->left) - _avl_tree_node_get_height(node->right);
} }
avl_tree_node * NATIVE64 _avl_tree_right_rotate(avl_tree_node *root) avl_tree_node * NATIVE64 _avl_tree_node_right_rotate(avl_tree_node *root)
{ {
avl_tree_node *left_children = root->left; avl_tree_node *left_children = root->left;
//adjust parents first //adjust parents first
@ -29,12 +27,12 @@ avl_tree_node * NATIVE64 _avl_tree_right_rotate(avl_tree_node *root)
root->left = root->left->right; root->left = root->left->right;
left_children->right = root; left_children->right = root;
//adjust height //adjust height
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1; root->height = MAX(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
left_children->height = MAX(_avl_tree_get_height(left_children->left), _avl_tree_get_height(left_children->right)) + 1; left_children->height = MAX(_avl_tree_node_get_height(left_children->left), _avl_tree_node_get_height(left_children->right)) + 1;
return left_children; return left_children;
} }
avl_tree_node * NATIVE64 _avl_tree_left_rotate(avl_tree_node *root) avl_tree_node * NATIVE64 _avl_tree_node_left_rotate(avl_tree_node *root)
{ {
avl_tree_node *right_children = root->right; avl_tree_node *right_children = root->right;
//adjust parents //adjust parents
@ -46,41 +44,41 @@ avl_tree_node * NATIVE64 _avl_tree_left_rotate(avl_tree_node *root)
root->right = root->right->left; root->right = root->right->left;
right_children->left = root; right_children->left = root;
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1; root->height = MAX(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
right_children->height = MAX(_avl_tree_get_height(right_children->left), _avl_tree_get_height(right_children->right)) + 1; right_children->height = MAX(_avl_tree_node_get_height(right_children->left), _avl_tree_node_get_height(right_children->right)) + 1;
return right_children; return right_children;
} }
avl_tree_node * NATIVE64 _avl_tree_balance_node(avl_tree_node *node) avl_tree_node * NATIVE64 _avl_tree_node_balance(avl_tree_node *node)
{ {
const int bf = _avl_tree_get_balance_factor(node); const int bf = _avl_tree_node_get_balance_factor(node);
if (bf > 1) if (bf > 1)
{ {
const int left_bf = _avl_tree_get_balance_factor(node->left); const int left_bf = _avl_tree_node_get_balance_factor(node->left);
if (left_bf >= 0) if (left_bf >= 0)
//left left //left left
return _avl_tree_right_rotate(node); return _avl_tree_node_right_rotate(node);
else else
{ {
//left right //left right
node->left = _avl_tree_left_rotate(node->left); node->left = _avl_tree_node_left_rotate(node->left);
return _avl_tree_right_rotate(node); return _avl_tree_node_right_rotate(node);
} }
} }
else if (bf < -1) else if (bf < -1)
{ {
const int right_bf = _avl_tree_get_balance_factor(node->right); const int right_bf = _avl_tree_node_get_balance_factor(node->right);
if (right_bf <= 0) if (right_bf <= 0)
{ {
// right right // right right
return _avl_tree_left_rotate(node); return _avl_tree_node_left_rotate(node);
} }
else else
{ {
// right left // right left
node->right = _avl_tree_right_rotate(node->right); node->right = _avl_tree_node_right_rotate(node->right);
return _avl_tree_left_rotate(node); return _avl_tree_node_left_rotate(node);
} }
} }
else else
@ -88,87 +86,166 @@ avl_tree_node * NATIVE64 _avl_tree_balance_node(avl_tree_node *node)
} }
avl_tree_node * NATIVE64 _avl_tree_node_insert(avl_tree_node *root, avl_tree_node *node, int(*compare)(void *, void *), avl_tree_node *parent)
void * NATIVE64 _avl_tree_search(avl_tree_node *root, void *data, int(*compare)(void *, void *))
{ {
if(root == NULL) if (node == NULL)
return NULL;
const int comp = compare(root->data, data);
if (comp < 0)
return _avl_tree_search(root->right, data, compare);
else if (comp == 0)
return root->data;
else
return _avl_tree_search(root->left, data, compare);
}
void * NATIVE64 avl_tree_search(avl_tree *root, void *data, int(*compare)(void *, void *))
{
if(root == NULL || data == NULL)
return NULL;
return _avl_tree_search(root->root, data, compare);
}
avl_tree_node * NATIVE64 _avl_tree_create_node()
{
avl_tree_node *tree = (avl_tree_node *) (kmalloc(sizeof(avl_tree_node)));
tree->parent = NULL;
tree->data = NULL;
tree->right = NULL;
tree->left = NULL;
tree->height = 0;
return tree;
}
avl_tree_node * NATIVE64 _avl_tree_insert(avl_tree_node *root, void *data, int(*compare)(void *, void *), avl_tree_node *parent)
{
if (data == NULL)
return root; return root;
if (root == NULL) if (root == NULL)
{ {
avl_tree_node *tree = _avl_tree_create_node(); node->parent = parent;
tree->data = data; return node;
tree->parent = parent;
return tree;
} }
const int comp = compare(root->data, data); const int comp = compare(root, node);
if (comp < 0) if (comp < 0)
{ root->right = _avl_tree_node_insert(root->right, node, compare, root);
root->right = _avl_tree_insert(root->right, data, compare, root);
}
else if (comp == 0) else if (comp == 0)
return root; return root;
else else
root->left = _avl_tree_insert(root->left, data, compare, root); root->left = _avl_tree_node_insert(root->left, node, compare, root);
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1; root->height = MAX(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
return _avl_tree_balance_node(root); return _avl_tree_node_balance(root);
} }
void NATIVE64 avl_tree_insert(avl_tree *tree, void *data, int (*compare)(void *, void *)) void _swap_nodes(avl_tree_node *node1, avl_tree_node *node2)
{ {
if(tree != NULL && data != NULL && compare != NULL) if (node1 == NULL || node2 == NULL)
return;
avl_tree_node *parent = NULL;
avl_tree_node *child = NULL;
avl_tree_node *temp = NULL;
//swap node but does not change anything else other than node1,node2
if (node1->parent != NULL && node1->parent == node2)
{ {
if(avl_tree_search(tree, data, compare) == NULL) parent = node2;
child = node1;
}
else if (node2->parent != NULL && node2->parent == node1)
{
parent = node1;
child = node2;
}
if (parent != NULL && child != NULL)
{
//connected case
if(parent->parent != NULL)
{ {
tree->root = _avl_tree_insert(tree->root, data, compare, NULL); if(parent->parent->left == parent)
tree->size++; parent->parent->left = child;
else
parent->parent->right = child;
}
//update left/right for parent
if(parent->left != NULL && child != parent->left)
{
parent->left->parent = child;
}
if(parent->right != NULL && child != parent->right)
{
parent->right->parent = child;
}
//update left/right for children
if(child->left != NULL)
child->left->parent = parent;
if(child->right != NULL)
child->right->parent = parent;
child->parent = parent->parent;
parent->parent = child;
if (child == parent->left)
{
// parent
// / \
// children
parent->left = child->left;
child->left = parent;
temp = parent->right;
parent->right = child->right;
child->right = temp;
}
else
{
// parent
// / \
// children
parent->right = child->right;
child->right = parent;
temp = parent->left;
parent->left = child->left;
child->left = temp;
} }
} }
else
{
//not connected case
//adjust all the nodes other than node1,node2
if(node1->left != NULL)
node1->left->parent = node2;
if(node1->right != NULL)
node1->right->parent = node2;
if(node2->left != NULL)
node2->left->parent = node1;
if(node2->right != NULL)
node2->right->parent = node1;
if(node1->parent != NULL)
{
if(node1->parent->left == node1)
node1->parent->left = node2;
else
node1->parent->right = node2;
}
if(node2->parent != NULL)
{
if(node2->parent->left == node2)
node2->parent->left = node1;
else
node2->parent->right = node1;
}
//adjust node1,node2
temp = node1->parent;
node1->parent = node2->parent;
node2->parent = temp;
temp = node1->left;
node1->left = node2->left;
node2->left = temp;
temp = node1->right;
node1->right = node2->right;
node2->right = temp;
}
//swap height
int height = node1->height;
node1->height = node2->height;
node2->height = height;
return; return;
} }
avl_tree_node * NATIVE64 _avl_tree_delete(avl_tree_node *root, void *data, int (*compare)(void *, void *)) //Interface
avl_tree_node* NATIVE64 avl_tree_node_insert(avl_tree_node* root, avl_tree_node* node, int(*compare)(void*,void*))
{ {
if (root == NULL || data == NULL) return _avl_tree_node_insert(root, node, compare, NULL);
}
avl_tree_node* NATIVE64 avl_tree_node_delete(avl_tree_node* root, avl_tree_node* node, int (*compare)(void *, void *))
{
if (root == NULL || node == NULL)
return root; return root;
const int comp = compare(root->data, data); const int comp = compare(root, node);
if (comp < 0) if (comp < 0)
root->right = _avl_tree_delete(root->right, data, compare); root->right = avl_tree_node_delete(root->right, node, compare);
else if(comp > 0) else if(comp > 0)
root->left = _avl_tree_delete(root->left, data, compare); root->left = avl_tree_node_delete(root->left, node, compare);
else else
{ {
// node with only one child or no child // node with only one child or no child
@ -178,89 +255,64 @@ avl_tree_node * NATIVE64 _avl_tree_delete(avl_tree_node *root, void *data, int (
if(child == NULL) if(child == NULL)
{ // 0 child { // 0 child
//free(root);
root = NULL; root = NULL;
} }
else // 1 child else // 1 child
{ {
//copy content of temp to root except for the parent child->parent = root->parent;
root->left = child->left; root = child;
root->right = child->right;
root->data = child->data;
root->height = child->height;
//free(child);
} }
} }
else else
{ {
// node with two children: Get the inorder successor (smallest // node with two children: Get the inorder successor (smallest
// in the right subtree) // in the right subtree)
avl_tree_node *successor = root->right;
while(successor->left != NULL)
successor = successor->left;
//swap fields
_swap_nodes(successor,root);
avl_tree_node * temp = root->right; // Detach the inorder successor
while(temp->left != NULL) successor->right = avl_tree_node_delete(successor->right, root, compare);
temp = temp->left;
// Copy the inorder successor's data to this node root = successor;
root->data = temp->data;
// Delete the inorder successor
root->right = _avl_tree_delete(root->right, temp->data, compare);
} }
} }
if (root == NULL) if (root == NULL)
return root; return root;
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1; root->height = MAX(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
root = _avl_tree_balance_node(root); root = _avl_tree_node_balance(root);
return root; return root;
} }
void NATIVE64 avl_tree_delete(avl_tree *tree, void *data, int (*compare)(void *, void *)) avl_tree_node* NATIVE64 avl_tree_node_search(avl_tree_node *root, avl_tree_node* node, int(*compare)(void *, void *))
{ {
if(tree != NULL && data != NULL && compare != NULL && tree->size != 0) if(root == NULL)
return NULL;
const int comp = compare(root, node);
if (comp < 0)
return avl_tree_node_search(root->right, node, compare);
else if (comp == 0)
return root;
else
return avl_tree_node_search(root->left, node, compare);
}
void NATIVE64 avl_tree_node_init(avl_tree_node* it)
{
if(it != NULL)
{ {
if(avl_tree_search(tree, data, compare) != NULL) it->height = 0;
{ it->left = NULL;
tree->root = _avl_tree_delete(tree->root, data, compare); it->right = NULL;
tree->size--; it->parent = NULL;
}
} }
return; return;
} }
void NATIVE64 _avl_tree_free(avl_tree_node *root, void (*delete_data)(void *))
{
if(root != NULL)
{
_avl_tree_free(root->left, delete_data);
_avl_tree_free(root->right, delete_data);
if (delete_data != NULL)
delete_data(root->data);
}
return;
}
void NATIVE64 avl_tree_free(avl_tree *tree, void (*delete_data)(void *)) avl_tree_node * NATIVE64 avl_tree_node_smallest(avl_tree_node *root)
{
if(tree != NULL)
{
_avl_tree_free(tree->root, delete_data);
kfree(tree);
}
return;
}
avl_tree * NATIVE64 avl_tree_create()
{
avl_tree* new_tree = kmalloc(sizeof(avl_tree));
new_tree->root = NULL;
new_tree->size = 0;
return new_tree;
}
//iterator
avl_tree_node * NATIVE64 _avl_tree_smallest(avl_tree_node *root)
{ {
if (root == NULL) if (root == NULL)
return NULL; return NULL;
@ -269,89 +321,135 @@ avl_tree_node * NATIVE64 _avl_tree_smallest(avl_tree_node *root)
return root; return root;
} }
avl_tree_iterator* NATIVE64 avl_tree_create_iterator(avl_tree *tree) avl_tree_node * NATIVE64 avl_tree_node_largest(avl_tree_node *root)
{ {
if(tree == NULL) if (root == NULL)
return NULL; return NULL;
avl_tree_iterator* it = (avl_tree_iterator*)kmalloc(sizeof(avl_tree_iterator)); while (root->right != NULL)
it->current = _avl_tree_smallest(tree->root); root = root->right;
return it; return root;
} }
void NATIVE64 avl_tree_next(avl_tree_iterator *it)
avl_tree_node* NATIVE64 avl_tree_node_next(avl_tree_node *it)
{ {
if (it == NULL || it->current == NULL) if (it == NULL)
return; return NULL;
avl_tree_node* root = it->current; avl_tree_node* root = it;
if (root->right != NULL) if (root->right != NULL)
{ {
root = root->right; root = root->right;
while (root->left != NULL) while (root->left != NULL)
{
root = root->left; root = root->left;
} return root;
it->current = root;
return;
} }
else else
{ {
while (root->parent != NULL) while (root->parent != NULL)
{ {
if (root->parent->left == root) if (root->parent->left == root)
{ return root->parent;
it->current = root->parent;
return;
}
root = root->parent; root = root->parent;
} }
it->current = NULL; return NULL;
return;
} }
} }
void NATIVE64 avl_tree_prev(avl_tree_iterator *it) avl_tree_node* NATIVE64 avl_tree_node_prev(avl_tree_node *it)
{ {
if (it == NULL || it->current == NULL) if (it == NULL)
return; return NULL;
avl_tree_node* root = it->current; avl_tree_node* root = it;
if (root->left != NULL) if (root->left != NULL)
{ {
root = root->left; root = root->left;
while (root->right != NULL) while (root->right != NULL)
{
root = root->right; root = root->right;
} return root;
it->current = root;
} }
else else
{ {
while (root->parent != NULL) while (root->parent != NULL)
{ {
if (root->parent->right == root) if (root->parent->right == root)
{ return root->parent;
it->current = root->parent;
}
root = root->parent; root = root->parent;
} }
it->current = NULL; return NULL;
} }
} }
avl_tree_node* avl_tree_search(avl_tree *tree, avl_tree_node* node, int (*compare)(void *, void *))
{
return avl_tree_node_search(tree->root,node,compare);
}
void NATIVE64 avl_tree_insert(avl_tree *tree, void *data, int (*compare)(void *, void *))
{
if(tree != NULL && data != NULL && compare != NULL)
{
if(avl_tree_search(tree, data, compare) == NULL)
{
tree->root = _avl_tree_node_insert(tree->root, data, compare, NULL);
tree->size++;
}
}
return;
}
void NATIVE64 avl_tree_delete(avl_tree *tree, void *data, int (*compare)(void *, void *))
{
if(tree != NULL && data != NULL && compare != NULL && tree->size != 0)
{
if(avl_tree_search(tree, data, compare) != NULL)
{
tree->root = avl_tree_node_delete(tree->root, data, compare);
tree->size--;
}
}
return;
}
void NATIVE64 avl_tree_init(avl_tree* tree)
{
if(tree != NULL)
{
tree->root = NULL;
tree->size = 0;
}
return;
}
// TESTS // TESTS
int NATIVE64 avl_tree_test_calculate_height(avl_tree_node *tree) int NATIVE64 avl_tree_node_calculate_height(avl_tree_node *tree)
{ {
if (tree == NULL) if (tree == NULL)
return -1; return -1;
return MAX(avl_tree_test_calculate_height(tree->left), avl_tree_test_calculate_height(tree->right)) + 1; return MAX(avl_tree_node_calculate_height(tree->left), avl_tree_node_calculate_height(tree->right)) + 1;
} }
int NATIVE64 avl_tree_test(avl_tree_node *tree) int NATIVE64 avl_tree_node_test(avl_tree_node *tree, int (*compare)(void*,void*))
{ {
if (tree == NULL) if (tree == NULL)
return 1; return 1;
if (_avl_tree_get_balance_factor(tree) < -1 || _avl_tree_get_balance_factor(tree) > 1 || avl_tree_test_calculate_height(tree) != tree->height) if (_avl_tree_node_get_balance_factor(tree) < -1 || _avl_tree_node_get_balance_factor(tree) > 1 || avl_tree_node_calculate_height(tree) != tree->height)
return 0; return 0;
return avl_tree_test(tree->left) && avl_tree_test(tree->right); if(tree->left != NULL)
{
if(tree->left->parent != tree)
return 0;
}
if(tree->right != NULL)
{
if(tree->right->parent != tree)
return 0;
}
if(compare != NULL)
{
if((tree->right != NULL && compare(tree,tree->right) > 0) || (tree->left != NULL && compare(tree,tree->left) < 0))
return 0;
}
return avl_tree_node_test(tree->left,compare) && avl_tree_node_test(tree->right,compare);
} }

View File

@ -8,7 +8,6 @@ typedef struct __attribute__((packed)) _avl_tree_node
struct _avl_tree_node * right; struct _avl_tree_node * right;
struct _avl_tree_node * parent; struct _avl_tree_node * parent;
int height; int height;
void *data;
} avl_tree_node; } avl_tree_node;
typedef struct __attribute__((packed)) typedef struct __attribute__((packed))
@ -17,29 +16,36 @@ typedef struct __attribute__((packed))
int size; int size;
} avl_tree; } avl_tree;
typedef struct __attribute__((packed)) avl_tree_node* NATIVE64 avl_tree_node_insert(avl_tree_node* root, avl_tree_node* node, int(*compare)(void*,void*));
{
avl_tree_node * current; avl_tree_node* NATIVE64 avl_tree_node_delete(avl_tree_node* root, avl_tree_node* node, int (*compare)(void *, void *));
} avl_tree_iterator;
avl_tree_node* NATIVE64 avl_tree_node_search(avl_tree_node *root, avl_tree_node* node, int(*compare)(void *, void *));
void NATIVE64 avl_tree_node_init(avl_tree_node* it);
avl_tree_node* NATIVE64 avl_tree_node_next(avl_tree_node *it);
avl_tree_node* NATIVE64 avl_tree_node_prev(avl_tree_node *it);
avl_tree_node * NATIVE64 avl_tree_node_smallest(avl_tree_node *root);
avl_tree_node * NATIVE64 avl_tree_node_largest(avl_tree_node *root);
avl_tree_node* avl_tree_search(avl_tree *tree, avl_tree_node* node, int (*compare)(void *, void *));
void NATIVE64 avl_tree_insert(avl_tree *tree, void *data, int (*compare)(void *, void *)); void NATIVE64 avl_tree_insert(avl_tree *tree, void *data, int (*compare)(void *, void *));
void NATIVE64 avl_tree_delete(avl_tree *tree, void *data, int (*compare)(void *, void *)); void NATIVE64 avl_tree_delete(avl_tree *tree, void *data, int (*compare)(void *, void *));
void NATIVE64 avl_tree_free(avl_tree *tree, void (*delete_data)(void *)); void NATIVE64 avl_tree_init(avl_tree* tree);
void NATIVE64 *avl_tree_search(avl_tree *tree, void *data, int(*compare)(void *, void *)); // TESTS
avl_tree * NATIVE64 avl_tree_create(); int NATIVE64 avl_tree_node_calculate_height(avl_tree_node *tree);
avl_tree_iterator* NATIVE64 avl_tree_create_iterator(avl_tree *tree); int NATIVE64 avl_tree_node_test(avl_tree_node *tree, int(*compare)(void *, void *));
void NATIVE64 avl_tree_next(avl_tree_iterator *it);
void NATIVE64 avl_tree_prev(avl_tree_iterator *it);
int NATIVE64 avl_tree_test_calculate_height(avl_tree_node *tree);
int NATIVE64 avl_tree_test(avl_tree_node *tree);
#endif #endif

View File

@ -3,6 +3,8 @@
#include "print.h" #include "print.h"
#include "mm.h" #include "mm.h"
#include "multiboot.h" #include "multiboot.h"
#include "linked_list.h"
uint8_t g_gdt[8*9]; uint8_t g_gdt[8*9];
gdt_ptr_t g_gdt_ptr; gdt_ptr_t g_gdt_ptr;
extern uint64_t text_pos; extern uint64_t text_pos;
@ -26,12 +28,13 @@ void NATIVE64 kmain(multiboot_info_t *multiboot_info)
write_segment_descriptor((void *) &g_gdt[48], 0, 0xFFFFF, SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_DATA_RW); write_segment_descriptor((void *) &g_gdt[48], 0, 0xFFFFF, SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_DATA_RW);
write_segment_descriptor((void *) &g_gdt[56], 0, 0xFFFFF, SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_CODE_X); write_segment_descriptor((void *) &g_gdt[56], 0, 0xFFFFF, SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_CODE_X);
write_segment_descriptor((void *) &g_gdt[64], 0, 0xFFFFF, SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_DATA_RW); write_segment_descriptor((void *) &g_gdt[64], 0, 0xFFFFF, SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | SEG_TYPE_DATA_RW);
g_gdt_ptr.base = (uint64_t)g_gdt; g_gdt_ptr.base = (uint64_t)g_gdt;
g_gdt_ptr.limit = 8*9-1; g_gdt_ptr.limit = 8*9-1;
flush_gdt(&g_gdt_ptr, SEG_SELECTOR(1, 0), SEG_SELECTOR(2, 0)); flush_gdt(&g_gdt_ptr, SEG_SELECTOR(1, 0), SEG_SELECTOR(2, 0));
kprintf("Done.\n\n"); kprintf("Done.\n\n");
linked_list* mm_list = (linked_list*)kmalloc(sizeof(linked_list));
linked_list_init(mm_list);
kprintf("allocated:0x%x\n",(uint64_t)mm_list);
kprintf("*Checking memory information...\n"); kprintf("*Checking memory information...\n");
if(multiboot_info->flags & (1 << 6)) if(multiboot_info->flags & (1 << 6))
{ {
@ -40,7 +43,7 @@ void NATIVE64 kmain(multiboot_info_t *multiboot_info)
kprintf("BaseAddr - Length - Type\n"); kprintf("BaseAddr - Length - Type\n");
uint64_t total_available_mem = 0; uint64_t total_available_mem = 0;
uint64_t total_reserved_mem = 0; uint64_t total_reserved_mem = 0;
for (uint64_t i = 0; i < mem_map_size; i++) for (int i = 0; i < mem_map_size; i++)
{ {
kprintf("0x%X - 0x%X - 0x%x\n", (mem_map + i)->addr, (mem_map + i)->len, (mem_map + i)->type); kprintf("0x%X - 0x%X - 0x%x\n", (mem_map + i)->addr, (mem_map + i)->len, (mem_map + i)->type);
if((mem_map + i)->type == MULTIBOOT_MEMORY_RESERVED) if((mem_map + i)->type == MULTIBOOT_MEMORY_RESERVED)
@ -49,11 +52,21 @@ void NATIVE64 kmain(multiboot_info_t *multiboot_info)
} }
else if ((mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE) else if ((mem_map + i)->type == MULTIBOOT_MEMORY_AVAILABLE)
{ {
phy_mem_info* mm_info = kmalloc(sizeof(phy_mem_info));
linked_list_node_init(&mm_info->node);
mm_info->base = (mem_map+i)->addr;
mm_info->limit = (mem_map+i)->len;
linked_list_add(mm_list,(linked_list_node*)mm_info);
total_available_mem += (mem_map + i)->len; total_available_mem += (mem_map + i)->len;
} }
} }
kprintf("Total available memory: %uB, %uKB, %uMB.\n", total_available_mem, total_available_mem / 1024, total_available_mem / 1024 / 1024); kprintf("Total available memory: %uB, %uKB, %uMB.\n", total_available_mem, total_available_mem / 1024, total_available_mem / 1024 / 1024);
kprintf("Total reserved memory: %uB, %uKB, %uMB.\n\n", total_reserved_mem, total_reserved_mem / 1024, total_reserved_mem / 1024 / 1024); kprintf("Total reserved memory: %uB, %uKB, %uMB.\n\n", total_reserved_mem, total_reserved_mem / 1024, total_reserved_mem / 1024 / 1024);
for(int i = 0; i < mm_list->size; i++)
{
phy_mem_info* mem_info = (phy_mem_info*)linked_list_get(mm_list,i);
kprintf("0x%X - 0x%X", mem_info->base, mem_info->limit);
}
} }
else else
{ {

View File

@ -1 +0,0 @@
#include "int.h"

View File

@ -1,3 +0,0 @@
#ifndef _INT_H_
#define _INT_H_
#endif

View File

@ -1,193 +1,156 @@
#include "mm.h" #include "kdef.h"
#include "linked_list.h" #include "linked_list.h"
//internal void NATIVE64 linked_list_node_init(linked_list_node* node)
linked_list_node* NATIVE64 _linked_list_get_by_index(linked_list_node *head, int index)
{ {
while(1) if(node != NULL)
{ {
if(index <= 0 || head == NULL) node->prev = NULL;
return head; node->next = NULL;
head = head->next;
index--;
}
}
linked_list_node* NATIVE64 _linked_list_get_by_element(linked_list_node *head, void *data, int(*compare)(int *, int *))
{
while(1)
{
if(head == NULL || compare(data,head->data) == 0)
return head;
head = head->next;
}
}
linked_list_node* NATIVE64 _linked_list_create_node()
{
linked_list_node* node = (linked_list_node*)kmalloc(sizeof(linked_list_node));
node->data = NULL;
node->prev = NULL;
node->next = NULL;
return node;
}
void NATIVE64 _linked_list_delete_node(linked_list *list, linked_list_node *node)
{
if(list != NULL && node != NULL)
{
//check if itself is head
if(list->head == node)
{
list->head = node->next;
}
//check if itself is tail
if(list->tail == node)
{
list->tail = node->prev;
}
if (node->prev != NULL)
node->prev->next = node->next;
if (node->next != NULL)
node->next->prev = node->prev;
list->size--;
kfree(node);
} }
return; return;
} }
//interface linked_list_node* NATIVE64 linked_list_node_get(linked_list_node * head, int index)
linked_list* NATIVE64 linked_list_create()
{ {
linked_list* list = (linked_list*)kmalloc(sizeof(linked_list)); if(head == NULL || index < 0)
list->size = 0; return NULL;
list->tail = NULL; while(index--)
list->head = NULL; {
return list; head = head->next;
if(head == NULL)
break;
}
return head;
} }
void NATIVE64 linked_list_free(linked_list* list, void(*delete_data)(void*)) int NATIVE64 linked_list_node_size(linked_list_node* head)
{ {
if(list == NULL) int i = 0;
return;
linked_list_node* head = list->head;
while(head != NULL) while(head != NULL)
{ {
linked_list_node* temp = head; i++;
head = head->next; head = head->next;
if(delete_data != NULL)
delete_data(temp->data);
kfree(temp);
} }
kfree(list); return i;
return;
} }
void NATIVE64 linked_list_insert(linked_list * list, void* data) //returns new head
linked_list_node* NATIVE64 linked_list_node_insert(linked_list_node * head, int index, linked_list_node* node)
{ {
if(list == NULL) if(head == NULL)
return; return node;
linked_list_node* node = _linked_list_create_node(); if(node == NULL || index < 0)
node->data = data; return head;
if(list->tail != NULL) //@ head != NULL
if(index == 0)
{ {
//already elements in the list //insert at head
//guaranteed that list->next == NULL node->prev = NULL;
node->prev = list->tail; node->next = head;
list->tail->next = node; head->prev = node;
list->tail = node; return node;
} }
else else
{ {
//no element case linked_list_node* target = linked_list_node_get(head, index-1);
list->tail = node; if(target == NULL)
list->head = node; return NULL;
node->prev = target;
node->next = target->next;
if(target->next != NULL)
target->next->prev = node;
target->next = node;
return head;
} }
list->size++; }
void NATIVE64 linked_list_node_add(linked_list_node * head, linked_list_node* node)
{
if(head == NULL || node == NULL)
return;
int size = linked_list_node_size(head);
linked_list_node_insert(head,size,node);
return; return;
} }
void NATIVE64 linked_list_insert_at(linked_list * list, int position, void* data) //returns new head
linked_list_node* NATIVE64 linked_list_node_remove(linked_list_node *head, int index)
{ {
if(list != NULL && position >= 0 && position <= list->size) if(head == NULL || index < 0)
return head;
if(index == 0)
{
linked_list_node* next = head->next;
head->next = NULL;
head->prev = NULL;
if(next != NULL)
next->prev = NULL;
return next;
}
else
{
linked_list_node *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;
target->prev = NULL;
target->next = NULL;
return head;
}
}
void NATIVE64 linked_list_init(linked_list* list)
{
if(list != NULL)
{
list->size = 0;
list->head = NULL;
}
return;
}
void NATIVE64 linked_list_add(linked_list * list, linked_list_node* node)
{
if(list != NULL && node != NULL)
{
//@ node != NULL
if (list->head == NULL)
{ {
linked_list_node* target = _linked_list_get_by_index(list->head, position); list->head = node;
if(target == NULL)
{
//tail case
linked_list_insert(list, data);
} }
else else
{ linked_list_node_add(list->head, node);
//head or normal case list->size++;
linked_list_node* node = _linked_list_create_node();
node->data = data;
if (list->head == target) {
list->head = node;
}
node->prev = target->prev;
node->next = target;
if (target->prev != NULL)
target->prev->next = node;
target->prev = node;
list->size++;
}
} }
return; return;
} }
void* NATIVE64 linked_list_get(linked_list * list, int index) void NATIVE64 linked_list_insert(linked_list * list, int index, linked_list_node* node)
{ {
if(list == NULL || list->head == NULL || index < 0 || list->size <= index) if(list != NULL && index > 0 && node != NULL)
{
list->head = linked_list_node_insert(list->head, index, node);
list->size++;
}
return;
}
linked_list_node* NATIVE64 linked_list_get(linked_list * list, int index)
{
if(list == NULL || index < 0 || index >= list->size)
return NULL; return NULL;
linked_list_node* node = _linked_list_get_by_index(list->head, index); return linked_list_node_get(list->head,index);
return node == NULL ? NULL : node->data;
} }
void NATIVE64 linked_list_delete(linked_list * list, void* data, int(*compare)(int*,int*)) void NATIVE64 linked_list_remove(linked_list *list, int index)
{ {
if(list == NULL || list->head == NULL || compare == NULL) if(list != NULL && index >= 0 && index < list->size)
return; {
linked_list_node* node = _linked_list_get_by_element(list->head, data, compare); list->head = linked_list_node_remove(list->head, index);
_linked_list_delete_node(list, node); list->size--;
return; }
}
void NATIVE64 linked_list_delete_at(linked_list * list, int index)
{
if(list == NULL || list->head == NULL || index < 0 || list->size <= index)
return;
linked_list_node* node = _linked_list_get_by_index(list->head, index);
_linked_list_delete_node(list, node);
return;
}
// iterator
linked_list_iterator* NATIVE64 linked_list_create_iterator(linked_list* list)
{
if(list == NULL)
return NULL;
linked_list_iterator* it = (linked_list_iterator*)kmalloc(sizeof(linked_list_iterator));
it->current = list->head;
return it;
}
void NATIVE64 linked_list_delete_iterator(linked_list_iterator* it)
{
kfree(it);
return;
}
void NATIVE64 linked_list_prev(linked_list_iterator* it)
{
it->current = it->current->prev;
return;
}
void NATIVE64 linked_list_next(linked_list_iterator* it)
{
it->current = it->current->next;
return; return;
} }

View File

@ -1,44 +1,40 @@
#ifndef _LINKED_LIST_H_ #ifndef _LINKED_LIST_H_
#define _LINKED_LIST_H_ #define _LINKED_LIST_H_
#include "kdef.h"
typedef struct _linked_list_node typedef struct _linked_list_node
{ {
struct _linked_list_node* prev; struct _linked_list_node* prev;
struct _linked_list_node* next; struct _linked_list_node* next;
void* data;
} linked_list_node; } linked_list_node;
typedef struct typedef struct
{ {
linked_list_node* head; linked_list_node* head;
linked_list_node* tail;
int size; int size;
} linked_list; } linked_list;
typedef struct void NATIVE64 linked_list_init(linked_list* list);
{
linked_list_node* current;
} linked_list_iterator;
linked_list* NATIVE64 linked_list_create(); void NATIVE64 linked_list_add(linked_list * list, linked_list_node* node);
void NATIVE64 linked_list_insert(linked_list * list, void* data); void NATIVE64 linked_list_insert(linked_list * list, int index, linked_list_node* node);
void NATIVE64 linked_list_insert_at(linked_list * list, int position, void* data); linked_list_node* NATIVE64 linked_list_get(linked_list * list, int index);
void* NATIVE64 linked_list_get(linked_list * list, int index); void NATIVE64 linked_list_remove(linked_list *list, int index);
void NATIVE64 linked_list_delete(linked_list * list, void* data, int(*compare)(int*,int*));
void NATIVE64 linked_list_delete_at(linked_list * list, int index);
linked_list_iterator* NATIVE64 linked_list_create_iterator(linked_list* list); int NATIVE64 linked_list_node_size(linked_list_node* head);
void NATIVE64 linked_list_delete_iterator(linked_list_iterator* it); void NATIVE64 linked_list_node_init(linked_list_node* node);
void NATIVE64 linked_list_prev(linked_list_iterator* it); void NATIVE64 linked_list_node_add(linked_list_node * head, linked_list_node* node);
void NATIVE64 linked_list_next(linked_list_iterator* it); linked_list_node* NATIVE64 linked_list_node_insert(linked_list_node * head, int index, linked_list_node* node);
void NATIVE64 linked_list_free(linked_list* list, void(*delete_data)(void*)); linked_list_node* NATIVE64 linked_list_node_get(linked_list_node * head, int index);
linked_list_node* NATIVE64 linked_list_node_remove(linked_list_node *head, int index);
#endif #endif

View File

@ -3,6 +3,7 @@
#include "type.h" #include "type.h"
#include "kdef.h" #include "kdef.h"
#include "linked_list.h"
#define PML4_PRESENT (1ull << 0) #define PML4_PRESENT (1ull << 0)
#define PML4_WRITE (1ull << 1) #define PML4_WRITE (1ull << 1)
#define PML4_USER (1ull << 2) #define PML4_USER (1ull << 2)
@ -68,6 +69,13 @@ typedef struct __attribute__ ((packed))
uint64_t base; uint64_t base;
} gdt_ptr_t; } gdt_ptr_t;
typedef struct __attribute__ ((packed))
{
linked_list_node node;
uint64_t base;
uint64_t limit;
} phy_mem_info;
void*NATIVE64 kmalloc(size_t const size); void*NATIVE64 kmalloc(size_t const size);
void NATIVE64 kfree(void* ptr); void NATIVE64 kfree(void* ptr);