/*-----------------------------------------------------------------------
	File:  stkicpp2.cpp
	Author:  M. Sebern
	Date:  23-May-1995
	Purpose:
		Implementation of "stack of integers" abstract data type
		using a variable-length array, with constructor and destructor.
	Revision history:
		Jeffrey Blessing 3-13-98 for CS-481 students.
-----------------------------------------------------------------------*/

/* Include Files: */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "stkicpp2.h"

/* Constant Definitions: */

#define STACK_SIZE_INCR (5)

/* Macro Definitions: */

/* Type Declarations: */

/* Function Prototypes: */

/* External Variables: */

/*-----------------------------------------------------------------------
	Function:	Stack
	Purpose:
		Class constructor; initializes a new instance of the
		stack ADT.
	Usage:
		Stack	s; 	// (or equivalent)
	Input Parameters:
		None
	Output Parameters:
		None.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		Stack storage has been allocated.
		Stack is empty.
	Functions Referenced:
		assert		(assert.h)
		IsEmpty		Test if stack is empty.
	Pseudo Code:

	Allocate storage for stack array
	Set stack size to agree with allocated space
	Set current element index to "empty"
	Return data structure pointer to caller
-----------------------------------------------------------------------*/

Stack::Stack()
{
	printf("In Stack constructor\n");
	max_elem = STACK_SIZE_INCR;
	current_elem = -1;
	elems = (int*) malloc(max_elem * sizeof(int));

	assert( elems != NULL );
	assert( IsEmpty() );
}

/*-----------------------------------------------------------------------
	Function:	~Stack
	Purpose:
		Class destructor: frees data from an instance of the
		stack ADT.
	Usage:
		(automatic when variable goes out of scope or is deleted)
	Input Parameters:
		None.
	Output Parameters:
		None.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		None.
	Functions Referenced:
		None.
	Pseudo Code:
		Deallocate storage for stack array.
-----------------------------------------------------------------------*/

Stack::~Stack()
{
	printf("In Stack destructor\n");
	free(elems);
	// C++ will free the storage it allocated.
}

/*-----------------------------------------------------------------------
	Function:	Push
	Purpose:
		Push an element onto a stack.
	Usage:
		Stack	stack;
		int	elem;
		...
		stack.Push (elem);
	Input Parameters:
		element	Element to push on stack.
	Output Parameters:
		None.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		Reallocation (if needed) must not have failed.
		The array size must not be big enough to overflow.
		Stack must not be empty.
		Current element index must be < max_elem.
	Functions Referenced:
		assert   (assert.h)
		IsEmpty  Check for empty stack.
	Pseudo Code:
		If stack array is full
			 Allocate more array space.
		End If
		Increment current element index.
		Store new value in array.
-----------------------------------------------------------------------*/

void Stack::Push(int element)
{
	if ( current_elem >= (max_elem - 1) )
	{
		size_t	alloc_size;

		max_elem += STACK_SIZE_INCR;
		assert( max_elem > 0 );
		alloc_size = (size_t) max_elem * sizeof(int);
		elems = (int*) realloc(elems, alloc_size);
		assert( elems != NULL );
	}
	elems[++current_elem] = element;

	assert( !IsEmpty() );
	assert( current_elem < max_elem );
}

/*-----------------------------------------------------------------------
	Function:	Pop
	Purpose:
		Pop an element off a stack.
	Usage:
		Stack	stack;
		int	elem;
		...
		elem = stack.Pop();
	Input Parameters:
		None.
	Output Parameters:
		Return value: element from top of stack.
	Side Effects:
		None.
	Preconditions:
		Stack must not be empty.
	Postconditions:
		Current element index must be >= -1 and < (max_elem-1).
	Functions Referenced:
		assert		(assert.h)
		IsEmpty		Test if stack is empty.
	Pseudo Code:
		Get current top element.
		Decrement current element index.
		Return prior top element.
-----------------------------------------------------------------------*/

int Stack::Pop()
{
	int	ret_elem = 0;

	assert( !IsEmpty() );

	ret_elem = elems[current_elem--];

	assert( current_elem >= -1 );
	assert( current_elem < (max_elem - 1) );

	return ret_elem;
}

/*-----------------------------------------------------------------------
	Function:	Top
	Purpose:
		Copy top element of a stack.
	Usage:
		Stack	stack;
		int	elem;
		...
		elem = stack.Top();
	Input Parameters:
		None.
	Output Parameters:
		Return value: element from top of stack.
	Side Effects:
		None.
	Preconditions:
		Stack must not be empty.
	Postconditions:
		None.
	Functions Referenced:
		assert		Verify condition.
		IsEmpty		Test if stack is empty.
	Pseudo Code:
		Return top element of stack.
-----------------------------------------------------------------------*/

int Stack::Top () const
{
	assert( !IsEmpty() );

	// Uncomment to test invalid change to member from
	// routine with "const" access to object.
//	current_elem++;

	return elems[current_elem];
}

/*-----------------------------------------------------------------------
	Function:	IsEmpty
	Purpose:
		Report whether a stack is empty.
	Usage:
		Stack	stack;
		Boolean	empty;
		...
		empty = stack.IsEmpty ();
	Input Parameters:
		None.
	Output Parameters:
		Function value:	True if stack is empty,
				false otherwise.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		None.
	Functions Referenced:
		None.
	Pseudo Code:

	If current stack element index < 0)
		 Return true status
	Else
		 Return false status
	End If
-----------------------------------------------------------------------*/

bool Stack::IsEmpty() const
{
	return current_elem < 0;
}
