mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
7.6 KiB
442 lines
7.6 KiB
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
PMY_ARRAY
|
|
StartArray(
|
|
OUT PMY_ARRAY ExistingStruct, OPTIONAL
|
|
IN unsigned InitialCount,
|
|
IN unsigned GrowthDelta,
|
|
IN unsigned ElementSize
|
|
)
|
|
{
|
|
PMY_ARRAY a;
|
|
|
|
a = ExistingStruct ? ExistingStruct : _MyMalloc(sizeof(MY_ARRAY));
|
|
if(a) {
|
|
|
|
if(a->Data = _MyMalloc(InitialCount * ElementSize)) {
|
|
|
|
a->Used = 0;
|
|
a->GrowthDelta = GrowthDelta;
|
|
a->ElementSize = ElementSize;
|
|
a->Size = InitialCount;
|
|
a->NeedsFreeing = (ExistingStruct == NULL);
|
|
return(a);
|
|
}
|
|
|
|
if(!ExistingStruct) {
|
|
_MyFree(a);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CopyDataIntoArray(
|
|
IN OUT PMY_ARRAY Array,
|
|
IN PVOID Data
|
|
)
|
|
{
|
|
if(Array->Data = _MyMalloc(Array->Used * Array->ElementSize)) {
|
|
|
|
CopyMemory(Array->Data,Data,Array->Used*Array->ElementSize);
|
|
|
|
Array->Size = Array->Used;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
GrowArray(
|
|
IN PMY_ARRAY Array,
|
|
IN unsigned MinimumDelta OPTIONAL
|
|
)
|
|
{
|
|
PVOID p;
|
|
unsigned Delta;
|
|
|
|
//
|
|
// Figure out how many multiples of the growth delta we need
|
|
// to get the minimum capacity delta. If minimum is not
|
|
// specified then just grow by the growth delta.
|
|
//
|
|
if(MinimumDelta) {
|
|
Delta = Array->Used + MinimumDelta - Array->Size;
|
|
|
|
if((int)Delta < 0) {
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// Round Delta up to a multiple of the growth delta.
|
|
//
|
|
if(Delta % Array->GrowthDelta) {
|
|
Delta += Array->GrowthDelta - (Delta % Array->GrowthDelta);
|
|
}
|
|
} else {
|
|
Delta = Array->GrowthDelta;
|
|
}
|
|
|
|
|
|
p = _MyRealloc(Array->Data,(Array->Size+Delta)*Array->ElementSize);
|
|
if(p) {
|
|
|
|
Array->Size += Delta;
|
|
Array->Data = p;
|
|
}
|
|
|
|
return(p != NULL);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ResizeArray(
|
|
IN OUT PMY_ARRAY Array,
|
|
IN LONG ElementCount
|
|
)
|
|
{
|
|
PVOID p;
|
|
|
|
if(ElementCount == -1) {
|
|
ElementCount = Array->Used;
|
|
}
|
|
|
|
if(p = _MyRealloc(Array->Data,ElementCount*Array->ElementSize)) {
|
|
Array->Data = p;
|
|
Array->Size = ElementCount;
|
|
}
|
|
//
|
|
// Leave original data undisturbed if realloc fails
|
|
//
|
|
return(p != NULL);
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeArray(
|
|
IN OUT PMY_ARRAY Array
|
|
)
|
|
{
|
|
_MyFree(Array->Data);
|
|
if(Array->NeedsFreeing) {
|
|
_MyFree(Array);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
#define STRBLK_INITIAL_SIZE 4096
|
|
#define STRBLK_GROWTH_DELTA 1024
|
|
|
|
PSTRINGBLOCK
|
|
CreateStringBlock(
|
|
VOID
|
|
)
|
|
{
|
|
PSTRINGBLOCK p;
|
|
|
|
if(p = _MyMalloc(sizeof(STRINGBLOCK))) {
|
|
|
|
if(InitStringBlock(p)) {
|
|
p->NeedToFree = TRUE;
|
|
return(p);
|
|
}
|
|
|
|
_MyFree(p);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
BOOL
|
|
InitStringBlock(
|
|
IN OUT PSTRINGBLOCK Block
|
|
)
|
|
{
|
|
Block->NeedToFree = FALSE;
|
|
|
|
if(Block->Data = _MyMalloc(STRBLK_INITIAL_SIZE*sizeof(WCHAR))) {
|
|
|
|
Block->Size = STRBLK_INITIAL_SIZE;
|
|
Block->Used = 0;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ReinitStringBlock(
|
|
IN OUT PSTRINGBLOCK StringBlock,
|
|
IN PVOID Data
|
|
)
|
|
{
|
|
if(StringBlock->Data = _MyMalloc(StringBlock->Used * sizeof(WCHAR))) {
|
|
|
|
CopyMemory(StringBlock->Data,Data,StringBlock->Used*sizeof(WCHAR));
|
|
|
|
StringBlock->Size = StringBlock->Used;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
VOID
|
|
StringBlockIdsToPointers(
|
|
IN PSTRINGBLOCK Block,
|
|
IN PVOID ArrayBase,
|
|
IN unsigned ArraySize,
|
|
IN unsigned ElementSize,
|
|
IN unsigned IdOffset
|
|
)
|
|
{
|
|
unsigned u;
|
|
PWSTR *pField;
|
|
LONG l;
|
|
|
|
for(u=0; u<ArraySize; u++) {
|
|
|
|
pField = (PWSTR *)((PUCHAR)ArrayBase+(u*ElementSize)+IdOffset);
|
|
|
|
l = *(LONG *)pField;
|
|
|
|
*pField = (l == -1) ? NULL : (Block->Data + l);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
StringPointersToBlockIds(
|
|
IN PSTRINGBLOCK Block,
|
|
IN PVOID ArrayBase,
|
|
IN unsigned ArraySize,
|
|
IN unsigned ElementSize,
|
|
IN unsigned IdOffset
|
|
)
|
|
{
|
|
unsigned u;
|
|
PLONG pField;
|
|
PWCHAR p;
|
|
|
|
for(u=0; u<ArraySize; u++) {
|
|
|
|
pField = (PLONG)((PUCHAR)ArrayBase+(u*ElementSize)+IdOffset);
|
|
|
|
p = *(PWCHAR *)pField;
|
|
|
|
*pField = p ? (((DWORD)p -(DWORD)Block->Data)/sizeof(WCHAR)) : -1;
|
|
}
|
|
}
|
|
|
|
|
|
LONG
|
|
AddToStringBlock(
|
|
IN OUT PSTRINGBLOCK Block,
|
|
IN PCWSTR String
|
|
)
|
|
{
|
|
UINT Length;
|
|
LONG Offset;
|
|
PVOID p;
|
|
|
|
Offset = -1;
|
|
|
|
//
|
|
// Determine how many char cells are needed to store this string.
|
|
//
|
|
Length = lstrlen(String) + 1;
|
|
|
|
while((Block->Used + Length) > Block->Size) {
|
|
//
|
|
// Need to grow the block.
|
|
//
|
|
p = _MyRealloc(Block->Data,(Block->Size+STRBLK_GROWTH_DELTA)*sizeof(WCHAR));
|
|
if(!p) {
|
|
break;
|
|
}
|
|
|
|
Block->Data = p;
|
|
Block->Size += STRBLK_GROWTH_DELTA;
|
|
}
|
|
|
|
Offset = (LONG)Block->Used;
|
|
|
|
lstrcpy(Block->Data+Offset,String);
|
|
|
|
Block->Used += Length;
|
|
|
|
return(Offset);
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeStringBlock(
|
|
IN OUT PSTRINGBLOCK Block
|
|
)
|
|
{
|
|
if(Block->Data) {
|
|
_MyFree(Block->Data);
|
|
}
|
|
if(Block->NeedToFree) {
|
|
_MyFree(Block);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
SortByStrings(
|
|
IN PSTRINGBLOCK StringBlock,
|
|
IN OUT PMY_ARRAY StructArray,
|
|
IN unsigned StructStringOffset,
|
|
IN PQSORTCB Compare
|
|
)
|
|
{
|
|
//
|
|
// Convert string ids in strctures in the array to pointers.
|
|
//
|
|
StringBlockIdsToPointers(
|
|
StringBlock,
|
|
ARRAY_DATA(StructArray),
|
|
ARRAY_USED(StructArray),
|
|
ARRAY_ELEMENT_SIZE(StructArray),
|
|
StructStringOffset
|
|
);
|
|
|
|
//
|
|
// Do the sort
|
|
//
|
|
qsort(
|
|
ARRAY_DATA(StructArray),
|
|
ARRAY_USED(StructArray),
|
|
ARRAY_ELEMENT_SIZE(StructArray),
|
|
Compare
|
|
);
|
|
|
|
//
|
|
// Convert string pointers back to ids
|
|
//
|
|
StringPointersToBlockIds(
|
|
StringBlock,
|
|
ARRAY_DATA(StructArray),
|
|
ARRAY_USED(StructArray),
|
|
ARRAY_ELEMENT_SIZE(StructArray),
|
|
StructStringOffset
|
|
);
|
|
}
|
|
|
|
|
|
int
|
|
_CRTAPI1
|
|
CompareStringsRoutine(
|
|
const void *p1,
|
|
const void *p2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback routine passed to the qsort function, which compares 2
|
|
strings. The comparison is based on the lexical value of the
|
|
strings.
|
|
|
|
The comparison is not case sensitive.
|
|
|
|
Arguments:
|
|
|
|
p1,p2 - supply pointers to 2 pointers to strings to be compared.
|
|
|
|
Return Value:
|
|
|
|
<0 element1 < element2
|
|
=0 element1 = element2
|
|
>0 element1 > element2
|
|
|
|
--*/
|
|
|
|
{
|
|
return(lstrcmpi(*(PCWSTR *)p1,*(PCWSTR *)p2));
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
InitDataBlock(
|
|
OUT PDATABLOCK DataBlock
|
|
)
|
|
{
|
|
DataBlock->Size = 0;
|
|
return((DataBlock->Data = _MyMalloc(0)) != NULL);
|
|
}
|
|
|
|
|
|
VOID
|
|
TermDataBlock(
|
|
OUT PDATABLOCK DataBlock
|
|
)
|
|
{
|
|
if(DataBlock->Data) {
|
|
_MyFree(DataBlock->Data);
|
|
DataBlock->Data = NULL;
|
|
}
|
|
}
|
|
|
|
LONG
|
|
AddToDataBlock(
|
|
IN OUT PDATABLOCK DataBlock,
|
|
IN PVOID Data,
|
|
IN DWORD DataSize
|
|
)
|
|
{
|
|
PVOID p;
|
|
LONG l;
|
|
|
|
p = _MyRealloc(DataBlock->Data,DataBlock->Size+DataSize);
|
|
if(!p) {
|
|
return(-1);
|
|
}
|
|
|
|
l = DataBlock->Size;
|
|
|
|
DataBlock->Data = p;
|
|
CopyMemory(DataBlock->Data+l,Data,DataSize);
|
|
|
|
DataBlock->Size += DataSize;
|
|
|
|
return(l);
|
|
}
|
|
|
|
VOID
|
|
DataBlockIdsToPointers(
|
|
IN PDATABLOCK Block,
|
|
IN PVOID ArrayBase,
|
|
IN unsigned ArraySize,
|
|
IN unsigned ElementSize,
|
|
IN unsigned IdOffset
|
|
)
|
|
{
|
|
unsigned u;
|
|
PVOID *pField;
|
|
|
|
for(u=0; u<ArraySize; u++) {
|
|
|
|
pField = (PVOID *)((PUCHAR)ArrayBase+(u*ElementSize)+IdOffset);
|
|
|
|
*pField = Block->Data + (*(LONG *)pField);
|
|
}
|
|
}
|