/***************************************************************************//**
* @file
* @brief Single Link List
*******************************************************************************
* # License
* Copyright 2019 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_assert.h"
#include "sl_slist.h"
#include
#include
#include
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* Initializes a singly-linked list.
******************************************************************************/
void sl_slist_init(sl_slist_node_t **head)
{
*head = 0;
}
/***************************************************************************//**
* Add given item at beginning of list.
******************************************************************************/
void sl_slist_push(sl_slist_node_t **head,
sl_slist_node_t *item)
{
EFM_ASSERT((item != NULL) && (head != NULL));
item->node = *head;
*head = item;
}
/***************************************************************************//**
* Add item at end of list.
******************************************************************************/
void sl_slist_push_back(sl_slist_node_t **head,
sl_slist_node_t *item)
{
sl_slist_node_t **node_ptr = head;
EFM_ASSERT((item != NULL) && (head != NULL));
while (*node_ptr != NULL) {
node_ptr = &((*node_ptr)->node);
}
item->node = NULL;
*node_ptr = item;
}
/***************************************************************************//**
* Removes and returns first element of list.
******************************************************************************/
sl_slist_node_t *sl_slist_pop(sl_slist_node_t **head)
{
sl_slist_node_t *item;
EFM_ASSERT(head != NULL);
item = *head;
if (item == NULL) {
return (NULL);
}
*head = item->node;
item->node = NULL;
return (item);
}
/***************************************************************************//**
* Insert item after given item.
******************************************************************************/
void sl_slist_insert(sl_slist_node_t *item,
sl_slist_node_t *pos)
{
EFM_ASSERT((item != NULL) && (pos != NULL));
item->node = pos->node;
pos->node = item;
}
/***************************************************************************//**
* Remove item from list.
******************************************************************************/
void sl_slist_remove(sl_slist_node_t **head,
sl_slist_node_t *item)
{
sl_slist_node_t **node_ptr;
EFM_ASSERT((item != NULL) && (head != NULL));
for (node_ptr = head; *node_ptr != NULL; node_ptr = &((*node_ptr)->node)) {
if (*node_ptr == item) {
*node_ptr = item->node;
return;
}
}
EFM_ASSERT(node_ptr != NULL);
}
/***************************************************************************//**
* Sorts list items.
******************************************************************************/
void sl_slist_sort(sl_slist_node_t **head,
bool (*cmp_fnct)(sl_slist_node_t *item_l,
sl_slist_node_t *item_r))
{
bool swapped;
sl_slist_node_t **pp_item_l;
EFM_ASSERT((head != NULL) && (cmp_fnct != NULL));
do {
swapped = false;
pp_item_l = head;
// Loop until end of list is found.
while ((*pp_item_l != NULL) && ((*pp_item_l)->node != NULL)) {
sl_slist_node_t *p_item_r = (*pp_item_l)->node;
bool ordered;
// Call provided compare fnct.
ordered = cmp_fnct(*pp_item_l, p_item_r);
if (ordered == false) {
// If order is not correct, swap items.
sl_slist_node_t *p_tmp = p_item_r->node;
// Swap the two items.
p_item_r->node = *pp_item_l;
(*pp_item_l)->node = p_tmp;
*pp_item_l = p_item_r;
pp_item_l = &(p_item_r->node);
// Indicate a swap has been done.
swapped = true;
} else {
pp_item_l = &((*pp_item_l)->node);
}
}
// Re-loop until no items have been swapped.
} while (swapped == true);
}