|
|
#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_T123PSTN);
/* slist.cpp
* * Copyright (c) 1996 by Microsoft Corporation * * Written by: Christos Tsollis * * Revisions: * * Abstract: * * This is the implementation of a linked list data structure. * */
#define MyMalloc(size) LocalAlloc (LMEM_FIXED, (size))
#define MyFree(ptr) LocalFree ((HLOCAL) (ptr))
#define Max(a,b) (((a) > (b)) ? (a) : (b))
/* Function: Constructor
* * Parameters: * ltype: List type * num_of_items: Size of the list's cache * * Return value: * None */
SListClass::SListClass (DWORD num_of_items) {
MaxEntries = Max (num_of_items, DEFAULT_NUMBER_OF_ITEMS);
// Allocate the block of items (which, hopefully, will be the last one)
Entries = (DWORD_PTR *) MyMalloc (MaxEntries * sizeof (DWORD_PTR));
// Initialize the private member variables
NumOfEntries = 0; HeadOffset = 0; CurrOffset = 0xFFFFFFFF;
}
/* Function: Destructor
* * Parameters: * None. * * Return value: * None * */
SListClass::~SListClass (void) { if (Entries != NULL) MyFree (Entries); }
/* Function: Expand
* This private member function, expands the storage array of a list. It doubles its size. * * Parameters: * None. * * Return value: * TRUE, if the expansion was successful. FALSE, otherwise. * */
BOOL SListClass::Expand (void) { DWORD_PTR *OldEntries; // Keeps a copy of the old array of values.
DWORD dwTemp; // Temporary DWORD value
if (Entries == NULL) { // the list is empty; we try to allocate space anyway.
Entries = (DWORD_PTR *) MyMalloc (MaxEntries * sizeof (DWORD_PTR)); if (Entries == NULL) return FALSE; return TRUE; } ASSERT (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 = Entries; Entries = (DWORD_PTR *) MyMalloc ((MaxEntries << 1) * sizeof (DWORD_PTR)); if (Entries == NULL) { // we failed; we have to return
Entries = OldEntries; return FALSE; }
// copy the old entries into the new array, starting from the beginning
dwTemp = MaxEntries - HeadOffset; memcpy ((void *) Entries, (void *) (OldEntries + HeadOffset), dwTemp * sizeof (DWORD)); memcpy ((void *) (Entries + dwTemp), (void *) OldEntries, HeadOffset * sizeof (DWORD));
// Free the old array of entries
MyFree (OldEntries);
// Set the instance variables
MaxEntries <<= 1; HeadOffset = 0; return TRUE; }
/* Function: append
* Inserts a value at the end of a list. * * Parameters: * new_key: The new value that has to be inserted in the list * * Return value: * None. * */
void SListClass::append (DWORD_PTR new_key) { DWORD_PTR dwTemp;
if (Entries == NULL || NumOfEntries >= MaxEntries) if (! Expand ()) return;
ASSERT (Entries != NULL); ASSERT (NumOfEntries < MaxEntries);
dwTemp = HeadOffset + (NumOfEntries++); if (dwTemp >= MaxEntries) dwTemp -= MaxEntries; Entries[dwTemp] = new_key; }
/* Function: prepend
* Inserts a value at the beginning of a list. * * Parameters: * new_key: The new value that has to be inserted in the list * * Return value: * None. * */
void SListClass::prepend (DWORD_PTR new_key) { if (Entries == NULL || NumOfEntries >= MaxEntries) if (! Expand ()) return;
ASSERT (Entries != NULL); ASSERT (NumOfEntries < MaxEntries);
NumOfEntries++; if (HeadOffset == 0) HeadOffset = MaxEntries - 1; else HeadOffset--; Entries[HeadOffset] = new_key; }
/* Function: find
* Looks up a value in a DWORD_LIST list. * * Parameters: * Key: The value to look up * * Return value: * TRUE, if "Key" is found in the list. FALSE, otherwise. * */
BOOL SListClass::find (DWORD_PTR Key) { DWORD i; DWORD_PTR *pItem; // Goes through the items in the list.
for (i = 0, pItem = Entries + HeadOffset; i < NumOfEntries; i++) { if (Key == *pItem) return TRUE;
// Advance the "pItem" pointer
if ((DWORD) (++pItem - Entries) >= MaxEntries) pItem = Entries; } return FALSE; }
/* Function: read
* Reads an item from the list. The list item is not removed from the list. * * Parameters: * index: Index of the item to be read. 0 is the index of the 1st list item. * NumOfEntries - 1 is the last valid index. * * Return value: * The value at the index-th entry in the list. If the index is invalid, 0. * */
DWORD_PTR SListClass::read (DWORD index) { DWORD dwTemp;
if (index >= NumOfEntries) return 0;
dwTemp = HeadOffset + index; if (dwTemp >= MaxEntries) dwTemp -= MaxEntries;
return (Entries[dwTemp]); }
/* Function: remove
* Removes a value from the list * * Parameters: * Key: The value that has to be removed from the DWORD_LIST list * * Return value: * None. * */
void SListClass::remove (DWORD_PTR Key) { DWORD i, dwTemp; DWORD_PTR *pItem; // Goes through the list items
for (i = 0, pItem = Entries + HeadOffset; i < NumOfEntries; i++) { if (Key == *pItem) { // we found the "Key"; to remove it, we move the last value into its place.
dwTemp = HeadOffset + (--NumOfEntries); if (dwTemp >= MaxEntries) dwTemp -= MaxEntries; *pItem = Entries[dwTemp]; return; }
// Advance the "pItem" pointer
if ((DWORD) (++pItem - Entries) >= MaxEntries) pItem = Entries; } }
/* Function: get
* Reads and removes the 1st item from the list. * * Parameters: * None. * * Return value: * The value at the 1st entry in the list. If the list is empty, 0. * */
DWORD_PTR SListClass::get (void) { DWORD_PTR return_value = 0;
if (NumOfEntries > 0) { return_value = Entries[HeadOffset]; NumOfEntries--; if (++HeadOffset >= MaxEntries) HeadOffset = 0; } return return_value; }
/* Function: removeLast
* Reads and removes the last item from the list * * Parameters: * None. * * Return value: * The value at the last entry in the list. If the list is empty, 0. * */
DWORD_PTR SListClass::removeLast (void) { DWORD_PTR return_value = 0; DWORD dwTemp;
if (NumOfEntries > 0) { dwTemp = HeadOffset + (--NumOfEntries); if (dwTemp >= MaxEntries) dwTemp -= MaxEntries; return_value = Entries[dwTemp]; } return return_value; }
/* Function: iterate
* Iterates through the items of a list. It remembers where it has * stopped during the last call and starts from there. * * Parameters * pKey: Pointer to DWORD or unsigned short value to receive the next item's value. * It can be NULL. * * Return value: * FALSE, when we reach the end of the dictionary * TRUE, otherwise. Then, *pKey is valid * */
BOOL SListClass::iterate (DWORD_PTR *pKey) { DWORD dwTemp;
if (NumOfEntries <= 0) return FALSE;
if (CurrOffset == 0xFFFFFFFF) { // start from the beginning
CurrOffset = 0; } else { if (++CurrOffset >= NumOfEntries) { // reset the iterator
CurrOffset = 0xFFFFFFFF; return FALSE; } }
dwTemp = CurrOffset + HeadOffset; if (dwTemp >= MaxEntries) dwTemp -= MaxEntries;
*pKey = Entries[dwTemp]; return TRUE;
}
|