//----------------------------------------------------------------------
//  IMPLEMENTATION FILE (uqueue.cpp)
//  This module exports an ADT for an unbounded queue of integer values.
//  Queue representation: a dynamic singly linked list with front and
//                        rear pointers.
//----------------------------------------------------------------------
#include "uqueue.h"
#include <stddef.h>     // For NULL
#include <alloc.h>      // For coreleft()   (This function is nonportable)

typedef NodeType* NodePtr;

struct NodeType {             // List node type
    int     data;
    NodePtr link;
};

void CopyList(NodePtr, NodePtr&, NodePtr& );   // Prototype for
                                               // auxiliary function
// Private members of class:
//     NodeType* front;
//     NodeType* rear;
//
// CLASSINV:
//       front points to first node of a singly linked list (or == NULL)
//    && rear points to last node of this list (or == NULL)

IntQueue::IntQueue()
    //..................................................................
    // Constructor
    // POST: front == NULL  &&  rear == NULL
    //..................................................................
{
    front = rear = NULL;
}

IntQueue::~IntQueue()
    //..................................................................
    // Destructor
    // POST: Linked list is not on free store
    //..................................................................
{
    NodePtr tempPtr;

    while (front != NULL) {  // INV (prior to test):
                             //   front points to list with previous
                             //   first node deallocated (or == NULL)
        tempPtr = front;
        front = tempPtr->link;
        delete tempPtr;
    }
}

IntQueue::IntQueue( const IntQueue& otherQ )
    //..................................................................
    // Copy-constructor
    // POST: A clone of otherQ's linked list is on free store
    //    && front points to front of this new list (or == NULL)
    //    && rear points to rear of this new list (or == NULL)
    //..................................................................
{
    if (otherQ.front == NULL)
        front = rear = NULL;
    else
        CopyList(otherQ.front, front, rear);
}

Boolean IntQueue::IsEmpty() const
    //..................................................................
    // POST: FCTVAL == (front == NULL)
    //..................................................................
{
    return (front == NULL);
}

Boolean IntQueue::IsFull() const
    //..................................................................
    // POST: FCTVAL == (there is no room on the free store for
    //                  another NodeType object)
    //..................................................................
{
    return (coreleft() < sizeof(NodeType));
}

void IntQueue::Enqueue( /* in */ int newItem )
    //..................................................................
    // PRE:  NOT IsFull()  &&  Assigned(newItem)
    // POST: A new node containing newItem is at back of list
    //..................................................................
{
    NodePtr newPtr = new NodeType;
    newPtr->data = newItem;
    newPtr->link = NULL;
    if (front == NULL)
        front = rear = newPtr;
    else {
        rear->link = newPtr;
        rear = newPtr;
    }
}

int IntQueue::Front() const
    //..................................................................
    // PRE:  front != NULL
    // POST: FCTVAL == front->data
    //..................................................................
{
    return front->data;
}

void IntQueue::Dequeue()
    //..................................................................
    // PRE:  front != NULL
    // POST: Previous first node is not in list
    //    && front points to new first node (or == NULL)
    //..................................................................
{
    NodePtr tempPtr = front;
    front = tempPtr->link;
    delete tempPtr;
    if (front == NULL)
        rear = NULL;
}

void CopyList( /* in */  NodePtr  currPtr,
               /* out */ NodePtr& cloneFront,
               /* out */ NodePtr& cloneRear  )
    //..................................................................
    // PRE:  Assigned(currPtr)
    // POST: A clone of sublist starting with *currPtr is on free store
    //    && cloneFront points to front of this sublist
    //    && (After recursion unwinds) cloneRear points to rear of
    //          entire clone list
    //..................................................................
{
    NodePtr newPtr = NULL;
    if (currPtr != NULL) {
        CopyList(currPtr->link, cloneFront, cloneRear);
        newPtr = new NodeType;
        newPtr->data = currPtr->data;
        newPtr->link = cloneFront;
        if (currPtr->link == NULL)      // Last node in list
            cloneRear = newPtr;
    }
    cloneFront = newPtr;
}

