406 lines
9.7 KiB
C
406 lines
9.7 KiB
C
/**
|
|
****************************************************************************************
|
|
*
|
|
* @file co_list.c
|
|
*
|
|
* @brief List management functions
|
|
*
|
|
* Copyright (C) RivieraWaves 2009-2015
|
|
*
|
|
*
|
|
****************************************************************************************
|
|
*/
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @addtogroup CO_LIST
|
|
* @{
|
|
*****************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
* INCLUDE FILES
|
|
****************************************************************************************
|
|
*/
|
|
|
|
#include <string.h> // for mem* functions
|
|
#include <stdbool.h>
|
|
#include "co_list.h" // common list definitions
|
|
|
|
/*
|
|
* FUNCTION DEFINTIONS
|
|
****************************************************************************************
|
|
*/
|
|
void co_list_init(struct co_list *list)
|
|
{
|
|
list->first = NULL;
|
|
list->last = NULL;
|
|
}
|
|
|
|
void co_list_pool_init(struct co_list *list,
|
|
void *pool,
|
|
size_t elmt_size,
|
|
uint32_t elmt_cnt,
|
|
void *default_value,
|
|
uint8_t list_type)
|
|
{
|
|
uint32_t i;
|
|
|
|
// initialize the free list relative to the pool
|
|
co_list_init(list);
|
|
|
|
// Add each element of the pool to this list, and init them one by one
|
|
for (i = 0; i < elmt_cnt; i++)
|
|
{
|
|
if (default_value)
|
|
{
|
|
memcpy(pool, default_value, elmt_size);
|
|
}
|
|
if((i == (elmt_cnt - 1)) && (list_type != POOL_LINKED_LIST))
|
|
{
|
|
struct co_list_hdr *list_hdr =(struct co_list_hdr *) pool;
|
|
|
|
// check if list is empty
|
|
if (co_list_is_empty(list))
|
|
{
|
|
// list empty => pushed element is also head
|
|
list->first = list_hdr;
|
|
}
|
|
else
|
|
{
|
|
// list not empty => update next of last
|
|
list->last->next = list_hdr;
|
|
}
|
|
|
|
// add element at the end of the list
|
|
list->last = list_hdr;
|
|
list_hdr->next = NULL;
|
|
}
|
|
else
|
|
{
|
|
co_list_push_back(list, (struct co_list_hdr *) pool);
|
|
}
|
|
|
|
// move to the next pool element
|
|
pool = (void *)((uint8_t *)pool + (uint32_t)elmt_size);
|
|
}
|
|
}
|
|
|
|
void co_list_push_back(struct co_list *list,
|
|
struct co_list_hdr *list_hdr)
|
|
{
|
|
// check if list is empty
|
|
if (co_list_is_empty(list))
|
|
{
|
|
// list empty => pushed element is also head
|
|
list->first = list_hdr;
|
|
}
|
|
else
|
|
{
|
|
// list not empty => update next of last
|
|
list->last->next = list_hdr;
|
|
}
|
|
|
|
// add element at the end of the list
|
|
list->last = list_hdr;
|
|
list_hdr->next = NULL;
|
|
}
|
|
|
|
void co_list_push_back_sublist(struct co_list *list, struct co_list_hdr *first_hdr, struct co_list_hdr *last_hdr)
|
|
{
|
|
// check if list is empty
|
|
if (co_list_is_empty(list))
|
|
{
|
|
// list empty => pushed element is also head
|
|
list->first = first_hdr;
|
|
}
|
|
else
|
|
{
|
|
// list not empty => update next of last
|
|
list->last->next = first_hdr;
|
|
}
|
|
|
|
// Update last pointer
|
|
list->last = last_hdr;
|
|
last_hdr->next = NULL;
|
|
}
|
|
|
|
void co_list_push_front(struct co_list *list,
|
|
struct co_list_hdr *list_hdr)
|
|
{
|
|
// check if list is empty
|
|
if (co_list_is_empty(list))
|
|
{
|
|
// list empty => pushed element is also head
|
|
list->last = list_hdr;
|
|
}
|
|
|
|
// add element at the beginning of the list
|
|
list_hdr->next = list->first;
|
|
list->first = list_hdr;
|
|
}
|
|
|
|
struct co_list_hdr *co_list_pop_front(struct co_list *list)
|
|
{
|
|
struct co_list_hdr *element;
|
|
|
|
// check if list is empty
|
|
element = list->first;
|
|
if (element != NULL)
|
|
{
|
|
|
|
// The list isn't empty : extract the first element
|
|
list->first = list->first->next;
|
|
|
|
if(list->first == NULL)
|
|
{
|
|
list->last = list->first;
|
|
}
|
|
}
|
|
return element;
|
|
}
|
|
|
|
struct co_list_hdr *co_list_pop_subfront(struct co_list *list)
|
|
{
|
|
struct co_list_hdr *element;
|
|
|
|
// check if list is empty
|
|
element = list->first;
|
|
if (element != NULL)
|
|
{
|
|
element = list->first->next;
|
|
if(element != NULL){
|
|
// The list isn't empty : extract the first element
|
|
list->first->next = list->first->next->next;
|
|
if(list->first->next == NULL){
|
|
list->last->next = list->first;
|
|
}
|
|
}
|
|
}
|
|
return element;
|
|
}
|
|
|
|
|
|
|
|
bool co_list_extract(struct co_list *list, struct co_list_hdr *list_hdr)
|
|
{
|
|
bool found = false;
|
|
|
|
struct co_list_hdr *prev = NULL;
|
|
struct co_list_hdr *curr = list->first;
|
|
|
|
// Search for the element
|
|
while(curr != NULL)
|
|
{
|
|
// Check element
|
|
if(curr == list_hdr)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
|
|
// Move pointers
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
|
|
if(found)
|
|
{
|
|
// Check if the element is first
|
|
if(prev == NULL)
|
|
{
|
|
// Extract element
|
|
list->first = list_hdr->next;
|
|
}
|
|
else
|
|
{
|
|
// Extract element
|
|
prev->next = list_hdr->next;
|
|
}
|
|
|
|
// Check if the element is last
|
|
if(list_hdr == list->last)
|
|
{
|
|
// Update last pointer
|
|
list->last = prev;
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
void co_list_extract_after(struct co_list *list, struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_rem_hdr)
|
|
{
|
|
// Check if the element is first
|
|
if(elt_ref_hdr == NULL)
|
|
{
|
|
// The list isn't empty : extract the first element
|
|
list->first = list->first->next;
|
|
}
|
|
else
|
|
{
|
|
// Extract element
|
|
elt_ref_hdr->next = elt_to_rem_hdr->next;
|
|
}
|
|
|
|
// Check if the element is last
|
|
if(elt_to_rem_hdr == list->last)
|
|
{
|
|
// Update last pointer
|
|
list->last = elt_ref_hdr;
|
|
}
|
|
}
|
|
|
|
void co_list_extract_sublist(struct co_list *list, struct co_list_hdr *ref_hdr, struct co_list_hdr *last_hdr)
|
|
{
|
|
// Check if the element is first
|
|
if(ref_hdr == NULL)
|
|
{
|
|
// Extract the elements
|
|
list->first = last_hdr->next;
|
|
}
|
|
else
|
|
{
|
|
// Extract the elements
|
|
ref_hdr->next = last_hdr->next;
|
|
}
|
|
|
|
// Check if the element is last
|
|
if(last_hdr == list->last)
|
|
{
|
|
// Reference element becomes last
|
|
list->last = ref_hdr;
|
|
}
|
|
}
|
|
|
|
bool co_list_find(struct co_list *list,
|
|
struct co_list_hdr *list_hdr)
|
|
{
|
|
struct co_list_hdr *tmp_list_hdr;
|
|
|
|
// Go through the list to find the element
|
|
tmp_list_hdr = list->first;
|
|
|
|
while ((tmp_list_hdr != list_hdr) && (tmp_list_hdr != NULL))
|
|
{
|
|
tmp_list_hdr = tmp_list_hdr->next;
|
|
}
|
|
|
|
return (tmp_list_hdr == list_hdr);
|
|
}
|
|
|
|
void co_list_merge(struct co_list *list1,
|
|
struct co_list *list2)
|
|
{
|
|
// just copy list elements
|
|
if(co_list_is_empty(list1))
|
|
{
|
|
list1->first = list2->first;
|
|
list1->last = list2->last;
|
|
}
|
|
// merge lists
|
|
else
|
|
{
|
|
// Append list2 to list1
|
|
list1->last->next = list2->first;
|
|
list1->last = list2->last;
|
|
|
|
}
|
|
|
|
// Empty list2
|
|
list2->first = NULL;
|
|
}
|
|
|
|
void co_list_insert_before(struct co_list *list,
|
|
struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_add_hdr)
|
|
{
|
|
// If no element referenced
|
|
if(elt_ref_hdr == NULL)
|
|
{
|
|
co_list_push_front(list,elt_to_add_hdr);
|
|
}
|
|
else
|
|
{
|
|
struct co_list_hdr *tmp_list_prev_hdr = NULL;
|
|
struct co_list_hdr *tmp_list_curr_hdr;
|
|
|
|
// Go through the list to find the element
|
|
tmp_list_curr_hdr = list->first;
|
|
|
|
while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL))
|
|
{
|
|
// Save previous element
|
|
tmp_list_prev_hdr = tmp_list_curr_hdr;
|
|
// Get the next element of the list
|
|
tmp_list_curr_hdr = tmp_list_curr_hdr->next;
|
|
}
|
|
// If only one element is available
|
|
if(tmp_list_prev_hdr == NULL)
|
|
{
|
|
co_list_push_front(list,elt_to_add_hdr);
|
|
}
|
|
else
|
|
{
|
|
tmp_list_prev_hdr->next = elt_to_add_hdr;
|
|
elt_to_add_hdr->next = tmp_list_curr_hdr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void co_list_insert_after(struct co_list *list,
|
|
struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_add_hdr)
|
|
{
|
|
// If no element referenced
|
|
if(elt_ref_hdr == NULL)
|
|
{
|
|
co_list_push_back(list,elt_to_add_hdr);
|
|
}
|
|
else
|
|
{
|
|
struct co_list_hdr *tmp_list_curr_hdr;
|
|
|
|
// Go through the list to find the element
|
|
tmp_list_curr_hdr = list->first;
|
|
|
|
while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL))
|
|
{
|
|
// Get the next element of the list
|
|
tmp_list_curr_hdr = tmp_list_curr_hdr->next;
|
|
}
|
|
// If only one element is available
|
|
if(tmp_list_curr_hdr == NULL)
|
|
{
|
|
co_list_push_back(list,elt_to_add_hdr);
|
|
}
|
|
else
|
|
{
|
|
// Check if the found element was the last of the list
|
|
if (!tmp_list_curr_hdr->next)
|
|
{
|
|
// Update last pointer
|
|
list->last = elt_to_add_hdr;
|
|
}
|
|
|
|
elt_to_add_hdr->next = tmp_list_curr_hdr->next;
|
|
tmp_list_curr_hdr->next = elt_to_add_hdr;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t co_list_size(struct co_list *list)
|
|
{
|
|
uint16_t count = 0;
|
|
struct co_list_hdr *tmp_list_hdr = list->first;
|
|
|
|
// browse list to count number of elements
|
|
while (tmp_list_hdr != NULL)
|
|
{
|
|
tmp_list_hdr = tmp_list_hdr->next;
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/// @} CO_LIST
|