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.
329 lines
7.8 KiB
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;
|
|
}
|
|
}
|