//================================================================================ // Copyright (C) 1997 Microsoft Corporation // Author: RameshV // Description: implements a growable array // ThreadSafe: no // Locks: none // Please read stdinfo.txt for conventions on reading/writing code that i use //================================================================================ #include #define FILE "mm\\array.h" #ifdef IMPORTS MemAlloc MemFree AssertRet Require #endif IMPORTS //BeginExport(typedef) typedef struct _ARRAY { DWORD nElements; DWORD nAllocated; LPVOID *Ptrs; } ARRAY, *PARRAY, *LPARRAY; //EndExport(typedef) //BeginExport(typedef) typedef DWORD ARRAY_LOCATION; typedef ARRAY_LOCATION* PARRAY_LOCATION; typedef PARRAY_LOCATION LPARRAY_LOCATION; //EndExport(typedef) //BeginExport(inline) DWORD _inline MemArrayInit( // initialize the STRUCTURE OUT PARRAY Array // input structure pre-allocated ) { AssertRet(Array, ERROR_INVALID_PARAMETER); Array->nElements = Array->nAllocated = 0; Array->Ptrs = NULL; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayCleanup( // freeup the memory if any, allocated in this module IN OUT PARRAY Array ) { AssertRet(Array, ERROR_INVALID_PARAMETER); if( Array->Ptrs) MemFree(Array->Ptrs); Array->nElements = Array->nAllocated = 0; Array->Ptrs = NULL; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArraySize( IN PARRAY Array ) { AssertRet(Array, ERROR_INVALID_PARAMETER); return Array->nElements; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayInitLoc( // Initialize an array location IN PARRAY Array, IN OUT PARRAY_LOCATION Location ) { AssertRet(Array && Location, ERROR_INVALID_PARAMETER); (*Location) = 0; if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) BOOL _inline MemArrayValidLoc( IN PARRAY Array, IN PARRAY_LOCATION Location ) { AssertRet(Array && Location, FALSE); return ( *Location < Array->nElements ); } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayNextLoc( // move one step forward IN PARRAY Array, IN OUT PARRAY_LOCATION Location ) { AssertRet(Array && Location, ERROR_INVALID_PARAMETER); if( (*Location) + 1 >= Array->nElements ) return ERROR_FILE_NOT_FOUND; (*Location) ++; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayPrevLoc( IN PARRAY Array, IN OUT PARRAY_LOCATION Location ) { AssertRet(Array && Location, ERROR_INVALID_PARAMETER); if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND; if( ((LONG)(*Location)) - 1 < 0 ) return ERROR_FILE_NOT_FOUND; (*Location) --; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayLastLoc( IN PARRAY Array, IN OUT PARRAY_LOCATION Location ) { AssertRet(Array && Location, ERROR_INVALID_PARAMETER); if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND; (*Location) = Array->nElements -1; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayGetElement( IN PARRAY Array, IN PARRAY_LOCATION Location, OUT LPVOID *Element ) { AssertRet(Array && Location && Element, ERROR_INVALID_PARAMETER); (*Element) = Array->Ptrs[*Location]; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArraySetElement( IN OUT PARRAY Array, IN PARRAY_LOCATION Location, IN LPVOID Element ) { AssertRet(Array && Location, ERROR_INVALID_PARAMETER ); Array->Ptrs[*Location] = Element; return ERROR_SUCCESS; } //EndExport(inline) const DWORD MinAllocUnit = 4; const DWORD MinFreeUnit = 4; // Must be a power of two LPVOID _inline MemAllocLpvoid( DWORD nLpvoids ) { return MemAlloc(sizeof(LPVOID)*nLpvoids); } //BeginExport(function) DWORD MemArrayAddElement( IN OUT PARRAY Array, IN LPVOID Element ) //EndExport(function) { LPVOID Ptrs; AssertRet(Array, ERROR_INVALID_PARAMETER ); if( Array->nElements < Array->nAllocated ) { Array->Ptrs[Array->nElements ++ ] = Element; return ERROR_SUCCESS; } if( 0 == Array->nAllocated ) { Array->Ptrs = MemAllocLpvoid(MinAllocUnit); if( NULL == Array->Ptrs ) return ERROR_NOT_ENOUGH_MEMORY; Array->nAllocated = MinAllocUnit; Array->nElements = 1; Array->Ptrs[0] = Element; return ERROR_SUCCESS; } Ptrs = MemAllocLpvoid(MinAllocUnit+Array->nAllocated); if( NULL == Ptrs ) return ERROR_NOT_ENOUGH_MEMORY; memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*Array->nAllocated); MemFree(Array->Ptrs); Array->Ptrs = Ptrs; Array->Ptrs[Array->nElements++] = Element; Array->nAllocated += MinAllocUnit; return ERROR_SUCCESS; } //BeginExport(function) DWORD MemArrayInsElement( IN OUT PARRAY Array, IN PARRAY_LOCATION Location, IN LPVOID Element ) //EndExport(function) { LPVOID *Ptrs; AssertRet(Array && Location, ERROR_INVALID_PARAMETER); if( (*Location) == Array->nElements ) return MemArrayAddElement(Array,Element); if( Array->nElements < Array->nAllocated ) { memmove(&Array->Ptrs[1+*Location], &Array->Ptrs[*Location], sizeof(LPVOID)*(Array->nElements - *Location)); Array->Ptrs[*Location] = Element; Array->nElements++; return ERROR_SUCCESS; } Require(Array->nElements); Ptrs = MemAllocLpvoid(MinAllocUnit + Array->nAllocated); if( NULL == Ptrs ) return ERROR_NOT_ENOUGH_MEMORY; memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*(*Location) ); Ptrs[*Location] = Element; memcpy(&Ptrs[1+*Location], &Array->Ptrs[*Location], sizeof(LPVOID)*(Array->nElements - *Location)); MemFree(Array->Ptrs); Array->Ptrs = Ptrs; Array->nElements ++; Array->nAllocated += MinAllocUnit; return ERROR_SUCCESS; } //BeginExport(function) DWORD MemArrayDelElement( IN OUT PARRAY Array, IN PARRAY_LOCATION Location, IN LPVOID *Element ) //EndExport(function) { LPVOID *Ptrs; AssertRet(Array && Location && Array->nElements && Element, ERROR_INVALID_PARAMETER); (*Element) = Array->Ptrs[*Location]; Array->nElements--; if( 0 == Array->nElements ) { Require(0 == *Location); return MemArrayCleanup(Array); } if( Array->nElements % MinFreeUnit || NULL == (Ptrs = MemAllocLpvoid(Array->nElements))) { memcpy(&Array->Ptrs[*Location], &Array->Ptrs[1+*Location], sizeof(LPVOID)*(Array->nElements - (*Location))); return ERROR_SUCCESS; } Require(Ptrs); memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*(*Location)); memcpy(&Ptrs[*Location], &Array->Ptrs[1+*Location], sizeof(LPVOID)*(Array->nElements - (*Location))); MemFree(Array->Ptrs); Array->Ptrs = Ptrs; Array->nAllocated = Array->nElements; return ERROR_SUCCESS; } //BeginExport(inline) DWORD _inline MemArrayAdjustLocation( // reset location to "next" after a delete IN PARRAY Array, IN OUT PARRAY_LOCATION Location ) { AssertRet(Location && Array, ERROR_INVALID_PARAMETER); if( *Location >= Array->nElements ) return ERROR_FILE_NOT_FOUND; return ERROR_SUCCESS; } //EndExport(inline) //BeginExport(inline) DWORD _inline MemArrayRotateCyclical( // rotate forward/right cyclical IN PARRAY Array ) { LPVOID FirstPtr; AssertRet(Array, ERROR_INVALID_PARAMETER); if( Array->nElements < 2 ) return ERROR_SUCCESS; FirstPtr = Array->Ptrs[0]; memcpy(Array->Ptrs, &Array->Ptrs[1], sizeof(Array->Ptrs[0])* (Array->nElements -1)); Array->Ptrs[Array->nElements -1] = FirstPtr; return ERROR_SUCCESS; } //EndExport(inline) //================================================================================ // end of file //================================================================================