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