//----------------------------------------------------------------------
//  IMPLEMENTATION FILE (ustack.cpp)
//  This module exports an ADT for an unbounded stack of integer values.
//  Stack representation: a dynamic singly linked list.
//----------------------------------------------------------------------
#include "ustack.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;
};

NodePtr PtrToClone( NodePtr );      // Prototype for auxiliary function

// Private members of class:
//     NodeType* top;
//
// CLASSINV: top is the head pointer to a singly linked list (or==NULL)
//     NOTE: There is no explicit bound on stack size (subject to
//           available free store memory)

IntStack::IntStack()
    //..................................................................
    // Constructor
    // POST: top == NULL
    //..................................................................
{
    top = NULL;
}

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

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

IntStack::IntStack( const IntStack& otherStk )
    //..................................................................
    // Copy-constructor
    // POST: A clone of otherStk's linked list is on free store
    //    && top points to this new list
    //..................................................................
{
    top = PtrToClone(otherStk.top);
}

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

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

void IntStack::Push( /* in */ int newItem )
    //..................................................................
    // PRE:  NOT IsFull()  &&  Assigned(newItem)
    // POST: A new node containing newItem is at front of list
    //    && top points to this node
    //..................................................................
{
    NodePtr newPtr = new NodeType;
    newPtr->data = newItem;
    newPtr->link = top;
    top = newPtr;
}

int IntStack::Top() const
    //..................................................................
    // PRE:  top != NULL
    // POST: FCTVAL == top->data
    //..................................................................
{
    return top->data;
}

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

NodePtr PtrToClone( /* in */ NodePtr currPtr )
    //..................................................................
    // PRE:  Assigned(currPtr)
    // POST: A clone of sublist starting with *currPtr is on free store
    //    && FCTVAL == pointer to front of this sublist
    //..................................................................
{
    NodePtr newPtr = NULL;
    if (currPtr != NULL) {
        newPtr = new NodeType;
        newPtr->data = currPtr->data;
        newPtr->link = PtrToClone(currPtr->link);
    }
    return newPtr;
}

