Please send questions to st10@humboldt.edu .
//---------------------------------------------------------------------
// File: stack.cpp
// Name: Sharon M. Tuttle
// last modified: 3-10-05
//
// Class name: stack
//
// Purpose: a collection of items such that entries can be
//    inserted and removed at only one end (called the top)
//    This version does NOT have a fixed capacity.
//
// Implementation notes: 
//     *   uses a dynamically-allocated linked list of
//         nodes
//     *   stack constructor and push can fail if new
//         cannot allocated sufficient space.
//---------------------------------------------------------------------

#include <cassert> // provides assert
#include "node.h"
#include "stack.h"
using namespace std;

/*****************************************************/
/* CONSTRUCTOR                                       */
/*****************************************************/

// constructor
//
// postcondition: creates an empty stack instance
//
stack::stack()
{
    used = 0;
    top = NULL;
}

// copy constructor
//
// (adapted from list_copy, Savitch and Main,
//    p. 241)
stack::stack(const stack& source)
{
    node *source_curr, *new_curr;

    top = NULL;
    
    used = source.used;

    // handle the case of the empty stack
    if (source.top == NULL)
    {
        return; // source is empty, so this copy is, too
    }

    // if source is NOT empty, make a copy of it

    // cause new copy to now have source top's data; 

    top = new node(source.top->get_data());

    // start a pointer walking through the new copy
    //    starting from its top
    new_curr = top;

    // is there another in the source left to be copied?
    source_curr = source.top->get_next();

    // while there is another node in the source left
    //     to be copied...
    while (source_curr != NULL)
    {
        // add a new node to the new copy with the data in
        //    that node;
        new_curr->set_next(new node(source_curr->get_data()));

        // move the new copy's pointer to the new node
        new_curr = new_curr->get_next();

        // is there another in the source left to be copied?
        source_curr = source_curr->get_next();
    }
}

// destructor
//
stack::~stack( )
{
    node *curr_ptr, *node_to_delete;

    curr_ptr = top;

    // need to deallocate EACH node in the stack
    while (curr_ptr != NULL)
    {
        node_to_delete = curr_ptr;
        curr_ptr = curr_ptr->get_next();
        delete node_to_delete;
    }

    // playing it safe...
    top = NULL;
    used = 0;
}
       
/*************************************************************/
/* ACCESSORS and other constant member functions (observers) */
/*************************************************************/

// is_empty
//
// postcondition: returns true if stack is empty, and
//    returns false otherwise
//
bool stack::is_empty( ) const
{
    return (used == 0);
}

// get_top
//
// precondition: is_empty() == false
//
// postcondition: returns the value of the top item of the
//    stack, BUT the stack is unchanged.
//
stack::value_type stack::get_top( ) const
{
    assert(is_empty() == false);

    return(top->get_data());
}

// get_size
//
// postcondition: returns the number of elements 
//    currently in the stack
//
int stack::get_size( ) const
{
    return used;
}

/*****************************************************/
/* MODIFIERS and other modifying member functions    */
/*****************************************************/

// push
//
// postcondition: a new copy of entry has been pushed
//    onto the (top of the) stack
//
void stack::push(const value_type& entry)
{
    node *temp;

    temp = new node(entry);

    // new top element's next field needs to point to 
    //    "old" top element
    temp->set_next(top);

    // now, top can safely be made to point to new top
    //    element
    top = temp;

    used++;
}

// pop
//
// precondition: is_empty() == false
//
// postcondition: the top item of the stack has been
//    removed, and its value is returned
//
stack::value_type stack::pop( )
{
    value_type popped_item;
    node*      temp;

    assert(is_empty() == false);

    used--;

    // remember: if we reach here, we KNOW that stack is 
    //    not empty
    
    popped_item = top->get_data();

    // keep track of item to be removed
    temp = top;

    // now it should be safe to make top point to the
    //    new top element
    top = top->get_next();

    // free the space for this popped node from the heap,
    //    so it be be re-allocated for other uses
    delete temp;

    return popped_item;
}