| /* |
| * Copyright 2018-2019 NXP |
| * All rights reserved. |
| * |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| /*! ********************************************************************************* |
| ************************************************************************************* |
| * Include |
| ************************************************************************************* |
| ********************************************************************************** */ |
| #include "generic_list.h" |
| |
| static list_status_t LIST_Error_Check(list_handle_t list, list_element_handle_t newElement) |
| { |
| list_status_t listStatus = kLIST_Ok; |
| list_element_handle_t element = list->head; |
| |
| if ((list->max != 0U) && (list->max == list->size)) |
| { |
| listStatus = kLIST_Full; /*List is full*/ |
| } |
| else |
| { |
| while (element != NULL) /*Scan list*/ |
| { |
| /* Determine if element is duplicated */ |
| if (element == newElement) |
| { |
| listStatus = kLIST_DuplicateError; |
| break; |
| } |
| element = element->next; |
| } |
| } |
| |
| return listStatus; |
| } |
| |
| /*! ********************************************************************************* |
| ************************************************************************************* |
| * Public functions |
| ************************************************************************************* |
| ********************************************************************************** */ |
| /*! ********************************************************************************* |
| * \brief Initialises the list descriptor. |
| * |
| * \param[in] list - LIST_ handle to init. |
| * max - Maximum number of elements in list. 0 for unlimited. |
| * |
| * \return void. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| void LIST_Init(list_handle_t list, uint32_t max) |
| { |
| list->head = NULL; |
| list->tail = NULL; |
| list->max = (uint16_t)max; |
| list->size = 0; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets the list that contains the given element. |
| * |
| * \param[in] element - Handle of the element. |
| * |
| * \return NULL if element is orphan. |
| * Handle of the list the element is inserted into. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_handle_t LIST_GetList(list_element_handle_t element) |
| { |
| return element->list; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Links element to the tail of the list. |
| * |
| * \param[in] list - ID of list to insert into. |
| * element - element to add |
| * |
| * \return kLIST_Full if list is full. |
| * kLIST_Ok if insertion was successful. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element) |
| { |
| uint32_t regPrimask = DisableGlobalIRQ(); |
| list_status_t listStatus = kLIST_Ok; |
| |
| listStatus = LIST_Error_Check(list, element); |
| if (listStatus == kLIST_Ok) /* Avoiding list status error */ |
| { |
| if (list->size == 0U) |
| { |
| list->head = element; |
| } |
| else |
| { |
| list->tail->next = element; |
| } |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| #else |
| element->prev = list->tail; |
| #endif |
| element->list = list; |
| element->next = NULL; |
| list->tail = element; |
| list->size++; |
| } |
| |
| EnableGlobalIRQ(regPrimask); |
| return listStatus; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Links element to the head of the list. |
| * |
| * \param[in] list - ID of list to insert into. |
| * element - element to add |
| * |
| * \return kLIST_Full if list is full. |
| * kLIST_Ok if insertion was successful. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element) |
| { |
| uint32_t regPrimask = DisableGlobalIRQ(); |
| list_status_t listStatus = kLIST_Ok; |
| |
| listStatus = LIST_Error_Check(list, element); |
| if (listStatus == kLIST_Ok) /* Avoiding list status error */ |
| { |
| /* Links element to the head of the list */ |
| if (list->size == 0U) |
| { |
| list->tail = element; |
| } |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| #else |
| else |
| { |
| list->head->prev = element; |
| } |
| element->prev = NULL; |
| #endif |
| element->list = list; |
| element->next = list->head; |
| list->head = element; |
| list->size++; |
| } |
| |
| EnableGlobalIRQ(regPrimask); |
| return listStatus; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Unlinks element from the head of the list. |
| * |
| * \param[in] list - ID of list to remove from. |
| * |
| * \return NULL if list is empty. |
| * ID of removed element(pointer) if removal was successful. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_element_handle_t LIST_RemoveHead(list_handle_t list) |
| { |
| list_element_handle_t element; |
| |
| uint32_t regPrimask = DisableGlobalIRQ(); |
| |
| if ((NULL == list) || (list->size == 0U)) |
| { |
| element = NULL; /*LIST_ is empty*/ |
| } |
| else |
| { |
| element = list->head; |
| list->size--; |
| if (list->size == 0U) |
| { |
| list->tail = NULL; |
| } |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| #else |
| else |
| { |
| element->next->prev = NULL; |
| } |
| #endif |
| element->list = NULL; |
| list->head = element->next; /*Is NULL if element is head*/ |
| } |
| |
| EnableGlobalIRQ(regPrimask); |
| return element; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets head element ID. |
| * |
| * \param[in] list - ID of list. |
| * |
| * \return NULL if list is empty. |
| * ID of head element if list is not empty. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_element_handle_t LIST_GetHead(list_handle_t list) |
| { |
| return list->head; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets next element ID. |
| * |
| * \param[in] element - ID of the element. |
| * |
| * \return NULL if element is tail. |
| * ID of next element if exists. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_element_handle_t LIST_GetNext(list_element_handle_t element) |
| { |
| return element->next; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets previous element ID. |
| * |
| * \param[in] element - ID of the element. |
| * |
| * \return NULL if element is head. |
| * ID of previous element if exists. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_element_handle_t LIST_GetPrev(list_element_handle_t element) |
| { |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| return NULL; |
| #else |
| return element->prev; |
| #endif |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Unlinks an element from its list. |
| * |
| * \param[in] element - ID of the element to remove. |
| * |
| * \return kLIST_OrphanElement if element is not part of any list. |
| * kLIST_Ok if removal was successful. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_status_t LIST_RemoveElement(list_element_handle_t element) |
| { |
| list_status_t listStatus = kLIST_Ok; |
| uint32_t regPrimask = DisableGlobalIRQ(); |
| |
| if (element->list == NULL) |
| { |
| listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ |
| } |
| else |
| { |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| list_element_handle_t element_list = element->list->head; |
| while (element_list) |
| { |
| if (element->list->head == element) |
| { |
| element->list->head = element_list->next; |
| break; |
| } |
| if (element_list->next == element) |
| { |
| element_list->next = element->next; |
| break; |
| } |
| element_list = element_list->next; |
| } |
| #else |
| if (element->prev == NULL) /*Element is head or solo*/ |
| { |
| element->list->head = element->next; /*is null if solo*/ |
| } |
| if (element->next == NULL) /*Element is tail or solo*/ |
| { |
| element->list->tail = element->prev; /*is null if solo*/ |
| } |
| if (element->prev != NULL) /*Element is not head*/ |
| { |
| element->prev->next = element->next; |
| } |
| if (element->next != NULL) /*Element is not tail*/ |
| { |
| element->next->prev = element->prev; |
| } |
| #endif |
| element->list->size--; |
| element->list = NULL; |
| } |
| |
| EnableGlobalIRQ(regPrimask); |
| return listStatus; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Links an element in the previous position relative to a given member |
| * of a list. |
| * |
| * \param[in] element - ID of a member of a list. |
| * newElement - new element to insert before the given member. |
| * |
| * \return kLIST_OrphanElement if element is not part of any list. |
| * kLIST_Full if list is full. |
| * kLIST_Ok if insertion was successful. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement) |
| { |
| list_status_t listStatus = kLIST_Ok; |
| uint32_t regPrimask = DisableGlobalIRQ(); |
| |
| if (element->list == NULL) |
| { |
| listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ |
| } |
| else |
| { |
| listStatus = LIST_Error_Check(element->list, newElement); |
| if (listStatus == kLIST_Ok) |
| { |
| #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
| list_element_handle_t element_list = element->list->head; |
| while (element_list) |
| { |
| if ((element_list->next == element) || (element_list == element)) |
| { |
| if (element_list == element) |
| { |
| element->list->head = newElement; |
| } |
| else |
| { |
| element_list->next = newElement; |
| } |
| newElement->list = element->list; |
| newElement->next = element; |
| element->list->size++; |
| break; |
| } |
| element_list = element_list->next; |
| } |
| |
| #else |
| if (element->prev == NULL) /*Element is list head*/ |
| { |
| element->list->head = newElement; |
| } |
| else |
| { |
| element->prev->next = newElement; |
| } |
| newElement->list = element->list; |
| element->list->size++; |
| newElement->next = element; |
| newElement->prev = element->prev; |
| element->prev = newElement; |
| #endif |
| } |
| } |
| |
| EnableGlobalIRQ(regPrimask); |
| return listStatus; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets the current size of a list. |
| * |
| * \param[in] list - ID of the list. |
| * |
| * \return Current size of the list. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| uint32_t LIST_GetSize(list_handle_t list) |
| { |
| return list->size; |
| } |
| |
| /*! ********************************************************************************* |
| * \brief Gets the number of free places in the list. |
| * |
| * \param[in] list - ID of the list. |
| * |
| * \return Available size of the list. |
| * |
| * \pre |
| * |
| * \post |
| * |
| * \remarks |
| * |
| ********************************************************************************** */ |
| uint32_t LIST_GetAvailableSize(list_handle_t list) |
| { |
| return ((uint32_t)list->max - (uint32_t)list->size); /*Gets the number of free places in the list*/ |
| } |