mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 12:42:02 +00:00
259 lines
7.5 KiB
C
259 lines
7.5 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* This module provides sigle linked list near functionality of the
|
|
* the singly_link_list.c module with limitations. The main
|
|
* intention is for low overhead. The followings are the main
|
|
* differences.
|
|
*
|
|
* 1) It does not allocate storage containers for list node or
|
|
* list control structures by the facility. The caller
|
|
* provides the storage from any source as needed.
|
|
*
|
|
* 2) No application call back for node search/find.
|
|
*
|
|
* 3) The use must include the node structure as the first
|
|
* field of the user's data structure to linked. This allows
|
|
* user to retrives the node and at the same time access to
|
|
* the data associated with the node.
|
|
*
|
|
* 4) Lite verion is higher risk because the caller also has
|
|
* the defition of the list and node structures. Use it
|
|
* at your own risk.
|
|
*
|
|
* 5) There is no protection for mutual exclusive access by
|
|
* multiple threads or from interrupt context. The caller
|
|
* has to provide the protection if needed.
|
|
*/
|
|
|
|
#include "cpr_types.h"
|
|
#include "sll_lite.h"
|
|
|
|
/*
|
|
* LIST NODE-1 NODE-2 NODE-3
|
|
* ----------- ---------- ---------- ----------
|
|
* | head |--->| next_p |--->| next_p |--->| next_p |--->NULL
|
|
* | count | | | | | ->| |
|
|
* | | ---------- ---------- | ----------
|
|
* | tail |------------------------------|
|
|
* -----------
|
|
*/
|
|
|
|
/**
|
|
* sll_lite_init initializes list control structure given by the
|
|
* caller.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t
|
|
*
|
|
* @return - SLL_LITE_RET_SUCCESS for success
|
|
* - SLL_LITE_RET_INVALID_ARGS when arguments are
|
|
* invalid.
|
|
*/
|
|
sll_lite_return_e
|
|
sll_lite_init (sll_lite_list_t *list)
|
|
{
|
|
if (list == NULL) {
|
|
return (SLL_LITE_RET_INVALID_ARGS);
|
|
}
|
|
list->count = 0;
|
|
list->head_p = NULL;
|
|
list->tail_p = NULL;
|
|
return (SLL_LITE_RET_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* sll_lite_link_head puts node to the head of the list.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t. The list must be
|
|
* initialized prior.
|
|
* @param[in]node - pointer to the list node structure.
|
|
*
|
|
* @return - SLL_LITE_RET_SUCCESS for success
|
|
* - SLL_LITE_RET_INVALID_ARGS when arguments are
|
|
* invalid.
|
|
*/
|
|
sll_lite_return_e
|
|
sll_lite_link_head (sll_lite_list_t *list, sll_lite_node_t *node)
|
|
{
|
|
if ((list == NULL) || (node == NULL)) {
|
|
return (SLL_LITE_RET_INVALID_ARGS);
|
|
}
|
|
|
|
if (list->head_p == NULL) {
|
|
/* list is empty, this node becomes head */
|
|
list->head_p = node;
|
|
list->tail_p = node;
|
|
node->next_p = NULL;
|
|
} else {
|
|
/* list is not empty, link to the head */
|
|
node->next_p = list->head_p;
|
|
list->head_p = node;
|
|
}
|
|
list->count++;
|
|
|
|
return (SLL_LITE_RET_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* sll_lite_link_tail puts node to the tail of the list.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t. The list must be
|
|
* initialized prior.
|
|
* @param[in]node - pointer to the list node structure.
|
|
*
|
|
* @return - SLL_LITE_RET_SUCCESS for success
|
|
* - SLL_LITE_RET_INVALID_ARGS when arguments are
|
|
* invalid.
|
|
*/
|
|
sll_lite_return_e
|
|
sll_lite_link_tail (sll_lite_list_t *list, sll_lite_node_t *node)
|
|
{
|
|
if ((list == NULL) || (node == NULL)) {
|
|
return (SLL_LITE_RET_INVALID_ARGS);
|
|
}
|
|
|
|
if (list->tail_p == NULL) {
|
|
/* list is empty, this node becomes head */
|
|
list->head_p = node;
|
|
list->tail_p = node;
|
|
} else {
|
|
/* list is not empty, link to the tail */
|
|
list->tail_p->next_p = node;
|
|
list->tail_p = node;
|
|
}
|
|
node->next_p = NULL;
|
|
list->count++;
|
|
|
|
return (SLL_LITE_RET_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* sll_lite_unlink_head removes head node from the head of the list and
|
|
* returns it to the caller.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t. The list must be
|
|
* initialized prior.
|
|
*
|
|
* @return Pointer to the head node if one exists otherwise
|
|
* return NULL.
|
|
*/
|
|
sll_lite_node_t *
|
|
sll_lite_unlink_head (sll_lite_list_t *list)
|
|
{
|
|
sll_lite_node_t *node_p = NULL;
|
|
|
|
if (list == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
if (list->head_p != NULL) {
|
|
node_p = list->head_p;
|
|
list->head_p = list->head_p->next_p;
|
|
if (list->tail_p == node_p) {
|
|
/* this the only node on the list */
|
|
list->tail_p = list->head_p;
|
|
}
|
|
list->count--;
|
|
node_p->next_p = NULL;
|
|
}
|
|
return (node_p);
|
|
}
|
|
|
|
/**
|
|
* sll_lite_unlink_tail removes tail node from the list and
|
|
* returns it to the caller.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t. The list must be
|
|
* initialized prior.
|
|
*
|
|
* @return Pointer to the tail node if one exists otherwise
|
|
* return NULL.
|
|
*/
|
|
sll_lite_node_t *
|
|
sll_lite_unlink_tail (sll_lite_list_t *list)
|
|
{
|
|
sll_lite_node_t *node_p;
|
|
|
|
if ((list == NULL) || (list->tail_p == NULL)) {
|
|
return (NULL);
|
|
}
|
|
|
|
/* take the node at the tail and then remove it from the list */
|
|
node_p = list->tail_p;
|
|
if (sll_lite_remove(list, node_p) != SLL_LITE_RET_SUCCESS) {
|
|
/* some thing is wrong */
|
|
return (NULL);
|
|
}
|
|
return (node_p);
|
|
}
|
|
|
|
/**
|
|
* sll_lite_remove removes the given node from the list.
|
|
*
|
|
* @param[in]list - pointer to the list control structure
|
|
* sll_lite_list_t. The list must be
|
|
* initialized prior.
|
|
* @param[in]node - pointer to the list node structure to be
|
|
* removed.
|
|
*
|
|
* @return - SLL_LITE_RET_SUCCESS for success
|
|
* - SLL_LITE_RET_INVALID_ARGS when arguments are
|
|
* invalid.
|
|
* - SLL_LITE_RET_NODE_NOT_FOUND when the node
|
|
* to remove is not found.
|
|
*/
|
|
sll_lite_return_e
|
|
sll_lite_remove (sll_lite_list_t *list, sll_lite_node_t *node)
|
|
{
|
|
sll_lite_node_t *this_p, *prev_p;
|
|
|
|
if ((list == NULL) || (node == NULL)) {
|
|
return (SLL_LITE_RET_INVALID_ARGS);
|
|
}
|
|
|
|
prev_p = NULL;
|
|
this_p = list->head_p; /* starting from the head */
|
|
|
|
/*
|
|
* Find the node on the list and then remove it from
|
|
* the list.
|
|
*/
|
|
while (this_p != NULL) {
|
|
if (this_p == node) {
|
|
break;
|
|
}
|
|
prev_p = this_p;
|
|
this_p = this_p->next_p;
|
|
}
|
|
|
|
if (this_p != NULL) {
|
|
/* found the element */
|
|
if (prev_p == NULL) {
|
|
/* the node to remove is the head */
|
|
list->head_p = list->head_p->next_p;
|
|
if (list->tail_p == this_p) {
|
|
/* this the only node on the list */
|
|
list->tail_p = list->head_p;
|
|
}
|
|
} else {
|
|
/* the element is in the middle of the chain */
|
|
prev_p->next_p = this_p->next_p;
|
|
if (list->tail_p == this_p) {
|
|
/* the node to remove is the last node */
|
|
list->tail_p = prev_p;
|
|
}
|
|
}
|
|
list->count--;
|
|
node->next_p = NULL;
|
|
return (SLL_LITE_RET_SUCCESS);
|
|
}
|
|
return (SLL_LITE_RET_NODE_NOT_FOUND);
|
|
}
|