#include "CContinue.h"
#include <stdlib.h>
#include <string.h>
#pragma GCC visibility push(hidden)
#include <vector>
using std::vector;
#pragma GCC visibility pop
CContinue::CContinue ( DeallocateProc *inProcPtr ) : fMutex("CContinue::fMutex")
{
fHashArrayLength = 32;
fRefNumCount = 0;
fLookupTable = (sDSTableEntry**)calloc(fHashArrayLength, sizeof(sDSTableEntry*));
fDeallocProcPtr = inProcPtr;
}
CContinue::CContinue ( DeallocateProc *inProcPtr, UInt32 inHashArrayLength ) : fMutex("CContinue::fMutex")
{
fHashArrayLength = inHashArrayLength;
fRefNumCount = 0;
fLookupTable = (sDSTableEntry**)calloc(fHashArrayLength, sizeof(sDSTableEntry*));
fDeallocProcPtr = inProcPtr;
}
CContinue::~CContinue ( void )
{
}
SInt32 CContinue::AddItem ( void *inData, UInt32 inRefNum )
{
SInt32 siResult = eDSNoErr;
UInt32 uiSlot = 0;
UInt32 uiTmpRef = 0;
sDSTableEntry *pNewEntry = nil;
sDSTableEntry *pCurrEntry = nil;
fMutex.WaitLock();
uiTmpRef = (UInt32)inData;
pNewEntry = (sDSTableEntry *)::malloc( sizeof( sDSTableEntry ) );
if ( pNewEntry != nil )
{
::memset( pNewEntry, 0, sizeof( sDSTableEntry ) );
pNewEntry->fRefNum = inRefNum;
pNewEntry->fData = inData;
}
else
{
siResult = eMemoryError;
}
if ( siResult == eDSNoErr )
{
uiSlot = uiTmpRef % fHashArrayLength;
if ( fLookupTable[ uiSlot ] == nil )
{
fLookupTable[ uiSlot ] = pNewEntry;
fRefNumCount++;
}
else
{
pCurrEntry = fLookupTable[ uiSlot ];
while ( pCurrEntry != nil )
{
if ( pCurrEntry->fData == inData )
{
siResult = eDSInvalidIndex;
free( pNewEntry );
pNewEntry = nil;
break;
}
pCurrEntry = pCurrEntry->fNext;
}
if ( siResult == eDSNoErr )
{
pCurrEntry = fLookupTable[ uiSlot ];
pNewEntry->fNext = pCurrEntry;
fLookupTable[ uiSlot ] = pNewEntry;
fRefNumCount++;
}
}
}
fMutex.SignalLock();
return( siResult );
}
bool CContinue::VerifyItem ( void *inData )
{
bool bResult = false;
UInt32 uiTmpRef = 0;
UInt32 uiSlot = 0;
sDSTableEntry *pEntry = nil;
fMutex.WaitLock();
uiTmpRef = (UInt32)inData;
uiSlot = uiTmpRef % fHashArrayLength;
pEntry = fLookupTable[ uiSlot ];
while ( pEntry != nil )
{
if ( pEntry->fData == inData )
{
bResult = true;
break;
}
pEntry = pEntry->fNext;
}
fMutex.SignalLock();
return( bResult );
}
SInt32 CContinue::RemoveItem ( void *inData )
{
SInt32 siResult = eDSIndexNotFound;
UInt32 uiTmpRef = 0;
UInt32 uiSlot = 0;
sDSTableEntry *pCurrEntry = nil;
sDSTableEntry *pPrevEntry = nil;
void *pData = nil;
if ( inData == NULL )
return eDSNoErr;
fMutex.WaitLock();
uiTmpRef = (UInt32)inData;
uiSlot = uiTmpRef % fHashArrayLength;
pCurrEntry = fLookupTable[ uiSlot ];
pPrevEntry = fLookupTable[ uiSlot ];
while ( pCurrEntry != nil )
{
if ( pCurrEntry->fData == inData )
{
if ( pCurrEntry == pPrevEntry )
{
fLookupTable[ uiSlot ] = pCurrEntry->fNext;
}
else
{
pPrevEntry->fNext = pCurrEntry->fNext;
}
if ( (fDeallocProcPtr != nil) && (pCurrEntry->fData != nil) )
{
pData = pCurrEntry->fData;
}
free( pCurrEntry );
pCurrEntry = nil;
fRefNumCount--;
siResult = eDSNoErr;
break;
}
if ( pCurrEntry != nil )
{
pPrevEntry = pCurrEntry;
pCurrEntry = pPrevEntry->fNext;
}
}
fMutex.SignalLock();
if ( pData != nil )
{
(fDeallocProcPtr)( pData );
}
return( siResult );
}
SInt32 CContinue::RemoveItems ( UInt32 inRefNum )
{
bool bGetNext = true;
UInt32 i = 0;
SInt32 siResult = eDSIndexNotFound;
sDSTableEntry *pCurrEntry = nil;
sDSTableEntry *pPrevEntry = nil;
sDSTableEntry *pDeadEntry = nil;
vector<void*> entryDataPendingDelete;
fMutex.WaitLock();
for ( i = 0; i < fHashArrayLength; i++ )
{
pCurrEntry = fLookupTable[ i ];
pPrevEntry = fLookupTable[ i ];
while ( pCurrEntry != nil )
{
bGetNext = true;
if ( pCurrEntry->fRefNum == inRefNum )
{
pDeadEntry = pCurrEntry;
if ( pCurrEntry == pPrevEntry )
{
fLookupTable[ i ] = pCurrEntry->fNext;
pCurrEntry = fLookupTable[ i ];
pPrevEntry = fLookupTable[ i ];
bGetNext = false;
}
else
{
pPrevEntry->fNext = pCurrEntry->fNext;
pCurrEntry = pPrevEntry;
}
if ( (fDeallocProcPtr != nil) && (pDeadEntry->fData != nil) )
{
entryDataPendingDelete.push_back( pDeadEntry->fData );
}
free( pDeadEntry );
pDeadEntry = nil;
fRefNumCount--;
siResult = eDSNoErr;
}
if ( pCurrEntry != nil )
{
if ( bGetNext == true )
{
pPrevEntry = pCurrEntry;
pCurrEntry = pPrevEntry->fNext;
}
}
}
}
fMutex.SignalLock();
while ( entryDataPendingDelete.size() != 0 )
{
(fDeallocProcPtr)( entryDataPendingDelete.back() );
entryDataPendingDelete.pop_back();
}
return( siResult );
}
UInt32 CContinue::GetRefNumForItem ( void *inData )
{
UInt32 uiResult = 0;
UInt32 uiTmpRef = 0;
UInt32 uiSlot = 0;
sDSTableEntry *pEntry = nil;
fMutex.WaitLock();
uiTmpRef = (UInt32)inData;
uiSlot = uiTmpRef % fHashArrayLength;
pEntry = fLookupTable[ uiSlot ];
while ( pEntry != nil )
{
if ( pEntry->fData == inData )
{
uiResult = pEntry->fRefNum;
break;
}
pEntry = pEntry->fNext;
}
fMutex.SignalLock();
return( uiResult );
}