#include "GenLinkedList.h"
#define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
#define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
void InitLinkedList( GenLinkedList *pList, size_t linkOffset)
{
pList->Head = NULL;
pList->Tail = NULL;
pList->LinkOffset = linkOffset;
}
void AddToTail( GenLinkedList *pList, void *elem)
{
if ( pList->Tail) {
ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
} else
pList->Head = elem;
ASSIGNLINK( elem, NULL, pList->LinkOffset);
pList->Tail = elem;
}
void AddToHead( GenLinkedList *pList, void *elem)
{
ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
if ( pList->Tail == NULL)
pList->Tail = elem;
pList->Head = elem;
}
int RemoveFromList( GenLinkedList *pList, void *elem)
{
void *iElem, *lastElem;
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
if ( iElem == elem) {
if ( lastElem) { ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
} else { pList->Head = GETLINK( elem, pList->LinkOffset);
}
if ( pList->Tail == elem)
pList->Tail = lastElem ? lastElem : NULL;
ASSIGNLINK( elem, NULL, pList->LinkOffset); return 1;
}
lastElem = iElem;
}
return 0;
}
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
{
void *iElem, *lastElem;
if ( elemInList == NULL || newElem == NULL)
return 0;
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
{
if ( iElem == elemInList)
{
ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
if ( lastElem) {
ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
}
else {
pList->Head = newElem;
}
if ( pList->Tail == elemInList)
pList->Tail = newElem;
return 1;
}
lastElem = iElem;
}
return 0;
}
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
size_t backLinkOffset)
{
pList->Head = NULL;
pList->Tail = NULL;
pList->FwdLinkOffset = fwdLinkOffset;
pList->BackLinkOffset = backLinkOffset;
}
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
{
void *pNext;
pNext = pList->Head;
ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
pList->Head = elem;
if ( pNext) {
ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
} else
pList->Tail = elem;
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
}
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
{
void *pNext, *pPrev;
pNext = GETLINK( elem, pList->FwdLinkOffset);
pPrev = GETLINK( elem, pList->BackLinkOffset);
if ( pPrev)
ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
else
pList->Head = pNext;
if ( pNext)
ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
else
pList->Tail = pPrev;
ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
}
#define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset);
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
{
GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
}
void *GetHeadPtr( GenLinkedOffsetList *pList)
{
return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
}
void *GetTailPtr( GenLinkedOffsetList *pList)
{
return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
}
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
{
size_t nextOffset;
nextOffset = GETOFFSET( elem, pList->LinkOffset);
return nextOffset ? (char*) elem + nextOffset : NULL;
}
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
{
pList->Head = 0;
pList->Tail = 0;
pList->LinkOffset = linkOffset;
}
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
{
if ( pList->Tail) {
AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
} else
pList->Head = (size_t) elem - (size_t) pList;
AssignOffsetLink( elem, NULL, pList->LinkOffset);
pList->Tail = (size_t) elem - (size_t) pList;
}
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
{
AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
if ( pList->Tail == 0)
pList->Tail = (size_t) elem - (size_t) pList;
pList->Head = (size_t) elem - (size_t) pList;
}
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
{
void *iElem, *lastElem;
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elem) {
if ( lastElem) { AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
} else { iElem = GetOffsetLink( pList, elem);
pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
}
if ( GetTailPtr( pList) == elem)
pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
AssignOffsetLink( elem, NULL, pList->LinkOffset); return 1;
}
lastElem = iElem;
}
return 0;
}
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
{
void *iElem, *lastElem;
if ( elemInList == NULL || newElem == NULL)
return 0;
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elemInList)
{
AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
if ( lastElem) {
AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
}
else {
pList->Head = (size_t) newElem - (size_t) pList;
}
if ( GetTailPtr( pList) == elemInList)
pList->Tail = (size_t) newElem - (size_t) pList;
return 1;
}
lastElem = iElem;
}
return 0;
}