/*	List.c - Generic List Handling Routines
*
*******************************************************************************
* Copyright (c) 1996-97 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************
*
*/

#include "DS_RAS.h"
#include "List.h"

#define	ValidHead(p)	((p)->pPrevious == NULL)

void * WINAPI Add(LIST * const pHead, void const * const pDataToAdd, size_t const cbData)
{
	LIST * const pToAdd = malloc(sizeof (LIST) + cbData);
	void * pData = NULL;

	DebugAssert(ValidHead(pHead));

	if (pToAdd)
	{
		pData = ListToData(pToAdd);

		(void) memcpy(pData, pDataToAdd, cbData);

		pToAdd->pPrevious = pHead;
		pToAdd->pNext = pHead->pNext;

		if (pHead->pNext)
			pHead->pNext->pPrevious = pToAdd;
		pHead->pNext = pToAdd;
	}

	return pData;
}

void * WINAPI Find(LIST const * const pHead, void const * const pDataToFind, size_t const cbDataToFind, size_t const cbOffsetDataToFind)
{
	void * pDataFound = NULL;
	LIST * pCurrent;

	DebugAssert(ValidHead(pHead));

	for (pCurrent = pHead->pNext; pCurrent && pDataFound == NULL; pCurrent = pCurrent->pNext)
	{
		BYTE * const pCandidate = ListToData(pCurrent);

		if (memcmp(pDataToFind, pCandidate + cbOffsetDataToFind, cbDataToFind) == 0)
			pDataFound = pCandidate;
	}

	return pDataFound;
}

size_t WINAPI Count(LIST const * const pHead)
{
	size_t cItems = 0;
	LIST * pCurrent;

	DebugAssert(ValidHead(pHead));

	for (pCurrent = pHead->pNext; pCurrent; pCurrent = pCurrent->pNext)
		cItems++;

	return cItems;
}

VOID WINAPI ForEach(LIST const * const pHead, ONEACH_FUNCTION OnEachFunction, void * const pUserData)
{
	LIST * pCurrent;

	DebugAssert(ValidHead(pHead));

	for (pCurrent = pHead->pNext; pCurrent && !OnEachFunction(ListToData(pCurrent), pUserData); pCurrent = pCurrent->pNext);
}

VOID WINAPI ForAll(LIST const * const pHead, ONALL_FUNCTION OnAllFunction, void * const pUserData)
{
	LIST * pCurrent;

	DebugAssert(ValidHead(pHead));

	for (pCurrent = pHead->pNext; pCurrent; pCurrent = pCurrent->pNext)
		OnAllFunction(ListToData(pCurrent), pUserData);
}

VOID WINAPI Delete(LIST * const pHead, void const * const pDataToDelete)
{
	LIST * pToDelete = DataToList(pDataToDelete);

	DebugAssert(ValidHead(pHead));

	pToDelete->pPrevious->pNext = pToDelete->pNext;

	if (pToDelete->pNext)
		pToDelete->pNext->pPrevious = pToDelete->pPrevious;

	free(pToDelete);
}

VOID WINAPI Clear(LIST * const pHead)
{
	LIST * pCurrent;

	DebugAssert(ValidHead(pHead));

	pCurrent = pHead->pNext;
	while (pCurrent)
	{
		LIST * const pNext = pCurrent->pNext;
		free(pCurrent);
		pCurrent = pNext;
	}

	pHead->pNext = NULL;
}
