// The omnipresent memory list, WIN32 implementation, thread safe #define WIN32_LEAN_AND_MEAN #include #include "memlist.h" #pragma warning (disable: 4706) // assignment within conditional expression struct _tagLIST { unsigned int uiCount; unsigned int uiCapacity; void **apStorage; HANDLE hHeap; CRITICAL_SECTION cs; }; TYP_LIST *List_Init(unsigned int uiCapacity) { HANDLE hHeap = GetProcessHeap(); TYP_LIST *pstHandle; pstHandle = (TYP_LIST *)HeapAlloc(hHeap, 0, sizeof(TYP_LIST)); if (!pstHandle) return NULL; pstHandle->uiCount = 0; pstHandle->uiCapacity = uiCapacity; if (uiCapacity == 0) pstHandle->apStorage = NULL; else { pstHandle->apStorage = (void **)HeapAlloc(hHeap, 0, sizeof(void *)*uiCapacity); if (!pstHandle->apStorage) { HeapFree (hHeap, 0, pstHandle); return NULL; } } pstHandle->hHeap = hHeap; InitializeCriticalSection (&pstHandle->cs); return pstHandle; } void List_Exit(TYP_LIST *pstHandle) { if (pstHandle->apStorage) HeapFree (pstHandle->hHeap, 0, pstHandle->apStorage); DeleteCriticalSection (&pstHandle->cs); HeapFree (pstHandle->hHeap, 0, pstHandle); } BOOL List_Push(TYP_LIST *pstHandle, void *pItem) { return List_InsertElementAt(pstHandle, pItem,pstHandle->uiCount); } void *List_Pop (TYP_LIST *pstHandle) { if (pstHandle->uiCount) return List_RemoveElementAt(pstHandle ,pstHandle->uiCount-1); else return NULL; } BOOL List_InsertElementAt(TYP_LIST *pstHandle, void *pItem, unsigned int uiPos) { unsigned int uiStep; void **apNewStorage; EnterCriticalSection (&pstHandle->cs); if (uiPos > pstHandle->uiCount) uiPos = pstHandle->uiCount; if (pstHandle->uiCount >= pstHandle->uiCapacity) { uiStep = pstHandle->uiCount*2; if (uiStep < 8) uiStep = 8; if (!pstHandle->apStorage) apNewStorage = (void **)HeapAlloc(pstHandle->hHeap, 0, sizeof(void *)*uiStep); else apNewStorage = HeapReAlloc (pstHandle->hHeap, 0, pstHandle->apStorage, sizeof(void *)*uiStep); if (!apNewStorage) { LeaveCriticalSection (&pstHandle->cs); return FALSE; } pstHandle->apStorage = apNewStorage; pstHandle->uiCapacity = uiStep; } if (uiPosuiCount) MoveMemory (&pstHandle->apStorage[uiPos+1], &pstHandle->apStorage[uiPos], (pstHandle->uiCount-uiPos)*sizeof(void*)); pstHandle->apStorage[uiPos] = pItem; pstHandle->uiCount++; LeaveCriticalSection (&pstHandle->cs); return TRUE; } void *List_RemoveElementAt(TYP_LIST *pstHandle, unsigned int uiPos) { void *pRet; EnterCriticalSection (&pstHandle->cs); pRet = pstHandle->apStorage[uiPos]; if (uiPosuiCount) MoveMemory (&pstHandle->apStorage[uiPos], &pstHandle->apStorage[uiPos+1], (pstHandle->uiCount-uiPos)*sizeof(void*)); pstHandle->uiCount--; LeaveCriticalSection (&pstHandle->cs); return pRet; } unsigned int List_Count(TYP_LIST *pstHandle) { return pstHandle->uiCount; } void *List_ElementAt(TYP_LIST *pstHandle,unsigned int uiPos) { void *pRet = NULL; EnterCriticalSection (&pstHandle->cs); if (uiPos < pstHandle->uiCount) pRet = pstHandle->apStorage[uiPos]; LeaveCriticalSection (&pstHandle->cs); return pRet; } void *List_Top(TYP_LIST *pstHandle) { if (pstHandle->uiCount) return List_ElementAt (pstHandle, pstHandle->uiCount-1); else return NULL; } #ifdef _INC_STDLIB void List_Sort(TYP_LIST *pstHandle, int (*pFunc)(const void*,const void*)) { EnterCriticalSection (&pstHandle->cs); qsort(pstHandle->apStorage,pstHandle->uiCount,sizeof(void *),pFunc); LeaveCriticalSection (&pstHandle->cs); } #endif void List_FreeElements(TYP_LIST *pstHandle) { void *pEntry; HANDLE hHeap = GetProcessHeap(); while (pEntry = List_Pop(pstHandle)) HeapFree (hHeap, 0, pEntry); } BOOL List_BinarySearch(TYP_LIST *hPList, int (*pPFunc)(const void *pstPElement,const void *pstPToFind), const void *pstPToFind,int *piPToInsert) { unsigned int iStart, iEnd, iInd; int iRetCompare; if (hPList == NULL) { *piPToInsert = 0; return FALSE; } iStart = 0; if (hPList->uiCount == 0) { *piPToInsert = 0; return FALSE; } EnterCriticalSection (&hPList->cs); iEnd = hPList->uiCount-1; iRetCompare = (*pPFunc)(hPList->apStorage[0],pstPToFind); if (iRetCompare >= 0) { *piPToInsert = 0; LeaveCriticalSection (&hPList->cs); return iRetCompare == 0; } iRetCompare = (*pPFunc)(hPList->apStorage[iEnd],pstPToFind); if (iRetCompare < 0) { *piPToInsert = hPList->uiCount; LeaveCriticalSection (&hPList->cs); return FALSE; } else if (iRetCompare == 0) { *piPToInsert = hPList->uiCount-1; LeaveCriticalSection (&hPList->cs); return TRUE; } // Otherwise C4702: unreachable code below #pragma warning (suppress: 4127) // conditional expression is constant while(1) { switch (iEnd-iStart) { case 0: *piPToInsert = iStart; LeaveCriticalSection (&hPList->cs); return FALSE; case 1: *piPToInsert = iStart+1; LeaveCriticalSection (&hPList->cs); return FALSE; default: iInd = iStart + (iEnd-iStart)/2; iRetCompare = (*pPFunc)(hPList->apStorage[iInd],pstPToFind); if (iRetCompare == 0) { *piPToInsert = iInd; LeaveCriticalSection (&hPList->cs); return TRUE; } if (iRetCompare < 0) iStart = iInd; else iEnd = iInd; break; } } LeaveCriticalSection (&hPList->cs); return FALSE; } BOOL List_InsertSort(TYP_LIST *hPList, int (*pPFunc)(const void *pstPElement,const void *pstPToFind), void *pItem) { int iListInd; if (!List_BinarySearch(hPList,pPFunc,(void *)pItem,&iListInd)) { return List_InsertElementAt (hPList, pItem, iListInd); } return FALSE; }