|
|
/* (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; }
|