317 lines
8.8 KiB
C
317 lines
8.8 KiB
C
//================================================================================
|
|
// 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 <mm.h>
|
|
#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
|
|
//================================================================================
|
|
|