Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

329 lines
7.8 KiB

/*****************************************************************************
* *
* STACK.C *
* *
* Copyright (C) Microsoft Corporation 1990-1994 *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Intent *
* *
* This module implements a general purpose stack ADT. *
* Access by indices is also supported because I need it for path stuff. *
* Another peculiarity is that pushing onto a full stack causes the oldest *
* thing on the stack to be lost. *
* The size of the stack is fixed at creation time. The size of the stack *
* elements is set at create time. *
* The stack is stored as one hunk of data. If you need to store variable *
* sized things in the stack, you'll have to store pointers or handles to *
* your data in the stack. *
* *
*****************************************************************************/
#include "help.h"
#pragma hdrstop
/*****************************************************************************
* *
* Typedefs *
* *
*****************************************************************************/
typedef void (STDCALL *STACK_CALLBACK)(void*);
// Private stack structure. Clients only get a handle.
typedef struct {
int cMaxElements; // max # of elements in stack
int cCurElements; // current number of elements in stack
STACK_CALLBACK pfCallback;
// callback function to free orphaned stack elements
int cbElement; // size of a stack element in bytes
BYTE aElements[1]; // the "array" of stack elements (sized at init time)
} STACK, *QSTACK;
/***************************************************************************\
*
- Function: RcInitStack( qhstack, c, cbElement, pfCallback )
-
* Purpose: Create a STACK.
*
* ASSUMES
*
* args IN: qhstack - pointer to user's HSTACK
* c - max number of stack elements
* cbElement - size in bytes of a stack element
* pfCallback - pointer to callback function.
* Called when a stack element is bumped from
* the stack due to a push on a full stack.
* Also called once for each element left in
* the stack at fini time. The parameter is
* a far pointer to the stack element.
* Prototype is:
*
* void STDCALL CallBack( QV );
*
* PROMISES
*
* returns: rcSuccess
* rcOutOfMemory
*
* args OUT: qhstack - contains an HSTACK on rcSuccess
*
\***************************************************************************/
RC STDCALL RcInitStack(HSTACK* qhstack, int cMaxElements, int cbElement,
STACK_CALLBACK pfCallback)
{
QSTACK qstack;
*qhstack = LhAlloc(LMEM_FIXED, sizeof(STACK) - 1 +
cbElement * cMaxElements);
if (!*qhstack)
OOM(); // doesn't return
qstack = PtrFromGh(*qhstack);
qstack->cMaxElements = cMaxElements;
qstack->cCurElements = 0;
qstack->pfCallback = pfCallback; // called when deleting the stack
qstack->cbElement = cbElement;
return rcSuccess;
}
/***************************************************************************\
*
- Function: RcFiniStack( hstack )
-
* Purpose: Deallocate memory associated with stack.
*
* ASSUMES
*
* args IN: hstack - a valid stack
*
* PROMISES
*
* returns: rcSuccess
*
* args OUT: hstack - no longer a valid HSTACK
*
\***************************************************************************/
RC STDCALL RcFiniStack(HSTACK hstack)
{
QSTACK qstack;
int i;
ASSERT(hstack);
qstack = PtrFromGh(hstack);
if (qstack->pfCallback) {
for(i = qstack->cCurElements - 1; i >= 0; i--)
qstack->pfCallback(qstack->aElements + qstack->cbElement * i);
}
FreeGh(hstack);
return rcSuccess;
}
/***************************************************************************\
*
- Function: FEmptyStack( hstack )
-
* Purpose: Is the stack empty?
*
* ASSUMES
*
* args IN: hstack - a valid stack
*
* PROMISES
*
* returns: emptiness of stack
*
\***************************************************************************/
BOOL STDCALL FEmptyStack(HSTACK hstack )
{
ASSERT(hstack);
return (((QSTACK) PtrFromGh(hstack))->cCurElements == 0);
}
/***************************************************************************
FUNCTION: CElementsStack
PURPOSE: Return number of elements in the stack.
PARAMETERS:
hstack
COMMENTS:
***************************************************************************/
UINT STDCALL CElementsStack(HSTACK hstack)
{
ASSERT(hstack);
return (UINT) ((QSTACK) PtrFromGh(hstack))->cCurElements;
}
/***************************************************************************\
*
- Function: RcPushStack( hstack, qse )
-
* Purpose: Push a stack element onto a stack.
*
* ASSUMES
*
* args IN: hstack - a valid stack
* qse - pointer to element to push
*
* PROMISES
*
* returns: rcSuccess always
*
* args OUT: hstack -
*
* Note: This is NOT a normal stack. When it's full, you lose the
* oldest thing stored.
*
\***************************************************************************/
void STDCALL RcPushStack(HSTACK hstack, void* qse)
{
QSTACK qstack;
ASSERT(qse);
ASSERT(hstack);
qstack = PtrFromGh(hstack);
if (qstack->cMaxElements == qstack->cCurElements) {
if (qstack->pfCallback)
qstack->pfCallback(qstack->aElements);
MoveMemory(qstack->aElements, qstack->aElements + qstack->cbElement,
qstack->cbElement * --qstack->cCurElements);
}
MoveMemory(qstack->aElements + qstack->cbElement * qstack->cCurElements++,
qse, qstack->cbElement);
}
/***************************************************************************\
*
- Function: RcPopStack( hstack )
-
* Purpose: Remove the top element from the stack.
*
* ASSUMES
*
* args IN: hstack - nonempty stack
*
* PROMISES
*
* returns: rcSuccess
* rcFailure - if stack was empty
*
* args OUT: hstack
*
\***************************************************************************/
RC STDCALL RcPopStack(HSTACK hstack)
{
QSTACK qstack;
ASSERT(hstack );
qstack = PtrFromGh(hstack);
if (!qstack->cCurElements)
return rcFailure;
else {
--qstack->cCurElements;
return rcSuccess;
}
}
/***************************************************************************
FUNCTION: RcTopStack
PURPOSE: Return the top element of the stack.
PARAMETERS:
hstack -- stack handle
qse -- buffer to receive stack element
RETURNS: rcFailure if stack is empty
COMMENTS:
Does not alter the stack
***************************************************************************/
RC STDCALL RcTopStack(HSTACK hstack, void* qse)
{
QSTACK qstack;
ASSERT(hstack);
qstack = PtrFromGh(hstack);
if (!qstack->cCurElements)
return rcFailure;
else {
MoveMemory(qse,
qstack->aElements + qstack->cbElement * (qstack->cCurElements - 1),
qstack->cbElement);
return rcSuccess;
}
}
/***************************************************************************\
*
- Function: RcGetIthStack( hstack, i, qse )
-
* Purpose: Get arbitrary element of the "stack".
* 0 means oldest element still stored in stack.
*
* ASSUMES
*
* args IN: hstack
* i - 0 <= i < # elements in stack
* qse - users buffer for
*
* PROMISES
*
* returns: rcSuccess
* rcFailure - i < 0 or > # elements in stack
*
* args OUT: qse - ith element copied here
*
* Side Effects:
*
* Notes: This isn't a real stack operation.
*
* Bugs: 0 should probably mean the newest (equivalent to top).
*
\***************************************************************************/
RC STDCALL RcGetIthStack(HSTACK hstack, int i, void* qse)
{
QSTACK qstack;
ASSERT(hstack);
ASSERT(i >= 0)
qstack = PtrFromGh(hstack);
if (i >= qstack->cCurElements) {
return rcFailure;
}
else {
MoveMemory(qse, qstack->aElements + qstack->cbElement * i,
qstack->cbElement);
return rcSuccess;
}
}