|
|
/* (C) 1997-1999 Microsoft Corp.
* * file : SList.c * authors : Christos Tsollis, Erik Mavrinac * * description: Implementation of list described in SList.h. */
#include "precomp.h"
#pragma hdrstop
#include "mcsimpl.h"
void SListInit(PSList pSL, unsigned NItems) { // Initialize the private member variables. Use preallocated array for
// initial node array.
pSL->Hdr.NEntries = 0; pSL->Hdr.MaxEntries = SListDefaultNumEntries; pSL->Hdr.HeadOffset = 0; pSL->Hdr.CurrOffset = 0xFFFFFFFF; pSL->Hdr.Entries = pSL->InitialList; }
void SListDestroy(PSList pSL) { // Only free if we have a pool-allocated array.
if (pSL->Hdr.Entries != pSL->InitialList) { ExFreePool(pSL->Hdr.Entries); pSL->Hdr.Entries = pSL->InitialList; pSL->Hdr.MaxEntries = SListDefaultNumEntries; } pSL->Hdr.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.
ASSERT(pSL->Hdr.Entries != NULL);
// 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->Hdr.Entries; pSL->Hdr.Entries = ExAllocatePoolWithTag(PagedPool, pSL->Hdr.MaxEntries * 2 * sizeof(_SListNode), MCS_POOL_TAG); if (pSL->Hdr.Entries == NULL) { // We failed; we have to return
pSL->Hdr.Entries = OldEntries; return FALSE; }
// Copy the old entries into the new array, starting from the head.
Temp = pSL->Hdr.MaxEntries - pSL->Hdr.HeadOffset; memcpy(pSL->Hdr.Entries, OldEntries + pSL->Hdr.HeadOffset, Temp * sizeof(_SListNode)); memcpy(pSL->Hdr.Entries + Temp, OldEntries, pSL->Hdr.HeadOffset * sizeof(_SListNode));
// Free the old array of entries if not the initial array.
if (OldEntries != pSL->InitialList) ExFreePool(OldEntries);
// Set the instance variables
pSL->Hdr.MaxEntries *= 2; pSL->Hdr.HeadOffset = 0; return TRUE; }
/*
* Append * Inserts a value at the end of a list. Returns FALSE on error. */ BOOLEAN SListAppend(PSList pSL, UINT_PTR NewKey, void *NewValue) { unsigned Temp;
if (pSL->Hdr.NEntries < pSL->Hdr.MaxEntries || (pSL->Hdr.NEntries >= pSL->Hdr.MaxEntries && SListExpand(pSL))) { Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries; if (Temp >= pSL->Hdr.MaxEntries) Temp -= pSL->Hdr.MaxEntries; pSL->Hdr.Entries[Temp].Key = NewKey; pSL->Hdr.Entries[Temp].Value = NewValue; pSL->Hdr.NEntries++;
return TRUE; } else { return FALSE; } }
#ifdef NotUsed
/*
* Prepend * Inserts a value at the beginning of a list. Returns FALSE on error. */ BOOLEAN SListPrepend(PSList pSL, UINT_PTR NewKey, void *NewValue) { if (pSL->Hdr.NEntries >= pSL->Hdr.MaxEntries) if (!SListExpand(pSL)) return FALSE;
ASSERT(pSL->Hdr.Entries != NULL); ASSERT(pSL->Hdr.NEntries < pSL->Hdr.MaxEntries);
if (pSL->Hdr.HeadOffset == 0) pSL->Hdr.HeadOffset = pSL->Hdr.MaxEntries - 1; else pSL->Hdr.HeadOffset--; pSL->Hdr.Entries[pSL->Hdr.HeadOffset].Key = NewKey; pSL->Hdr.Entries[pSL->Hdr.HeadOffset].Value = NewValue; pSL->Hdr.NEntries++;
// Reset iteration.
pSL->Hdr.CurrOffset = 0xFFFFFFFF;
return TRUE; } #endif // NotUsed
/*
* 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, UINT_PTR Key, void **pValue) { unsigned i, Temp, CurItem;
// Find Key in the list.
CurItem = pSL->Hdr.HeadOffset; for (i = 0; i < pSL->Hdr.NEntries; i++) { if (Key == pSL->Hdr.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->Hdr.Entries[CurItem].Value;
// Move the last item in the list into the open place.
Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries - 1; if (Temp >= pSL->Hdr.MaxEntries) Temp -= pSL->Hdr.MaxEntries; pSL->Hdr.Entries[CurItem] = pSL->Hdr.Entries[Temp];
pSL->Hdr.NEntries--; pSL->Hdr.CurrOffset = 0xFFFFFFFF; // Reset iteration.
return; }
// Advance CurItem, wrapping at end of list.
CurItem++; if (CurItem == pSL->Hdr.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, UINT_PTR *pKey, void **pValue) { if (pSL->Hdr.NEntries < 1) { *pKey = 0; *pValue = NULL; return; }
// Reset iteration.
pSL->Hdr.CurrOffset = 0xFFFFFFFF; *pKey = (pSL->Hdr.Entries + pSL->Hdr.HeadOffset)->Key; *pValue = (pSL->Hdr.Entries + pSL->Hdr.HeadOffset)->Value; pSL->Hdr.NEntries--; pSL->Hdr.HeadOffset++; if (pSL->Hdr.HeadOffset >= pSL->Hdr.MaxEntries) pSL->Hdr.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, UINT_PTR Key, void **pValue) { unsigned i, Temp; _SListNode *pItem;
// Find Key in the list.
pItem = pSL->Hdr.Entries + pSL->Hdr.HeadOffset; for (i = 0; i < pSL->Hdr.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->Hdr.Entries) >= pSL->Hdr.MaxEntries) pItem = pSL->Hdr.Entries; }
*pValue = NULL; return FALSE; }
#ifdef NotUsed
/*
* RemoveLast * Removes the value at the end of the lst and returns it. If the list is * empty, returns zero. */ void SListRemoveLast(PSList pSL, UINT_PTR *pKey, void **pValue) { unsigned Temp;
if (pSL->Hdr.NEntries < 1) { *pKey = 0; *pValue = NULL; return; }
// Reset iteration.
pSL->Hdr.CurrOffset = 0xFFFFFFFF; pSL->Hdr.NEntries--; Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries - 1; if (Temp >= pSL->Hdr.MaxEntries) Temp -= pSL->Hdr.MaxEntries;
*pKey = (pSL->Hdr.Entries + Temp)->Key; *pValue = (pSL->Hdr.Entries + Temp)->Value; } #endif // NotUsed
/*
* 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, UINT_PTR *pKey, void **pValue) { unsigned Temp;
if (pSL->Hdr.NEntries >= 1) { if (pSL->Hdr.CurrOffset != 0xFFFFFFFF) { pSL->Hdr.CurrOffset++; if (pSL->Hdr.CurrOffset >= pSL->Hdr.NEntries) { // Reset the iterator.
pSL->Hdr.CurrOffset = 0xFFFFFFFF; return FALSE; } } else { // Start from the beginning.
pSL->Hdr.CurrOffset = 0; }
Temp = pSL->Hdr.CurrOffset + pSL->Hdr.HeadOffset; if (Temp >= pSL->Hdr.MaxEntries) Temp -= pSL->Hdr.MaxEntries;
*pKey = pSL->Hdr.Entries[Temp].Key; *pValue = pSL->Hdr.Entries[Temp].Value; return TRUE; }
return FALSE; }
|