/* * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and * its subsidiaries and affiliates (collectly called MKSEMI). * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into an MKSEMI * integrated circuit in a product or a software update for such product, * must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of MKSEMI nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * 4. This software, with or without modification, must only be used with a * MKSEMI integrated circuit. * * 5. Any software provided in binary form under this license must not be * reverse engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mk_list.h" void mk_list_init(struct mk_list *list) { list->first = NULL; list->last = NULL; #if (MK_LIST_DEBUG) list->cnt = 0; list->maxcnt = 0; list->mincnt = 0xFFFF; #endif } void mk_list_push_back(struct mk_list *list, struct mk_list_hdr *list_hdr) { // Sanity check ASSERT(list_hdr != NULL, "Invalid list"); // check if list is empty if (mk_list_is_empty(list)) { // list empty => pushed element is also head list->first = list_hdr; } else { // list not empty => update next of last list->last->next = list_hdr; } // add element at the end of the list list->last = list_hdr; list_hdr->next = NULL; #if (MK_LIST_DEBUG) list->cnt++; if (list->maxcnt < list->cnt) { list->maxcnt = list->cnt; } #endif } void mk_list_push_back_sublist(struct mk_list *list, struct mk_list_hdr *first_hdr, struct mk_list_hdr *last_hdr) { // Sanity check ASSERT(first_hdr != NULL, "Invalid list"); ASSERT(last_hdr != NULL, "Invalid list"); // check if list is empty if (mk_list_is_empty(list)) { // list empty => pushed element is also head list->first = first_hdr; } else { // list not empty => update next of last list->last->next = first_hdr; } // Update last pointer list->last = last_hdr; last_hdr->next = NULL; #if (MK_LIST_DEBUG) { struct mk_list_hdr *cursor = first_hdr; // Count the number of extracted elements while (cursor != NULL) { cursor = cursor->next; } list->cnt++; list->maxcnt = (uint16_t)MAX(list->maxcnt, list->cnt); } #endif } void mk_list_push_front(struct mk_list *list, struct mk_list_hdr *list_hdr) { // Sanity check ASSERT(list_hdr != NULL, "Invalid list"); // check if list is empty if (mk_list_is_empty(list)) { // list empty => pushed element is also head list->last = list_hdr; } // add element at the beginning of the list list_hdr->next = list->first; list->first = list_hdr; #if (MK_LIST_DEBUG) list->cnt++; if (list->maxcnt < list->cnt) { list->maxcnt = list->cnt; } #endif } struct mk_list_hdr *mk_list_pop_front(struct mk_list *list) { struct mk_list_hdr *element; // check if list is empty element = list->first; if (element != NULL) { // The list isn't empty : extract the first element list->first = list->first->next; if (list->first == NULL) { list->last = list->first; } #if (MK_LIST_DEBUG) list->cnt--; if (list->mincnt > list->cnt) { list->mincnt = list->cnt; } #endif } return element; } bool mk_list_extract(struct mk_list *list, struct mk_list_hdr *list_hdr) { bool found = false; // sanity check ASSERT(list != NULL, "Invalid list"); struct mk_list_hdr *prev = NULL; struct mk_list_hdr *curr = list->first; // Search for the element while (curr != NULL) { // Check element if (curr == list_hdr) { found = true; break; } // Move pointers prev = curr; ASSERT(list->first != curr->next, "Move pointers error %x %x", ((uint32_t)curr) >> 16, ((uint32_t)curr) & 0xFFFF); ASSERT(curr != curr->next, "Move pointers error %x %x", ((uint32_t)curr) >> 16, ((uint32_t)curr) & 0xFFFF); curr = curr->next; } if (found) { // Check if the element is first if (prev == NULL) { // Extract element list->first = list_hdr->next; } else { // Extract element prev->next = list_hdr->next; } // Check if the element is last if (list_hdr == list->last) { // Update last pointer list->last = prev; } #if (MK_LIST_DEBUG) // Reference element extracted list->cnt--; if (list->mincnt > list->cnt) { list->mincnt = list->cnt; } #endif } return found; } void mk_list_extract_after(struct mk_list *list, struct mk_list_hdr *elt_ref_hdr, struct mk_list_hdr *elt_to_rem_hdr) { // sanity check ASSERT(list != NULL, "Invalid list"); ASSERT(elt_to_rem_hdr != NULL, "Invalid list"); // Check if the element is first if (elt_ref_hdr == NULL) { ASSERT(elt_to_rem_hdr == list->first, "Invalid list"); // The list isn't empty : extract the first element list->first = list->first->next; } else { ASSERT(elt_to_rem_hdr == elt_ref_hdr->next, "Invalid list"); // Extract element elt_ref_hdr->next = elt_to_rem_hdr->next; } // Check if the element is last if (elt_to_rem_hdr == list->last) { // Update last pointer list->last = elt_ref_hdr; } #if (MK_LIST_DEBUG) // Reference element extracted list->cnt--; if (list->mincnt > list->cnt) { list->mincnt = list->cnt; } #endif } void mk_list_extract_sublist(struct mk_list *list, struct mk_list_hdr *ref_hdr, struct mk_list_hdr *last_hdr) { // sanity check ASSERT(list != NULL, "Invalid list"); ASSERT(last_hdr != NULL, "Invalid list"); // Check if the element is first if (ref_hdr == NULL) { // Extract the elements list->first = last_hdr->next; } else { // Extract the elements ref_hdr->next = last_hdr->next; } // Check if the element is last if (last_hdr == list->last) { // Reference element becomes last list->last = ref_hdr; } } bool mk_list_find(struct mk_list *list, struct mk_list_hdr *list_hdr) { struct mk_list_hdr *tmp_list_hdr; // Go through the list to find the element tmp_list_hdr = list->first; while ((tmp_list_hdr != list_hdr) && (tmp_list_hdr != NULL)) { tmp_list_hdr = tmp_list_hdr->next; } return (tmp_list_hdr == list_hdr); } void mk_list_merge(struct mk_list *list1, struct mk_list *list2) { // Sanity check: list2 is not supposed to be empty ASSERT(!mk_list_is_empty(list2), "Invalid list2"); // just copy list elements if (mk_list_is_empty(list1)) { list1->first = list2->first; list1->last = list2->last; } // merge lists else { // Append list2 to list1 list1->last->next = list2->first; list1->last = list2->last; } // Empty list2 list2->first = NULL; #if (MK_LIST_DEBUG) list1->cnt += list2->cnt; list2->cnt = 0; #endif } void mk_list_insert_before(struct mk_list *list, struct mk_list_hdr *elt_ref_hdr, struct mk_list_hdr *elt_to_add_hdr) { // Sanity check ASSERT(elt_to_add_hdr != NULL, "Invalid list"); // If no element referenced if (elt_ref_hdr == NULL) { mk_list_push_front(list, elt_to_add_hdr); } else { struct mk_list_hdr *tmp_list_prev_hdr = NULL; struct mk_list_hdr *tmp_list_curr_hdr; // Go through the list to find the element tmp_list_curr_hdr = list->first; while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL)) { // Save previous element tmp_list_prev_hdr = tmp_list_curr_hdr; // Get the next element of the list tmp_list_curr_hdr = tmp_list_curr_hdr->next; } // If only one element is available if (tmp_list_prev_hdr == NULL) { mk_list_push_front(list, elt_to_add_hdr); } else { tmp_list_prev_hdr->next = elt_to_add_hdr; elt_to_add_hdr->next = tmp_list_curr_hdr; #if (MK_LIST_DEBUG) list->cnt++; if (list->maxcnt < list->cnt) { list->maxcnt = list->cnt; } #endif } } } void mk_list_insert_after(struct mk_list *list, struct mk_list_hdr *elt_ref_hdr, struct mk_list_hdr *elt_to_add_hdr) { // Sanity check ASSERT(elt_to_add_hdr != NULL, "Invalid list"); // If no element referenced if (elt_ref_hdr == NULL) { mk_list_push_back(list, elt_to_add_hdr); } else { struct mk_list_hdr *tmp_list_curr_hdr; // Go through the list to find the element tmp_list_curr_hdr = list->first; while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL)) { // Get the next element of the list tmp_list_curr_hdr = tmp_list_curr_hdr->next; } // If only one element is available if (tmp_list_curr_hdr == NULL) { mk_list_push_back(list, elt_to_add_hdr); } else { // Check if the found element was the last of the list if (!tmp_list_curr_hdr->next) { // Update last pointer list->last = elt_to_add_hdr; } elt_to_add_hdr->next = tmp_list_curr_hdr->next; tmp_list_curr_hdr->next = elt_to_add_hdr; #if (MK_LIST_DEBUG) list->cnt++; if (list->maxcnt < list->cnt) { list->maxcnt = list->cnt; } #endif } } } uint16_t mk_list_size(struct mk_list *list) { uint16_t count = 0; struct mk_list_hdr *tmp_list_hdr = list->first; // browse list to count number of elements while (tmp_list_hdr != NULL) { tmp_list_hdr = tmp_list_hdr->next; count++; } return count; }