blob: 86b0727e60f71f78de996106d57e7ee5f696e9f7 [file] [log] [blame]
/* list.c
*
* This Module implements the List API
*/
/*****************************************************************************
* Copyright (c) 2012-2020 by Rambus, Inc. and/or its subsidiaries.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
/*----------------------------------------------------------------------------
* This module implements (provides) the following interface(s):
*/
// List API
#include "list.h"
/*----------------------------------------------------------------------------
* This module uses (requires) the following interface(s):
*/
// Default configuration
#include "c_list.h"
// Driver Framework Basic Definitions API
#include "basic_defs.h"
/*----------------------------------------------------------------------------
* Definitions and macros
*/
typedef struct
{
// List head
List_Element_t * Head_p;
// List tail
List_Element_t * Tail_p;
// Number of elements in the list
unsigned int ElementCount;
} List_t;
/*----------------------------------------------------------------------------
* Local variables
*/
// Statically allocated list instances. This will be deprecated in future.
static List_t List [LIST_MAX_NOF_INSTANCES];
/*----------------------------------------------------------------------------
* List_Init
*
*/
List_Status_t
List_Init(
const unsigned int ListID,
void * const ListInstance_p)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Initialize the list instance
{
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
List_p->ElementCount = 0;
List_p->Head_p = NULL;
List_p->Tail_p = NULL;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_Uninit
*
*/
List_Status_t
List_Uninit(
const unsigned int ListID,
void * const ListInstance_p)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Un-initialize the list instance
{
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
List_p->ElementCount = 0;
List_p->Head_p = NULL;
List_p->Tail_p = NULL;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_AddToHead
*
*/
List_Status_t
List_AddToHead(
const unsigned int ListID,
void * const ListInstance_p,
List_Element_t * const Element_p)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Element_p == NULL)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Add the element at the list head
{
List_Element_t * TempElement_p;
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
TempElement_p = List_p->Head_p;
List_p->Head_p = Element_p;
// Previous element in the list, this is a head
Element_p->Internal[0] = NULL;
// Next element in the list
Element_p->Internal[1] = TempElement_p;
// Check if this is the first element
if (List_p->ElementCount == 0)
List_p->Tail_p = List_p->Head_p;
else
// Link the old head to the new head
TempElement_p->Internal[0] = Element_p;
List_p->ElementCount++;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_RemoveFromTail
*
*/
List_Status_t
List_RemoveFromTail(
const unsigned int ListID,
void * const ListInstance_p,
List_Element_t ** const Element_pp)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Element_pp == NULL)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Remove the element from the list tail
{
List_Element_t * TempElement_p;
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
#ifdef LIST_STRICT_ARGS
if (List_p->ElementCount == 0)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Get the previous for the tail element in the list
TempElement_p = (List_Element_t*)List_p->Tail_p->Internal[0];
List_p->Tail_p->Internal[0] = NULL;
List_p->Tail_p->Internal[1] = NULL;
*Element_pp = List_p->Tail_p;
// Set the new tail
List_p->Tail_p = TempElement_p;
// Check if this is the last element
if (List_p->ElementCount == 1)
List_p->Head_p = NULL;
else
// New tail must have no next element
List_p->Tail_p->Internal[1] = NULL;
List_p->ElementCount--;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_RemoveAnywhere
*/
List_Status_t
List_RemoveAnywhere(
const unsigned int ListID,
void * const ListInstance_p,
List_Element_t * const Element_p)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Element_p == NULL)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Remove the element from the list tail
{
List_Element_t * PrevElement_p, * NextElement_p;
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
#ifdef LIST_STRICT_ARGS
if (List_p->ElementCount == 0)
return LIST_ERROR_BAD_ARGUMENT;
// Check element belongs to this list
{
unsigned int i;
List_Element_t * TempElement_p = List_p->Head_p;
for (i = 0; i < List_p->ElementCount; i++)
{
List_Element_t * p;
if (TempElement_p == Element_p)
break; // Found
p = TempElement_p->Internal[1];
if (p)
TempElement_p = p; // not end of list yet
else
return LIST_ERROR_BAD_ARGUMENT; // Not found
}
if (TempElement_p != Element_p)
return LIST_ERROR_BAD_ARGUMENT; // Not found
}
#endif // LIST_STRICT_ARGS
PrevElement_p = Element_p->Internal[0];
NextElement_p = Element_p->Internal[1];
Element_p->Internal[0] = NULL;
Element_p->Internal[1] = NULL;
if (PrevElement_p)
PrevElement_p->Internal[1] = NextElement_p;
else
List_p->Head_p = NextElement_p;
if (NextElement_p)
NextElement_p->Internal[0] = PrevElement_p;
else
List_p->Tail_p = PrevElement_p;
List_p->ElementCount--;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_GetListElementCount
*
*/
List_Status_t
List_GetListElementCount(
const unsigned int ListID,
void * const ListInstance_p,
unsigned int * const Count_p)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Count_p == NULL)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
{
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
*Count_p = List_p->ElementCount;
}
return LIST_STATUS_OK;
}
#ifdef LIST_FULL_API
/*----------------------------------------------------------------------------
* List_RemoveFromHead
*
*/
List_Status_t
List_RemoveFromHead(
const unsigned int ListID,
void * const ListInstance_p,
List_Element_t ** const Element_pp)
{
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Element_pp == NULL)
return LIST_ERROR_BAD_ARGUMENT;
if (List_p->ElementCount == 0)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Remove the element from the list head
{
List_Element_t * TempElement_p;
// Get the next for the head element in the list
TempElement_p = (List_Element_t*)List_p->Head_p->Internal[1];
List_p->Head_p->Internal[0] = NULL;
List_p->Head_p->Internal[1] = NULL;
*Element_pp = List_p->Head_p;
List_p->Head_p = TempElement_p;
// Check if this is the last element
if (List_p->ElementCount == 1)
List_p->Tail_p = NULL;
else
List_p->Head_p->Internal[0] = NULL;
List_p->ElementCount--;
}
return LIST_STATUS_OK;
}
/*----------------------------------------------------------------------------
* List_GetHead
*/
List_Status_t
List_GetHead(
const unsigned int ListID,
void * const ListInstance_p,
const List_Element_t ** const Element_pp)
{
#ifdef LIST_STRICT_ARGS
if (ListID >= LIST_MAX_NOF_INSTANCES)
return LIST_ERROR_BAD_ARGUMENT;
if (Element_pp == NULL)
return LIST_ERROR_BAD_ARGUMENT;
#endif // LIST_STRICT_ARGS
// Get the list head
{
List_t * List_p;
if (ListInstance_p)
List_p = (List_t*)ListInstance_p;
else
List_p = &List[ListID];
*Element_pp = List_p->Head_p;
}
return LIST_STATUS_OK;
}
#endif // LIST_FULL_API
/*----------------------------------------------------------------------------
* List_GetInstanceByteCount
*
* Gets the memory size of the list instance (in bytes) excluding the list
* elements memory size. This list memory size can be used to allocate a list
* instance and pass a pointer to it subsequently to the List_*() functions.
*
* This function is re-entrant and can be called any time.
*
* Return Values
* Size of the list administration memory in bytes.
*/
unsigned int
List_GetInstanceByteCount(void)
{
return sizeof(List_t);
}
/* end of file list.c */