/*++

  Copyright 1996 - 2000 Microsoft Corporation.

  Copyright (c) 1995 Intel Corp
  
  File Name:
  
    nideque.h
  
  Abstract:
  
    Implements Deque structures.  These are double linked lists  that
    can place and remove data from the beginning and end. This file
    also contains an iterator for Deques.  Important to notice is that
    these are non-intrusive deques.  Meaning the use of these classes
    does not need to insert pointers into there classes to use these.
  
--*/

#ifndef _NIDEQUE_H_
#define _NIDEQUE_H_

#include "nowarn.h"  /* turn off benign warnings */
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
#endif
#include <windows.h>
#include "nowarn.h"  /* some warnings may have been turned back on */
#include "huerror.h"

template<class T> class NIDeque_c;
template<class T> class NIDequeIter_c;

// Class Name:     NILNode_c
// Purpose:  Simply holds data and pointer to form a double linked
// list. 
// Context:  Can be used anywhere.
template<class T> class NILNode_c {
    friend class NIDeque_c<T>;
    friend class NIDequeIter_c<T>;

    private:
        T           Data;
        NILNode_c   *Next,
                    *Back;

    public:
        NILNode_c();
};

template<class T> NILNode_c<T>::NILNode_c()
{
    // Make sure the members are correctly initialized.
    Next = NULL;
    Back = NULL;
} // NILNode_c::NILNode_c



// Class Name:     NIDeque_c   
// Purpose:  Non-intrusize deque                                       
// Context:  Can be used anywhere.
template<class T> class NIDeque_c {
    friend class NIDequeIter_c<T>;

    private:
      NILNode_c<T>  *Root,
                    *Tail;   
    public: 
                NIDeque_c();
            ~NIDeque_c();
        BOOL    RemoveFromFront(T &data);    
        BOOL    RemoveFromBack(T &data);
        BOOL    InsertIntoFront(T data);
        BOOL    InsertIntoBack(T data);
        BOOL    GetFromFront(T &data);
    BOOL    GetFromBack(T &data);
    BOOL    IsEmpty();
};




/*++
  
  NIDeque_c::NIDeque_c()
  
  Function Description:
  
      Constructor
  
  Arguments:
  
      None.
  
  Return Value:
  
      None.
  
--*/                                            
template<class T> NIDeque_c<T>::NIDeque_c()
{
    Root = NULL;
    Tail = NULL;
} // End of NINIDeque_c::NIDeque_c 





/*++
  
  NIDeque_c::~NIDeque_c()
  
  Function Description:
  
      Destructor
  
  Arguments:
  
      None.
  
  Return Value:
  
      None.
  
--*/
template<class T> NIDeque_c<T>::~NIDeque_c()
{                                            
    NILNode_c<T>    *bptr    = NULL,
                    *cptr    = NULL;

    for(bptr=NULL,cptr=Root;cptr;bptr=cptr,cptr=cptr->Next){  
        delete bptr;
    }                                           
    delete bptr;
}                




/*++
  
  NIDeque_c::InsertIntoFront()
  
  Function Description:
  
      Inserts a piece of data onto the linked list.
  
  Arguments:
  
      Data -- Data to put on the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::InsertIntoFront(T Data)
{       
    NILNode_c<T>    *nptr    = NULL;

    /*  If the list contains something then move the root pointer down.
    //  Otherwise, put this new object on the root.
    */
    nptr = new NILNode_c<T>;
    if(!nptr){
         HUSetLastError(ALLOCERROR);
         return FALSE;
    }                 

    nptr->Data = Data;

    if(Root){
        nptr->Next = Root;
        Root->Back = nptr;
        Root = nptr;
    }else{    
        Root = nptr;
        Tail = nptr;
    }
    return TRUE;
} // End of NIDeque_c::InsFront




/*++
  
  NIDeque_c::RemoveFromFront()
  
  Function Description:
  
      Removes a piece of data from the front of the linked list.
  
  Arguments:
  
      Data -- Data to be taken off of the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::RemoveFromFront(T &Data)
{           
    NILNode_c<T>    *nptr    = NULL;   
    
    if(Root){                 
        nptr = Root;
        Root = Root->Next;
        if(Root){
            Root->Back = NULL; 
        }else{
            Tail = NULL;
        }
        nptr->Next = NULL;
        nptr->Back = NULL; 
        Data = nptr->Data;
        delete nptr;
        return TRUE;
    }else{
        Data = NULL;
        return FALSE;
    }
} // End of NIDeque_c::RemFront



                                          
/*++
  
  NIDeque_c::InsertIntoBack()
  
  Function Description:
  
      Inserts a piece of data onto the back of the linked list.
  
  Arguments:
  
      Data -- Data to be taken off of the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::InsertIntoBack(T Data)
{       
    NILNode_c<T>    *nptr    = NULL;

    nptr = new NILNode_c<T>;
    if(!nptr){
        HUSetLastError(ALLOCERROR);
        return FALSE;
    }    

    nptr->Data = Data;

    if(Root){
        nptr->Back = Tail;
        Tail->Next = nptr;
        Tail = nptr;
    }else{    
        Root = nptr;
        Tail = nptr;
    }
    return TRUE;
} // End of NIDeque_c::InsBack




/*++
  
  NIDeque_c::RemoveFromBack()
  
  Function Description:
  
      Removes a piece of data from the back of the linked list.
  
  Arguments:
  
      Data -- Data to be taken off of the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::RemoveFromBack(T &Data)
{
    NILNode_c<T>    *nptr    = NULL;

    if(Tail){
        nptr = Tail;
        Tail = Tail->Back;
        if(Tail){
            Tail->Next = NULL;
        }else{
        Root = NULL;
    }
        nptr->Next = NULL;
        nptr->Back = NULL;
        Data = nptr->Data;
        delete nptr;
        return TRUE;
    }else{
        Data = NULL;
        return FALSE;
    }
}




/*++
  
  NIDeque_c::GetFromFront()
  
  Function Description:
  
      Gets a piece of data from the front of the linked list.
  
  Arguments:
  
      Data -- Data to be taken off of the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::GetFromFront(T &Data)
{           
    NILNode_c<T>    *nptr    = NULL;   
    
    if(Root){                 
        Data = Root->Data;
        return TRUE;
    }else{
        Data = NULL;
        return FALSE;
    }
} // End of NIDeque_c::GetFromFront




/*++
  
  NIDeque_c::GetFromBack()
  
  Function Description:
  
      Gets a piece of data from the back of the linked list.
  
  Arguments:
  
      Data -- Data to be taken off of the linked list.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::GetFromBack(T &Data)
{           
    NILNode_c<T>    *nptr    = NULL;   
    
    if(Tail){                 
        Data = Tail->Data;
        return TRUE;
    }else{
        Data = NULL;
        return FALSE;
    }
} // End of NIDeque_c::RemFront




/*++
  
  NIDeque_c::IsEmpty()
  
  Function Description:
  
      Determines whether a deques is empty
  
  Arguments:
  
      None.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDeque_c<T>::IsEmpty()
{           
    
    if(Root){               
        return FALSE;
    }else{
        return TRUE;
    }
} // End of NIDeque_c::IsEmpty


// Name:     NIDequeIter_c
// Purpose:  An iterator for the Deque_c class.                        
// Context:  Of course only with Deque_c
template<class T> class NIDequeIter_c {
    private:
        NIDeque_c<T>  *NIDeque;
        NILNode_c<T>  *Current;

    private:
        void    RemoveData(NILNode_c<T> *cptr,T &data);

    protected: // Derived class interface
    inline NILNode_c<T> *GetCurrent();
    inline NIDeque_c<T> *GetNIDeque();

    public: 
                NIDequeIter_c();
                NIDequeIter_c(NIDeque_c<T> &ANIDeque);
                ~NIDequeIter_c();
        BOOL    Initialize(NIDeque_c<T> &ANIDeque);
        BOOL    First(T &data);
        BOOL    Next(T &data);
        BOOL    Last(T &data);
        BOOL    Back(T &data);
        BOOL    Remove(T &data);
        BOOL    Replace(T &src,T chg);
};

//
// Private members                                             
//


/*++
  
  NIDequeIter_c::RemoveData()
  
  Function Description:
  
      To remove all of the data from the linked list.
  
  Arguments:
  
      cptr -- Current pointer in the linked list.
      
      ret_data -- Return the data before deleting.
  
  Return Value:
  
      None.
  
--*/
template<class T> void NIDequeIter_c<T>::RemoveData(NILNode_c<T> *cptr,
                                                    T &ret_data)
{
    NILNode_c<T>  *bptr    = NULL,
                  *nptr    = NULL,
                  *fptr    = NULL;

    if(Current == cptr){
        Current = cptr->Next;
    }
    fptr = cptr;
    bptr = cptr->Back;
    nptr = cptr->Next;
    if(bptr != NULL){
        bptr->Next = nptr;
    }                      
    if(nptr != NULL){
        nptr->Back = bptr;
    }
    if(fptr == NIDeque->Root){
        NIDeque->Root = nptr;
    }          
    if(fptr == NIDeque->Tail){
        NIDeque->Tail = bptr;
    }                                             
    if(ret_data){
        ret_data = fptr->Data;
    }
    delete fptr;
} // End of NINIDeque_c::RemoveData


//
// Public members                                             
//


/*++
  
  NIDequeIter_c::NIDequeIter_c()
  
  Function Description:
  
      Constructor.
  
  Arguments:
  
      ANIDeque -- The deque to iterate over.
  
  Return Value:
  
      None.
  
--*/
template<class T> NIDequeIter_c<T>::NIDequeIter_c(NIDeque_c<T> &ANIDeque) 
{
    NIDeque = &ANIDeque;
    Current = NULL;
}



template<class T> NIDequeIter_c<T>::NIDequeIter_c() 
{
    NIDeque = NULL;
    Current = NULL;
}




/*++
  
  NIDequeIter_c::~NIDequeIter_c()
  
  Function Description:
  
      Destructor.
  
  Arguments:
  
      None.
  
  Return Value:
  
      None.
  
--*/
template<class T> NIDequeIter_c<T>::~NIDequeIter_c()
{
}



/*++
  
  NIDequeIter_c::Initialize()
  
  Function Description:
  
      Initializes the iterator.
  
  Arguments:
  
      ANIDeque -> The deque to iterate over.
  
  Return Value:
  
      None.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Initialize(NIDeque_c<T> &ANIDeque) 
{
    NIDeque = &ANIDeque;
    Current = NULL;
    return TRUE;
}




/*++
  
  NIDequeIter_c::First()
  
  Function Description:
  
      Returns the First data in the linked list.  This primes the
      current pointer so that next time the Next method is used to get
      more linked list data.
  
  Arguments:
  
      data -- The data from the linked list.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::First(T &Data)
{
    Current = NIDeque->Root;
    if(Current != NULL){
        Data = Current->Data;
        return TRUE;
    }else{
        return FALSE;
    }
} // End of NIDeque_c::First




/*++
  
  NIDequeIter_c::Next()
  
  Function Description:
  
      Returns the Next data in the linked list.
  
  Arguments:
  
      data -- The data from the linked list.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Next(T &Data)
{
    if(Current){
        Current = Current->Next;
        if(Current){
            Data = Current->Data;
            return TRUE;
        }
    } 
    Data = NULL;              
    return FALSE;
} // End of NIDeque_c::Next




/*++
  
  NIDequeIter_c::Last()
  
  Function Description:
  
      Returns the Last data in the linked list.
  
  Arguments:
  
      data -- The data from the linked list.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Last(T &Data)
{
    Current = NIDeque->Tail;
    if(Current != NULL){
        Data = Current->Data;
        return TRUE;
    }else{
        return FALSE;
    }
} // End of NIDeque_c::First




/*++
  
  NIDequeIter_c::Back()
  
  Function Description:
  
      Returns the previous data in the linked list.
  
  Arguments:
  
      data -- The data from the linked list.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Back(T &Data)
{
    if(Current && (Current = Current->Back)){
        Data = Current->Data;
        return TRUE;
    }else{ 
        Data = NULL;              
        return FALSE;
    }
} // End of NIDeque_c::Next




/*++
  
  NIDequeIter_c::Replace()
  
  Function Description:
  
      Replaces src by chg.
  
  Arguments:
  
      src -- Data to search for.

      chg -- The new data.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Replace(T &src,T chg)
{
    NILNode_c<T> *cptr    = NULL; 
    
    if(Current != NULL){
        src = Current->Data;
        Current->Data = chg;
        return TRUE;
    }                
    return FALSE;
} // End of NIDeque_c::Replace




/*++
  
  NIDequeIter_c::Remove()
  
  Function Description:
  
      Removes whatever the current pointer is pointing at.
  
  Arguments:
  
      data -- Data removed.
  
  Return Value:
  
      TRUE -- If data is valid.

      FALSE -- If data is not valid.
  
--*/
template<class T> BOOL NIDequeIter_c<T>::Remove(T &data)
{            
    NILNode_c<T>    *cptr   = NULL;
    T               *vdata  = NULL;
                            
    if(Current != NULL){
        RemoveData(Current,data);
        return TRUE;
    }                           
    return FALSE;
} // End of NIDeque_c<T>::Remove

#endif
