Leaked source code of windows server 2003
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.
 
 
 
 
 
 

314 lines
7.7 KiB

/* (C) 1997 Microsoft Corp.
*
* file : SList.c
* authors : Christos Tsollis, Erik Mavrinac
*
* description: Implementation of list described in SList.h.
*/
#include "precomp.h"
#pragma hdrstop
#include "MCSMUX.h"
void SListInit(PSList pSL, unsigned NItems)
{
pSL->MaxEntries = NItems;
// Allocate the block of items (which, hopefully, will be the last one).
// NULL return value will be handled in the future.
pSL->Entries = (_SListNode *)Malloc(NItems * sizeof(_SListNode));
// Initialize the private member variables
pSL->NEntries = 0;
pSL->HeadOffset = 0;
pSL->CurrOffset = 0xFFFFFFFF;
}
void SListDestroy(PSList pSL)
{
if (pSL->Entries != NULL) {
Free(pSL->Entries);
pSL->Entries = NULL;
pSL->NEntries = 0;
}
}
/*
* Expand
* Private function to double the storage of the SList. Returns FALSE on
* error.
*/
static BOOLEAN SListExpand(PSList pSL)
{
unsigned Temp;
_SListNode *OldEntries; // Keeps a copy of the old array of values.
if (pSL->Entries == NULL) {
// The list is empty; we try to allocate space anyway.
pSL->Entries = Malloc(pSL->MaxEntries * sizeof(_SListNode));
if (pSL->Entries == NULL)
return FALSE;
return TRUE;
}
// The current array of entries is full, so we need to allocate a bigger
// one. The new array has twice the size of the old one.
OldEntries = pSL->Entries;
pSL->Entries = Malloc(pSL->MaxEntries * 2 * sizeof(_SListNode));
if (pSL->Entries == NULL) {
// We failed; we have to return
pSL->Entries = OldEntries;
return FALSE;
}
// Copy the old entries into the new array, starting from the head.
Temp = pSL->MaxEntries - pSL->HeadOffset;
MemCpy(pSL->Entries, OldEntries + pSL->HeadOffset, Temp * sizeof(_SListNode));
MemCpy(pSL->Entries + Temp, OldEntries, pSL->HeadOffset * sizeof(_SListNode));
// Free the old array of entries
Free(OldEntries);
// Set the instance variables
pSL->MaxEntries *= 2;
pSL->HeadOffset = 0;
return TRUE;
}
/*
* Append
* Inserts a value at the end of a list. Returns FALSE on error.
*/
BOOLEAN SListAppend(PSList pSL, unsigned NewKey, void *NewValue)
{
unsigned Temp;
if (pSL->Entries == NULL || pSL->NEntries >= pSL->MaxEntries)
if (!SListExpand(pSL))
return FALSE;
ASSERT(pSL->Entries != NULL);
ASSERT(pSL->NEntries < pSL->MaxEntries);
Temp = pSL->HeadOffset + pSL->NEntries;
if (Temp >= pSL->MaxEntries)
Temp -= pSL->MaxEntries;
pSL->Entries[Temp].Key = NewKey;
pSL->Entries[Temp].Value = NewValue;
pSL->NEntries++;
return TRUE;
}
/*
* Prepend
* Inserts a value at hte beginning of a list. Returns FALSE on error.
*/
BOOLEAN SListPrepend(PSList pSL, unsigned NewKey, void *NewValue)
{
if (pSL->Entries == NULL || pSL->NEntries >= pSL->MaxEntries)
if (!SListExpand(pSL))
return FALSE;
ASSERT(pSL->Entries != NULL);
ASSERT(pSL->NEntries < pSL->MaxEntries);
if (pSL->HeadOffset == 0)
pSL->HeadOffset = pSL->MaxEntries - 1;
else
pSL->HeadOffset--;
pSL->Entries[pSL->HeadOffset].Key = NewKey;
pSL->Entries[pSL->HeadOffset].Value = NewValue;
pSL->NEntries++;
// Reset iteration.
pSL->CurrOffset = 0xFFFFFFFF;
return TRUE;
}
/*
* Remove
* Removes a value from the list, returning the value in *pValue. Returns
* NULL in *pValue if the key does not exist. pValue can be NULL.
*/
void SListRemove(PSList pSL, unsigned Key, void **pValue)
{
unsigned i, Temp, CurItem;
// Find Key in the list.
CurItem = pSL->HeadOffset;
for (i = 0; i < pSL->NEntries; i++) {
if (Key == pSL->Entries[CurItem].Key) {
// Found it; now move the last value in the list into its place.
// (Remember we aren't trying to preserve ordering here.)
if (pValue != NULL)
*pValue = pSL->Entries[CurItem].Value;
// Move the last item in the list into the open place.
Temp = pSL->HeadOffset + pSL->NEntries - 1;
if (Temp >= pSL->MaxEntries)
Temp -= pSL->MaxEntries;
pSL->Entries[CurItem] = pSL->Entries[Temp];
pSL->NEntries--;
pSL->CurrOffset = 0xFFFFFFFF; // Reset iteration.
return;
}
// Advance CurItem, wrapping at end of list.
CurItem++;
if (CurItem == pSL->MaxEntries)
CurItem = 0;
}
if (pValue != NULL)
*pValue = NULL;
}
/*
* RemoveFirst
* Reads and removes the 1st item from the list. Returns the value removed,
* or zero if the list is empty.
*/
void SListRemoveFirst(PSList pSL, unsigned *pKey, void **pValue)
{
if (pSL->NEntries < 1) {
*pKey = 0;
*pValue = NULL;
return;
}
// Reset iteration.
pSL->CurrOffset = 0xFFFFFFFF;
*pKey = (pSL->Entries + pSL->HeadOffset)->Key;
*pValue = (pSL->Entries + pSL->HeadOffset)->Value;
pSL->NEntries--;
pSL->HeadOffset++;
if (pSL->HeadOffset >= pSL->MaxEntries)
pSL->HeadOffset = 0;
}
/*
* GetByKey
* Searches the list and returns in *pValue the value corresponding to the
* given key. If the key is not present, returns FALSE and NULL in
* *pValue. If key is found, reurns nonzero.
*/
BOOLEAN SListGetByKey(PSList pSL, unsigned Key, void **pValue)
{
unsigned i, Temp;
_SListNode *pItem;
// Find Key in the list.
pItem = pSL->Entries + pSL->HeadOffset;
for (i = 0; i < pSL->NEntries; i++) {
if (Key == pItem->Key) {
// Found it; set *pValue and return.
*pValue = pItem->Value;
return TRUE;
}
// Advance pItem, wrapping at end of list.
pItem++;
if ((unsigned)(pItem - pSL->Entries) >= pSL->MaxEntries)
pItem = pSL->Entries;
}
*pValue = NULL;
return FALSE;
}
/*
* RemoveLast
* Removes the value at the end of the lst and returns it. If the list is
* empty, returns zero.
*/
void SListRemoveLast(PSList pSL, unsigned *pKey, void **pValue)
{
unsigned Temp;
if (pSL->NEntries < 1) {
*pKey = 0;
*pValue = NULL;
return;
}
// Reset iteration.
pSL->CurrOffset = 0xFFFFFFFF;
pSL->NEntries--;
Temp = pSL->HeadOffset + pSL->NEntries - 1;
if (Temp >= pSL->MaxEntries)
Temp -= pSL->MaxEntries;
*pKey = (pSL->Entries + Temp)->Key;
*pValue = (pSL->Entries + Temp)->Value;
}
/*
* Iterate
* Iterates through the items of a list. CurrOffset is used as a current
* iteration pointer, so this function can be called in a loop. Returns
* FALSE if the iteration has completed, nonzero if the iteration continues
* (and *pKey is valid).
*/
BOOLEAN SListIterate(PSList pSL, unsigned *pKey, void **pValue)
{
unsigned Temp;
if (pSL->NEntries < 1)
return FALSE;
if (pSL->CurrOffset == 0xFFFFFFFF) {
// Start from the beginning.
pSL->CurrOffset = 0;
}
else {
pSL->CurrOffset++;
if (pSL->CurrOffset >= pSL->NEntries) {
// Reset the iterator.
pSL->CurrOffset = 0xFFFFFFFF;
return FALSE;
}
}
Temp = pSL->CurrOffset + pSL->HeadOffset;
if (Temp >= pSL->MaxEntries)
Temp -= pSL->MaxEntries;
*pKey = pSL->Entries[Temp].Key;
*pValue = pSL->Entries[Temp].Value;
return TRUE;
}