windows-nt/Source/XPSP1/NT/net/rras/ip/nath323/dynarray.h
2020-09-26 16:20:57 +08:00

262 lines
5.1 KiB
C++

#ifndef __h323ics_dynarray_h
#define __h323ics_dynarray_h
// a dense array
typedef const void * BINARY_SEARCH_KEY;
template <class OBJECT>
class DYNAMIC_ARRAY
{
public:
// returns positive if ObjectA > ObjectB
// returns negative if ObjectA < ObjectB
// returns zero if ObjectA = ObjectB
typedef int (__cdecl * COMPARE_FUNC) (const OBJECT * ObjectA, const OBJECT * ObjectB);
public:
OBJECT * Data;
DWORD Length;
DWORD MaxLength;
public:
void Clear (void) {
Length = 0;
}
void Free (void) {
if (Data) {
HeapFree (GetProcessHeap(), 0, Data);
Data = NULL;
Length = 0;
MaxLength = 0;
}
else {
_ASSERTE (!Length);
_ASSERTE (!MaxLength);
}
}
DWORD GetLength (void) { return Length; }
DWORD GetMax (void) { return MaxLength; }
BOOL Grow (DWORD MaxLengthRequested) {
OBJECT * NewData;
DWORD NewMaxLength; // in OBJECT units
DWORD BytesRequested;
if (MaxLengthRequested <= MaxLength)
return TRUE;
// very arbitrary heuristic
NewMaxLength = MaxLengthRequested + (MaxLengthRequested >> 1) + 0x20;
BytesRequested = NewMaxLength * sizeof (OBJECT);
if (Data) {
NewData = (OBJECT *) HeapReAlloc (GetProcessHeap(), 0, Data, BytesRequested);
if (!NewData)
DebugF (_T("DYNAMIC_ARRAY::Grow: HeapReAlloc failed, BytesRequested %08XH\n"), BytesRequested);
}
else {
NewData = (OBJECT *) HeapAlloc (GetProcessHeap(), 0, BytesRequested);
if (!NewData)
DebugF (_T("DYNAMIC_ARRAY::Grow: HeapAlloc failed, BytesRequested %08XH\n"), BytesRequested);
}
if (!NewData)
return FALSE;
Data = NewData;
MaxLength = NewMaxLength;
return TRUE;
}
OBJECT * AllocRangeAtPos (DWORD pos, DWORD RangeLength) {
_ASSERTE (pos <= Length);
if (!Grow (Length + RangeLength))
return NULL;
memmove (Data + pos + RangeLength, Data + pos, (Length - pos) * sizeof (OBJECT));
Length += RangeLength;
return Data + pos;
}
OBJECT * AllocAtPos (DWORD pos) {
return AllocRangeAtPos (pos, 1);
}
OBJECT * AllocAtEnd (void) {
return AllocAtPos (Length);
}
void DeleteRangeAtPos (DWORD pos, DWORD RangeLength) {
_ASSERTE (Data);
_ASSERTE (MaxLength);
_ASSERTE (Length);
_ASSERTE (pos < Length);
_ASSERTE (Length - pos >= RangeLength);
memmove (Data + pos, Data + pos + RangeLength, (Length - pos - RangeLength) * sizeof (OBJECT));
Length -= RangeLength;
}
void DeleteAtPos (DWORD pos) {
DeleteRangeAtPos (pos, 1);
}
void DeleteEntry (OBJECT * Object) {
_ASSERTE (Object >= Data);
_ASSERTE (Object < Data + Length);
DeleteAtPos ((DWORD)(Object - Data));
}
DYNAMIC_ARRAY (void)
: Data (NULL), Length (0), MaxLength (0) {}
~DYNAMIC_ARRAY (void) {
Free();
}
void QuickSort (COMPARE_FUNC CompareFunc) {
qsort (Data, Length, sizeof (OBJECT), (int (__cdecl *) (const void *, const void *)) CompareFunc);
}
// a templatized version of BinarySearch
// SearchFunc should:
// return positive if SearchKey > Comparand
// return negative if SearchKey < Comparand
// return zero if SearchKey = Comparand
template <class SEARCH_KEY>
BOOL BinarySearch (
IN INT (*SearchFunc) (const SEARCH_KEY * SearchKey, const OBJECT * Comparand),
IN const SEARCH_KEY * SearchKey,
OUT DWORD * ReturnIndex)
{
DWORD Start;
DWORD End;
DWORD Index;
OBJECT * Object;
int CompareResult;
assert (ReturnIndex);
Start = 0;
End = Length;
for (;;) {
Index = (Start + End) / 2;
if (Index == End) {
*ReturnIndex = Index;
return FALSE;
}
Object = Data + Index;
CompareResult = (*SearchFunc) (SearchKey, Object);
if (CompareResult == 0) {
*ReturnIndex = Index;
return TRUE;
}
else if (CompareResult > 0) {
Start = Index + 1;
}
else {
End = Index;
}
}
}
BOOL FindIndex (COMPARE_FUNC CompareFunc,
OBJECT * ObjectArg,
DWORD * ReturnIndex)
{
DWORD Start;
DWORD End;
DWORD Index;
OBJECT *Object;
int CompareResult;
_ASSERTE (ReturnIndex);
Start = 0;
End = Length;
for (;;) {
Index = (Start + End) / 2;
if (Index == End) {
*ReturnIndex = Index;
return FALSE;
}
Object = Data + Index;
CompareResult = (*CompareFunc)(ObjectArg, Object);
if (CompareResult == 0) {
*ReturnIndex = Index;
return TRUE;
}
else if (CompareResult > 0) {
Start = Index + 1;
}
else {
End = Index;
}
}
}
void GetExtents (
OUT OBJECT ** ReturnStart,
OUT OBJECT ** ReturnEnd)
{
_ASSERTE (ReturnStart);
_ASSERTE (ReturnEnd);
*ReturnStart = Data;
*ReturnEnd = Data + Length;
}
OBJECT & operator[] (
IN DWORD Index)
{
_ASSERTE (Index < Length);
return Data [Index];
}
};
// Hack/Hint for Alpha compiler
#define DECLARE_SEARCH_FUNC_CAST_X(Suffix,Key,Object) typedef INT (* SEARCH_FUNC_##Suffix)(const Key *, const Object *)
#define DECLARE_SEARCH_FUNC_CAST(Key,Object) DECLARE_SEARCH_FUNC_CAST_X(Object,Key,Object)
// I hope these don't conflict with someone else's m_Array, etc.
// Should eventually globally replace all references to the right names
#define m_Array Data
#define m_Length Length
#define m_Max MaxLength
#endif // __h323ics_dynarray_h