mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-15 06:28:14 +08:00
352 lines
8.3 KiB
C
352 lines
8.3 KiB
C
/**
|
|
******************************************************************************
|
|
* @file LinkListUtils.c
|
|
* @author William Xu
|
|
* @version V1.0.0
|
|
* @date 12-Jan-2015
|
|
* @brief This file contains function called by link list operation
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
|
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
|
* TIME. AS A RESULT, MXCHIP Inc. SHALL NOT BE HELD LIABLE FOR ANY
|
|
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
|
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
|
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
|
*
|
|
* <h2><center>© COPYRIGHT 2015 MXCHIP Inc.</center></h2>
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "LinkListUtils.h"
|
|
#include "debug.h"
|
|
|
|
OSStatus linked_list_init( linked_list_t* list )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
require_action( list, exit, err = kParamErr);
|
|
memset( list, 0, sizeof( *list ) );
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_deinit( linked_list_t* list )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
linked_list_node_t* current;
|
|
|
|
require_action( list, exit, err = kParamErr);
|
|
|
|
/* Traverse through all nodes and detach them */
|
|
current = list->front;
|
|
|
|
while ( current != NULL )
|
|
{
|
|
linked_list_node_t* next = current->next;
|
|
|
|
/* Detach node from the list */
|
|
current->prev = NULL;
|
|
current->next = NULL;
|
|
|
|
/* Move to the next node */
|
|
current = next;
|
|
}
|
|
|
|
memset( list, 0, sizeof( *list ) );
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_get_count( linked_list_t* list, uint32_t* count )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list, exit, err = kParamErr);
|
|
|
|
*count = list->count;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_set_node_data( linked_list_node_t* node, const void* data )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( node, exit, err = kParamErr);
|
|
|
|
node->data = (void*)data;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_get_front_node( linked_list_t* list, linked_list_node_t** front_node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list, exit, err = kParamErr);
|
|
|
|
*front_node = NULL;
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
*front_node = list->front;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_get_rear_node( linked_list_t* list, linked_list_node_t** rear_node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list, exit, err = kParamErr);
|
|
|
|
*rear_node = NULL;
|
|
require_action( list->count, exit, err = kNotFoundErr);
|
|
|
|
*rear_node = list->rear;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_find_node( linked_list_t* list, linked_list_compare_callback_t callback, void* user_data, linked_list_node_t** node_found )
|
|
{
|
|
OSStatus err = kNotFoundErr;
|
|
linked_list_node_t* current;
|
|
|
|
require_action( list && callback && node_found, exit, err = kParamErr);
|
|
|
|
require_action_quiet(list->count, exit, err = kNotFoundErr);
|
|
|
|
current = list->front;
|
|
|
|
while ( current != NULL )
|
|
{
|
|
if ( callback( current, user_data ) )
|
|
{
|
|
*node_found = current;
|
|
err = kNoErr;
|
|
goto exit;
|
|
}
|
|
|
|
current = current->next;
|
|
}
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_insert_node_at_front( linked_list_t* list, linked_list_node_t* node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && node, exit, err = kParamErr);
|
|
|
|
if ( list->count == 0 )
|
|
{
|
|
list->front = node;
|
|
list->rear = node;
|
|
node->prev = NULL;
|
|
node->next = NULL;
|
|
}
|
|
else
|
|
{
|
|
node->prev = NULL;
|
|
node->next = list->front;
|
|
list->front->prev = node;
|
|
list->front = node;
|
|
}
|
|
|
|
list->count++;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_insert_node_at_rear( linked_list_t* list, linked_list_node_t* node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && node, exit, err = kParamErr);
|
|
|
|
if ( list->count == 0 )
|
|
{
|
|
list->front = node;
|
|
list->rear = node;
|
|
node->prev = NULL;
|
|
node->next = NULL;
|
|
}
|
|
else
|
|
{
|
|
node->next = NULL;
|
|
node->prev = list->rear;
|
|
list->rear->next = node;
|
|
list->rear = node;
|
|
}
|
|
|
|
list->count++;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_insert_node_before( linked_list_t* list, linked_list_node_t* reference_node, linked_list_node_t* node_to_insert )
|
|
{
|
|
/* WARNING: User must make sure that reference_node is in the list */
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && reference_node && node_to_insert, exit, err = kParamErr);
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
if ( reference_node == list->front )
|
|
{
|
|
err = linked_list_insert_node_at_front( list, node_to_insert );
|
|
}
|
|
else
|
|
{
|
|
node_to_insert->prev = reference_node->prev;
|
|
node_to_insert->prev->next = node_to_insert;
|
|
node_to_insert->next = reference_node;
|
|
reference_node->prev = node_to_insert;
|
|
|
|
list->count++;
|
|
}
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_insert_node_after( linked_list_t* list, linked_list_node_t* reference_node, linked_list_node_t* node_to_insert )
|
|
{
|
|
/* WARNING: User must make sure that reference_node is in the list */
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && reference_node && node_to_insert, exit, err = kParamErr);
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
if ( reference_node == list->rear )
|
|
{
|
|
err = linked_list_insert_node_at_rear( list, node_to_insert );
|
|
}
|
|
else
|
|
{
|
|
node_to_insert->prev = reference_node;
|
|
node_to_insert->next = reference_node->next;
|
|
reference_node->next->prev = node_to_insert;
|
|
reference_node->next = node_to_insert;
|
|
|
|
list->count++;
|
|
}
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_remove_node( linked_list_t* list, linked_list_node_t* node )
|
|
{
|
|
/* WARNING: User must make sure that node to remove is in the list */
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && node, exit, err = kParamErr);
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
if ( list->count == 1 )
|
|
{
|
|
list->front = NULL;
|
|
list->rear = NULL;
|
|
}
|
|
else if ( node == list->front )
|
|
{
|
|
linked_list_node_t* removed_node;
|
|
|
|
return linked_list_remove_node_from_front( list, &removed_node );
|
|
}
|
|
else if ( node == list->rear )
|
|
{
|
|
linked_list_node_t* removed_node;
|
|
|
|
return linked_list_remove_node_from_rear( list, &removed_node );
|
|
}
|
|
else
|
|
{
|
|
node->prev->next = node->next;
|
|
node->next->prev = node->prev;
|
|
}
|
|
|
|
/* Make sure that detach node does not point to some arbitrary memory location */
|
|
node->prev = NULL;
|
|
node->next = NULL;
|
|
|
|
list->count--;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_remove_node_from_front( linked_list_t* list, linked_list_node_t** removed_node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && removed_node, exit, err = kParamErr);
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
*removed_node = list->front;
|
|
|
|
if ( list->count == 1 )
|
|
{
|
|
list->front = NULL;
|
|
list->rear = NULL;
|
|
}
|
|
else
|
|
{
|
|
list->front = list->front->next;
|
|
list->front->prev = NULL;
|
|
}
|
|
|
|
/* Make sure node does not point to some arbitrary memory location */
|
|
(*removed_node)->prev = NULL;
|
|
(*removed_node)->next = NULL;
|
|
|
|
list->count--;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
OSStatus linked_list_remove_node_from_rear( linked_list_t* list, linked_list_node_t** removed_node )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
require_action( list && removed_node, exit, err = kParamErr);
|
|
require_action_quiet( list->count, exit, err = kNotFoundErr);
|
|
|
|
*removed_node = list->rear;
|
|
|
|
if ( list->count == 1 )
|
|
{
|
|
list->front = NULL;
|
|
list->rear = NULL;
|
|
}
|
|
else
|
|
{
|
|
list->rear = list->rear->prev;
|
|
list->rear->next = NULL;
|
|
}
|
|
|
|
/* Make sure node does not point to some arbitrary memory location */
|
|
(*removed_node)->prev = NULL;
|
|
(*removed_node)->next = NULL;
|
|
|
|
list->count--;
|
|
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
|