/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "linked_list.h" /************************************************************************************/ HT_API LINKED_LIST * h_list_create(BOOL bNeedMutex) { LINKED_LIST * p_linked_list; p_linked_list = (LINKED_LIST*) malloc(sizeof(LINKED_LIST)); if (p_linked_list == NULL) { return NULL; } p_linked_list->p_first_node = NULL; p_linked_list->p_last_node = NULL; if (bNeedMutex) { p_linked_list->list_semMutex = sys_os_create_mutex(); } else { p_linked_list->list_semMutex = NULL; } return p_linked_list; } /************************************************************************************/ HT_API void h_list_get_ownership(LINKED_LIST * p_linked_list) { if (p_linked_list->list_semMutex) { sys_os_mutex_enter(p_linked_list->list_semMutex); } } HT_API void h_list_giveup_ownership(LINKED_LIST * p_linked_list) { if (p_linked_list->list_semMutex) { sys_os_mutex_leave(p_linked_list->list_semMutex); } } /************************************************************************************/ HT_API void h_list_free_container(LINKED_LIST * p_linked_list) { LINKED_NODE * p_node; LINKED_NODE * p_next_node; if (p_linked_list == NULL) { return; } h_list_get_ownership(p_linked_list); p_node = p_linked_list->p_first_node; while (p_node != NULL) { void * p_free; p_next_node = p_node->p_next; p_free = p_node->p_data; if (p_free != NULL) { free(p_free); } free (p_node); p_node = p_next_node; } h_list_giveup_ownership(p_linked_list); if (p_linked_list->list_semMutex) { sys_os_destroy_sig_mutex(p_linked_list->list_semMutex); } free (p_linked_list); } /************************************************************************************/ HT_API void h_list_free_all_node(LINKED_LIST * p_linked_list) { LINKED_NODE * p_node; LINKED_NODE * p_next_node; if (p_linked_list == NULL) { return; } h_list_get_ownership(p_linked_list); p_node = p_linked_list->p_first_node; while (p_node != NULL) { p_next_node = p_node->p_next; if (p_node->p_data != NULL) { free(p_node->p_data); } free (p_node); p_node = p_next_node; } p_linked_list->p_first_node = NULL; p_linked_list->p_last_node = NULL; h_list_giveup_ownership(p_linked_list); } /************************************************************************************/ HT_API BOOL h_list_add_at_front(LINKED_LIST * p_linked_list, void * p_item) { LINKED_NODE * p_node; LINKED_NODE * p_next_node; if (p_linked_list == NULL) { return FALSE; } if (p_item == NULL) { return FALSE; } p_node = (LINKED_NODE*) malloc(sizeof(LINKED_NODE)); if (p_node == NULL) { return FALSE; } p_node->p_next = NULL; p_node->p_previous = NULL; p_node->p_data = p_item; h_list_get_ownership(p_linked_list); if (p_linked_list->p_first_node == NULL) { p_linked_list->p_first_node = p_node; p_linked_list->p_last_node = p_node; p_node->p_previous = NULL; p_node->p_next = NULL; } else { p_next_node = p_linked_list->p_first_node; p_node->p_next = p_next_node; p_node->p_previous = NULL; p_next_node->p_previous = p_node; p_linked_list->p_first_node = p_node; } h_list_giveup_ownership(p_linked_list); return TRUE; } /************************************************************************************/ HT_API void h_list_remove_from_front(LINKED_LIST * p_linked_list) { LINKED_NODE * p_node_to_remove; if (p_linked_list == NULL) { return; } h_list_get_ownership(p_linked_list); p_node_to_remove = p_linked_list->p_first_node; if (p_node_to_remove == NULL) { h_list_giveup_ownership(p_linked_list); return; } if (p_linked_list->p_first_node == p_linked_list->p_last_node) { p_linked_list->p_first_node = NULL; p_linked_list->p_last_node = NULL; } else { p_linked_list->p_first_node = p_node_to_remove->p_next; p_linked_list->p_first_node->p_previous = NULL; } free(p_node_to_remove); h_list_giveup_ownership(p_linked_list); } HT_API void h_list_remove_from_front_no_lock(LINKED_LIST * p_linked_list) { LINKED_NODE * p_node_to_remove; if (p_linked_list == NULL) { return; } p_node_to_remove = p_linked_list->p_first_node; if (p_node_to_remove == NULL) { return; } if (p_linked_list->p_first_node == p_linked_list->p_last_node) { p_linked_list->p_first_node = NULL; p_linked_list->p_last_node = NULL; } else { p_linked_list->p_first_node = p_node_to_remove->p_next; p_linked_list->p_first_node->p_previous = NULL; } free (p_node_to_remove); } /************************************************************************************/ HT_API BOOL h_list_add_at_back(LINKED_LIST * p_linked_list, void * p_item) { LINKED_NODE * p_node; LINKED_NODE * p_previous_node; if (p_linked_list == NULL) { return FALSE; } if (p_item == NULL) { return FALSE; } p_node = (LINKED_NODE*) malloc(sizeof(LINKED_NODE)); if (p_node == NULL) { return FALSE; } p_node->p_next = NULL; p_node->p_previous = NULL; p_node->p_data = (void*) p_item; h_list_get_ownership(p_linked_list); if (p_linked_list->p_last_node == NULL) { p_linked_list->p_last_node = p_node; p_linked_list->p_first_node = p_node; p_node->p_next = NULL; p_node->p_previous = NULL; } else { p_previous_node = p_linked_list->p_last_node; p_node->p_next = NULL; p_node->p_previous = p_previous_node; p_previous_node->p_next = p_node; p_linked_list->p_last_node = p_node; } h_list_giveup_ownership(p_linked_list); return TRUE; } /************************************************************************************/ HT_API void h_list_remove_from_back(LINKED_LIST * p_linked_list) { LINKED_NODE * p_node_to_remove; if (p_linked_list == NULL) { return; } h_list_get_ownership(p_linked_list); if (p_linked_list->p_last_node == NULL) { h_list_giveup_ownership(p_linked_list); return; } if (p_linked_list->p_first_node == p_linked_list->p_last_node) { p_node_to_remove = p_linked_list->p_first_node; p_linked_list->p_first_node = NULL; p_linked_list->p_last_node = NULL; free(p_node_to_remove); h_list_giveup_ownership(p_linked_list); return; } p_node_to_remove = p_linked_list->p_last_node; p_linked_list->p_last_node = p_node_to_remove->p_previous; p_linked_list->p_last_node->p_next = NULL; free(p_node_to_remove); p_node_to_remove = NULL; h_list_giveup_ownership(p_linked_list); } HT_API BOOL h_list_remove(LINKED_LIST * p_linked_list, LINKED_NODE * p_node) { LINKED_NODE * p_previous_node; LINKED_NODE * p_next_node; if ((p_linked_list == NULL) || (p_node == NULL)) { return FALSE; } p_previous_node = p_node->p_previous; p_next_node = p_node->p_next; if (p_previous_node != NULL) { p_previous_node->p_next = p_next_node; } else { p_linked_list->p_first_node = p_next_node; } if (p_next_node != NULL) { p_next_node->p_previous = p_previous_node; } else { p_linked_list->p_last_node = p_previous_node; } free (p_node); return TRUE; } HT_API BOOL h_list_remove_data(LINKED_LIST * p_linked_list, void * p_data) { LINKED_NODE * p_previous_node; LINKED_NODE * p_next_node; LINKED_NODE * p_node; if ((p_linked_list == NULL) || (p_data == NULL)) { return FALSE; } h_list_get_ownership(p_linked_list); p_node = p_linked_list->p_first_node; while (p_node != NULL) { if (p_data == p_node->p_data) { break; } p_node = p_node->p_next; } if (p_node == NULL) { h_list_giveup_ownership(p_linked_list); return FALSE; } p_previous_node = p_node->p_previous; p_next_node = p_node->p_next; if (p_previous_node != NULL) { p_previous_node->p_next = p_next_node; } else { p_linked_list->p_first_node = p_next_node; } if (p_next_node != NULL) { p_next_node->p_previous = p_previous_node; } else { p_linked_list->p_last_node = p_previous_node; } free(p_node); h_list_giveup_ownership(p_linked_list); return TRUE; } /************************************************************************************/ HT_API uint32 h_list_get_number_of_nodes(LINKED_LIST * p_linked_list) { uint32 number_of_nodes; LINKED_NODE * p_node; if (NULL == p_linked_list) { return 0; } h_list_get_ownership(p_linked_list); p_node = p_linked_list->p_first_node; number_of_nodes = 0; while (p_node != NULL) { ++ number_of_nodes; p_node = p_node->p_next; } h_list_giveup_ownership(p_linked_list); return number_of_nodes; } /************************************************************************************/ HT_API BOOL h_list_insert(LINKED_LIST * p_linked_list, LINKED_NODE * p_pre_node, void *p_item) { if ((p_linked_list == NULL) || (p_item == NULL)) { return FALSE; } if (p_pre_node == NULL) { h_list_add_at_front(p_linked_list, p_item); } else { if (p_pre_node->p_next == NULL) { h_list_add_at_back(p_linked_list, p_item); } else { LINKED_NODE * p_node = (LINKED_NODE *)malloc(sizeof(LINKED_NODE)); if (NULL == p_node) { return FALSE; } h_list_get_ownership(p_linked_list); p_node->p_data = p_item; p_node->p_next = p_pre_node->p_next; p_node->p_previous = p_pre_node; p_pre_node->p_next->p_previous = p_node; p_pre_node->p_next = p_node; h_list_giveup_ownership(p_linked_list); } } return TRUE; } /***********************************************************************/ HT_API LINKED_NODE * h_list_lookup_start(LINKED_LIST * p_linked_list) { if (p_linked_list == NULL) { return NULL; } h_list_get_ownership(p_linked_list); if (p_linked_list->p_first_node) { return p_linked_list->p_first_node; } return NULL; } HT_API LINKED_NODE * h_list_lookup_next(LINKED_LIST * p_linked_list, LINKED_NODE * p_node) { if (p_node == NULL) { return NULL; } return p_node->p_next; } HT_API void h_list_lookup_end(LINKED_LIST * p_linked_list) { if (p_linked_list == NULL) { return; } h_list_giveup_ownership(p_linked_list); } HT_API LINKED_NODE * h_list_lookback_start(LINKED_LIST * p_linked_list) { if (p_linked_list == NULL) { return NULL; } h_list_get_ownership(p_linked_list); if (p_linked_list->p_last_node) { return p_linked_list->p_last_node; } return NULL; } HT_API LINKED_NODE * h_list_lookback_next(LINKED_LIST * p_linked_list, LINKED_NODE * p_node) { if (p_node == NULL) { return NULL; } return p_node->p_previous; } HT_API void h_list_lookback_end(LINKED_LIST * p_linked_list) { if (p_linked_list == NULL) { return; } h_list_giveup_ownership(p_linked_list); } HT_API LINKED_NODE * h_list_get_from_front(LINKED_LIST * p_list) { if (p_list == NULL) { return NULL; } return p_list->p_first_node; } HT_API LINKED_NODE * h_list_get_from_back(LINKED_LIST * p_list) { if (p_list == NULL) { return NULL; } return p_list->p_last_node; } HT_API BOOL h_list_is_empty(LINKED_LIST * p_list) { if (p_list == NULL) { return TRUE; } return (p_list->p_first_node == NULL); }