bond/lib/linked_list.c
2018-01-31 14:10:24 -05:00

330 lines
6.5 KiB
C

/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#include "lib/linked_list.h"
static void KABI lbp_init_linked_list_node(linked_list_node_t *node)
{
if (node != NULL)
{
node->next = NULL;
node->prev = NULL;
}
return;
}
static void KABI lbp_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 KABI lbp_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 KABI lbp_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 KABI lb_linked_list_init(linked_list_t *list)
{
if (list != NULL)
{
list->head = NULL;
list->tail = NULL;
}
return;
}
int32_t KABI lb_linked_list_size(linked_list_t *list)
{
if (list == NULL)
return -1;
if (list->head == NULL)
return 0;
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))
{
size++;
}
return size;
}
void KABI lb_linked_list_push_front(linked_list_t *list, linked_list_node_t *node)
{
if (list == NULL || node == NULL)
return;
lbp_init_linked_list_node(node);
lb_linked_list_insert_ref(list, NULL, node);
return;
}
void KABI lb_linked_list_push_back(linked_list_t *list, linked_list_node_t *node)
{
if (list == NULL || node == NULL)
return;
lbp_init_linked_list_node(node);
lb_linked_list_insert_ref(list, list->tail, node);
return;
}
linked_list_node_t *KABI lb_linked_list_pop_front(linked_list_t *list)
{
if (list == NULL)
return NULL;
return lb_linked_list_remove_ref(list, list->head);
}
linked_list_node_t *KABI lb_linked_list_pop_back(linked_list_t *list)
{
if (list == NULL)
return NULL;
return lb_linked_list_remove_ref(list, list->tail);
}
void KABI lb_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;
lbp_init_linked_list_node(node);
if (prev_node == NULL)
{
// if prev_node is NULL, then we are inserting to the head
// linked node with list->head
lbp_prepend_node(list->head, node);
if (list->tail == NULL)
{
// if the list is empty, we assign list->tail to node too
list->tail = node;
}
list->head = node;
}
else
{
// if prev_node is not NULL, we are inserting to the middle or the end
// linked node with the prev_node
lbp_append_node(prev_node, node);
if (node->next == NULL)
{
// if it's the end
list->tail = node;
}
}
}
void KABI lb_linked_list_insert(linked_list_t *list, int32_t index, linked_list_node_t *node)
{
if (list == NULL || index < 0 || node == NULL)
return;
linked_list_node_t *prev_node = lb_linked_list_get(list, index - 1);
lbp_init_linked_list_node(node);
if (prev_node == NULL)
{
if (index == 0)
{
lb_linked_list_insert_ref(list, NULL, node);
}
}
else
{
lb_linked_list_insert_ref(list, prev_node, node);
}
return;
}
linked_list_node_t *KABI lb_linked_list_remove(linked_list_t *list, int32_t index)
{
if (list == NULL || index < 0)
return NULL;
linked_list_node_t *cur_node = lb_linked_list_get(list, index);
if (cur_node == NULL)
return NULL;
return lb_linked_list_remove_ref(list, cur_node);
}
linked_list_node_t *KABI lb_linked_list_remove_ref(linked_list_t *list, linked_list_node_t *node)
{
if (list == NULL || node == NULL)
return NULL;
lbp_unlink_node(node);
if(node->next == NULL)
{
list->tail = node->prev;
}
if(node->prev == NULL)
{
list->head = node->next;
}
lbp_init_linked_list_node(node);
return node;
}
linked_list_node_t *KABI lb_linked_list_get(linked_list_t *list, int32_t 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 *KABI lb_linked_list_next(linked_list_node_t *node)
{
if (node != NULL)
{
node = node->next;
}
return node;
}
linked_list_node_t *KABI lb_linked_list_prev(linked_list_node_t *node)
{
if (node != NULL)
{
node = node->prev;
}
return node;
}
linked_list_node_t *KABI lb_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 *KABI lb_linked_list_last(linked_list_t *list)
{
linked_list_node_t *result = NULL;
if (list != NULL)
{
result = list->tail;
}
return result;
}
int32_t KABI lb_linked_list_search(linked_list_t *list, linked_list_node_t *target,
callback_func_t equals)
{
if(list == NULL || target == NULL)
return -1;
int32_t result = 0;
linked_list_node_t* node = lb_linked_list_first(list);
while(node != NULL)
{
if(equals != NULL)
{
if (equals(node, target))
{
return result;
}
}
else
{
if(target->next == node->next && target->prev == node->prev)
{
return result;
}
}
result++;
node = lb_linked_list_next(node);
}
return -1;
}