Files
ANSCORE/MediaClient/bm/linked_list.cpp

633 lines
12 KiB
C++

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