Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

361 lines
7.2 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: Stack.cpp
//
// History: 31-Mar-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "Stack.hxx"
Stack_::Stack_(CRITICAL_SECTION *pCS)
{
dwStackCount = 0;
psBottom = NULL;
ppsSorted = NULL;
ppsGet = NULL;
pSortCriticalSection = pCS;
}
Stack_::~Stack_(void)
{
if (psBottom)
{
StackStruct_ *psCurrent;
for (;;)
{
psCurrent = psBottom->psNext;
delete psBottom->pvData;
delete psBottom;
psBottom = psCurrent;
if (!(psBottom))
{
break;
}
}
}
DELETE_OBJECT(ppsSorted);
FlushGetStack();
}
BOOL Stack_::Add(DWORD cbData, void *pvData)
{
BYTE *pb;
if (pb = (BYTE *)this->Add(cbData))
{
memcpy(pb, pvData, cbData);
return(TRUE);
}
return(FALSE);
}
void *Stack_::Add(DWORD cbData)
{
StackStruct_ *psWork;
psWork = new StackStruct_;
if (!(psWork))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(NULL);
}
psWork->psNext = psBottom;
psWork->pvData = new BYTE[cbData];
if (!(psWork->pvData))
{
delete psWork;
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
psWork->cbData = cbData;
psBottom = psWork;
dwStackCount++;
FlushGetStack();
return((void *)psWork->pvData);
}
void *Stack_::Get(DWORD dwPosition, DWORD *cbData)
{
DWORD i;
StackStruct_ *psRet;
if (!(psBottom))
{
return(NULL);
}
if (dwPosition > (dwStackCount - 1))
{
return(NULL);
}
if ( InitGetStackIfNecessary() == TRUE )
{
DWORD Index = dwPosition;
if ( cbData != NULL )
{
*cbData = ppsGet[ Index ]->cbData;
}
return( ppsGet[ Index ]->pvData );
}
psRet = psBottom;
if (cbData)
{
*cbData = 0;
}
for (i = 0; i < dwPosition; i++)
{
psRet = psRet->psNext;
}
if ((psRet) && (psRet->pvData))
{
if (cbData)
{
*cbData = psRet->cbData;
}
return(psRet->pvData);
}
return(NULL);
}
void *Stack_::Get(DWORD cbStartIn_pvData, DWORD cbLengthIn_pvData, BYTE fbType, void *pvMemberOf_pvData)
{
DWORD dwEnd;
DWORD dwMiddle;
DWORD dwStart;
DWORD dwHalf;
DWORD dwCur;
void *pv;
int cmp;
dwStart = 0;
dwEnd = this->Count();
dwHalf = dwMiddle = dwEnd / 2L;
dwCur = 0;
for EVER
{
if (dwCur++ > this->Count())
{
break;
}
pv = this->Get(dwMiddle);
if (!(pv))
{
break;
}
switch (fbType)
{
case STACK_SORTTYPE_PWSZ:
cmp = wcscmp(*(WCHAR **)((BYTE *)pv + cbStartIn_pvData), (WCHAR *)pvMemberOf_pvData);
break;
case STACK_SORTTYPE_PSZ:
cmp = strcmp(*(char **)((BYTE *)pv + cbStartIn_pvData), (char *)pvMemberOf_pvData);
break;
case STACK_SORTTYPE_PWSZ_I:
cmp = _wcsicmp(*(WCHAR **)((BYTE *)pv + cbStartIn_pvData), (WCHAR *)pvMemberOf_pvData);
break;
case STACK_SORTTYPE_PSZ_I:
cmp = _stricmp(*(char **)((BYTE *)pv + cbStartIn_pvData), (char *)pvMemberOf_pvData);
break;
default:
cmp = memcmp((BYTE *)pv + cbStartIn_pvData, (BYTE *)pvMemberOf_pvData, cbLengthIn_pvData);
break;
}
if (cmp == 0)
{
return(pv);
}
if ((dwMiddle == 0) || (dwMiddle == this->Count()) ||
((dwHalf == 0) && (dwMiddle == dwStart)))
{
break;
}
if (cmp < 0)
{
dwEnd = dwMiddle;
}
else
{
dwStart = dwMiddle;
}
dwHalf = (dwEnd - dwStart) / 2L;
dwMiddle = dwStart + dwHalf;
}
return(NULL);
}
static DWORD cbSortOffset;
static DWORD cbSortLength;
static BYTE fbType;
int __cdecl Stack_compare(const void *arg1, const void *arg2)
{
StackStruct_ **p1 = (StackStruct_ **)arg1;
StackStruct_ **p2 = (StackStruct_ **)arg2;
switch (fbType)
{
case STACK_SORTTYPE_PWSZ:
return(wcscmp(*(WCHAR **)((BYTE *)(*p1)->pvData + cbSortOffset),
*(WCHAR **)((BYTE *)(*p2)->pvData + cbSortOffset)));
case STACK_SORTTYPE_PSZ:
return(strcmp(*(char **)((BYTE *)(*p1)->pvData + cbSortOffset),
*(char **)((BYTE *)(*p2)->pvData + cbSortOffset)));
case STACK_SORTTYPE_PWSZ_I:
return(_wcsicmp(*(WCHAR **)((BYTE *)(*p1)->pvData + cbSortOffset),
*(WCHAR **)((BYTE *)(*p2)->pvData + cbSortOffset)));
case STACK_SORTTYPE_PSZ_I:
return(_stricmp(*(char **)((BYTE *)(*p1)->pvData + cbSortOffset),
*(char **)((BYTE *)(*p2)->pvData + cbSortOffset)));
case STACK_SORTTYPE_BINARY:
default:
break;
}
return(memcmp((void **)((BYTE *)(*p1)->pvData + cbSortOffset),
(void **)((BYTE *)(*p2)->pvData + cbSortOffset), cbSortLength));
}
void Stack_::Sort(DWORD cbOffset_pvData, DWORD cbLength_pvData, BYTE fbTypeIn)
{
int i;
if (!(psBottom))
{
return;
}
//
// assign out offset & length for compare function
//
DELETE_OBJECT(ppsSorted); // wipe the last one.
if (!(ppsSorted = new StackStruct_ * [this->Count()]))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return;
}
//
// assign the contiguous array to be sorted.
//
ppsSorted[0] = psBottom;
for (i = 1; i < (int)this->Count(); i++)
{
ppsSorted[i] = ppsSorted[i - 1]->psNext;
}
//
// let's do the sort!
//
EnterCriticalSection(pSortCriticalSection);
cbSortOffset = cbOffset_pvData;
cbSortLength = cbLength_pvData;
fbType = fbTypeIn;
qsort( (void *)ppsSorted, (size_t)this->Count(), sizeof(StackStruct_ *), Stack_compare);
LeaveCriticalSection(pSortCriticalSection);
//
// now, we need to adjust out psNext's
//
for (i = 0; i < (int)(this->Count() - 1); i++)
{
ppsSorted[i]->psNext = ppsSorted[i + 1];
}
ppsSorted[i]->psNext = NULL;
psBottom = ppsSorted[0];
FlushGetStack();
}
BOOL Stack_::InitGetStackIfNecessary ()
{
DWORD cCount;
StackStruct_* psGet;
if ( ppsGet != NULL )
{
return( TRUE );
}
ppsGet = new StackStruct_ * [ dwStackCount ];
if ( ppsGet == NULL )
{
return( FALSE );
}
psGet = psBottom;
for ( cCount = 0; cCount < dwStackCount; cCount++ )
{
ppsGet[ cCount ] = psGet;
psGet = psGet->psNext;
}
return( TRUE );
}
VOID Stack_::FlushGetStack ()
{
delete ppsGet;
ppsGet = NULL;
}