/*===========================================================================
 *
 * DblList.H - Dave Humphrey (uesp@m0use.net), 1 December 2000
 *
 *=========================================================================*/
#ifndef __DBLLIST_H
#define __DBLLIST_H

	/* Required Includes */
#include "genutil.h"


/*===========================================================================
 *
 * Begin Defines
 *
 *=========================================================================*/

	/* Program Identification */
  #define DBLLIST_NAME    "DBLLIST.CPP"
  #define DBLLIST_VERSION "1.0"
  #define DBLLIST_AUTHOR  "Dave Humphrey"
  #define DBLLIST_DATE    "20 May 1998"

	/* Custom error codes */
  #define ERRDBLLIST_NOCURRENT		501
  #define ERRDBLLIST_NOCOMPAREPROC	502

/*===========================================================================
 *		End of Defines
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Type and Structure Definitions
 *
 *=========================================================================*/

	/* Used for sorting items in the linked list class */
  typedef int (*pDBLLIST_COMPARE_PROC) (const void*, const void*);

/*===========================================================================
 *		End of Type and Structure Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Class CDblEntry Definition
 *
 * Defines one node in the doubly linked list.
 *
 *=========================================================================*/
class CDblEntry { 
  friend class CDblList;

  /*---------- Begin Protected Class Members -----------------------*/
protected:
  CDblEntry* pNext;		/* Points to next members in list */
  CDblEntry* pPrev;

public:
  void*      pBody;		/* The node data */
  uint	     Size;		/* Size, in bytes of the data */


  /*---------- Begin Public Class Methods ----------------------------*/
public:

	/* Class Constructor and Destructor */
  CDblEntry (void);
  ~CDblEntry (void);

	/* Create a new body for the list node */
  void CreateBody (const void* pData, const uint NewSize);

	/* Get class members */
  void*      GetBody (void) { return (pBody); }
  uint       GetSize (void) { return (Size); }
  CDblEntry* GetNext (void) { return (pNext); }
  CDblEntry* GetPrev (void) { return (pPrev); }

	/* Set class members */
  void SetSize (const uint NewSize) { Size = NewSize; }
  void SetNext (CDblEntry* pPtr) { pNext = pPtr; }
  void SetPrev (CDblEntry* pPtr) { pPrev = pPtr; }

 };
/*===========================================================================
 *		End of Class CDblEntry Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Class CDblList Definition
 *
 * Holds the definition for a doubly-linked list class.
 *
 *=========================================================================*/
class CDblList {
  friend boolean Sort (void);

  /*---------- Begin Protected Class Members -----------------------*/
protected:
  CDblEntry* pHead;	/* Absolute Start and end of doubly linked list */
  CDblEntry* pTail;
  CDblEntry* pCurrent;	/* The current pointer to item in list */
  CDblEntry* pHold;	/* Temp pointer used for creation only */

  uint       NumEntries;	/* Number of entries in the list */

	/* Used to compare data for sorting the list */
  pDBLLIST_COMPARE_PROC CompareProc;


  /*---------- Begin Protected Class Methods -----------------------*/
protected:

	/* Add custom class errors */
  static boolean AddClassErrors (void);

	/* Creates new list entry */
  virtual CDblEntry *Create (const void* pData, const uint Size);

	/* Find a node to add a new sorted entry */
  CDblEntry* FindSortNode (const void* pData);


  /*---------- Begin Public Class Methods ----------------------------*/
public:

	/* Class Constructors/Destructor */
  CDblList (void);
  virtual ~CDblList (void) { Destroy(); }

	/* Adds a List Element to Current Position in the Doubly Linked List */
  virtual void* AddCurrent (const void* pData, const uint Size);
  virtual void* Insert     (const void* pData, const uint Size) { return AddCurrent(pData, Size); }

	/* Adds new value into the list somewhere */
  virtual void* AddHead (const void* pData, const uint Size);
  virtual void* AddTail (const void* pData, const uint Size);
  virtual void* Add     (const void* pData, const uint Size) { return AddTail(pData, Size); }
  virtual void* AddSort (const void* pData, const uint Size);

	/* Adds a list to the end of the current one */
  virtual void AddList (CDblList& NewList);

	/* Clears the list without deleting the nodes */
  void ClearList (void);

	/* Counts the Number of Elements in the List From Head to Tail */
  uint Count (void) { return (NumEntries); }

	/* Deletes the Current Entry, if any. Returns TRUE if successful */
  boolean DeleteEntry (void);

	/* Deletes the entire list */
  void DeleteList (void);
  void Destroy    (void) { DeleteList(); }

	/* Returns the Value of the current pointer body */
  virtual void* GetCurrent (void) { return (pCurrent ? pCurrent->GetBody() : NULL); }

  CDblEntry* GetHead       (void) { return (pHead); }
  CDblEntry* GetTail       (void) { return (pTail); }
  CDblEntry* GetCurrentPtr (void) { return (pCurrent); }
  
	/* Returns the head/tail of list */
  virtual void* GotoHead (void);
  virtual void* GotoTail (void);

	/* Returns the next/prev value in list */
  virtual void* Next (void) { if (pCurrent) pCurrent = pCurrent->GetNext();  return (GetCurrent()); }
  virtual void* Prev (void) { if (pCurrent) pCurrent = pCurrent->GetPrev();  return (GetCurrent()); }

	/* Adds an Item to the end of the current one */
  void MoveEntry (CDblList& NewList);

	/* Removes the current node without deleting it */
  void RemoveCurrent (void);

	/* Set the function used for sorting the list */
  void SetCompareProc (pDBLLIST_COMPARE_PROC Proc) { CompareProc = Proc; }

	/* Sorts the list using the current compare proc */
  boolean Sort (void);

 };
/*===========================================================================
 *		End of Class CDblList Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Template Class CDblListTemplate Definition
 *
 * Defines a template doubly linked list with a custom user defined type.
 *
 *=========================================================================*/
template <class UserClass> class CDblListTemplate : virtual public CDblList {


  /*---------- Begin Protected Class Methods -----------------------*/
protected:

	/* Creates new list entry */
  CDblEntry *Create (const void* pData, const uint Size);


  /*---------- Begin Public Class Methods ----------------------------*/
public:

	/* Adds a new class object to list */
  boolean AddCurrent (const UserClass& Data) { return ((CDblList::AddCurrent((void *)&Data, sizeof(UserClass)) == NULL) ? FALSE : TRUE); }
  boolean Insert     (const UserClass& Data) { return AddCurrent(Data); }
  boolean AddHead    (const UserClass& Data) { return ((CDblList::AddHead((void *)&Data, (uint) sizeof(UserClass)) == NULL) ? FALSE : TRUE); }
  boolean AddTail    (const UserClass& Data) { return ((CDblList::AddTail((void *)&Data, (uint) sizeof(UserClass)) == NULL) ? FALSE : TRUE); }
  boolean Add        (const UserClass& Data) { return ((CDblList::AddTail((void *)&Data, (uint) sizeof(UserClass)) == NULL) ? FALSE : TRUE); } 
  boolean AddSort    (const UserClass& Data) { return ((CDblList::AddSort((void *)&Data, (uint) sizeof(UserClass)) == NULL) ? FALSE : TRUE); } 
  UserClass* AddTail     (void)		         { return (UserClass *) CDblList::AddTail((void *)NULL, (uint) sizeof(UserClass)); }
  UserClass* AddTailData (const UserClass& Data) { return (UserClass *) CDblList::AddTail((void *)&Data, (uint) sizeof(UserClass)); }

  	/* Get class data  */
  UserClass* GetCurrentData (void) { return ((UserClass*) CDblList::GetCurrent()); }
  UserClass* GetHeadData    (void) { return ((UserClass*) CDblList::GotoHead()); }
  UserClass* GetTailData    (void) { return ((UserClass*) CDblList::GotoTail()); }

	/* Move the current pointer around the list */
  UserClass* GetNext (void) { return ((UserClass*) CDblList::Next()); }
  UserClass* GetPrev (void) { return ((UserClass*) CDblList::Prev()); }

  UserClass* operator++ (int) { return ((UserClass*) CDblList::Next()); }
  UserClass* operator-- (int) { return ((UserClass*) CDblList::Prev()); }
  
 }; 
/*===========================================================================
 *		End of Class CDblListTemplate Definition
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDblList::Create()"
/*===========================================================================
 *
 * Class CDblList Method - CDblEntry* Create (pData, Size);
 *
 * Protected class method which creates a new linked list node with the
 * given size and data.  Does not rearrange the list.
 *
 *=========================================================================*/
template <class UserClass>
CDblEntry* CDblListTemplate<UserClass>::Create (const void *pData, const uint Size) {

	/* Attempt to create new list pointer */
  CreatePointer(pHold, CDblEntry);

	/* Create a UserClass object in the new node body */
  CreatePointer(pHold->pBody, UserClass);

	/* Copy the class values, assuming the class has an overloaded
	 * copy constructor defined */
  if (pData != NULL) {
    *((UserClass *)pHold->pBody) = *((UserClass*)pData);
   }
	
	/* Add one more entry to the total number */
  NumEntries++;
  return (pHold);
 }
/*===========================================================================
 *		End of Class Method CDblList::Create()
 *=========================================================================*/


#endif
/*===========================================================================
 *		End of file DblList.H
 *=========================================================================*/