Files
freeswitch/libs/sipcc/core/src-common/sll_lite.c
T
2012-12-17 20:15:23 -05:00

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);
}