/*-----------------------------------------------------------------------
	File:  stackint.c
	Author:  M. Sebern
	Date:  19-May-1995
	Purpose:
		Implementation of "stack of integers" abstract data type
		using a variable-length array.
	Revision history:
		Jeffrey Blessing 3-13-98 Modified for CS-481 students.
-----------------------------------------------------------------------*/

/* Include Files: */

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

/* Constant Definitions: */

#define STACK_SIZE_INCR (10)

/* Macro Definitions: */

/* Type Declarations: */

/* Function Prototypes: */

/* External Variables: */

/*-----------------------------------------------------------------------
	Function:	CreateStack
	Purpose:
		Create a new instance of the stack ADT.
	Usage:
		Stack	s;
		s = CreateStack();
	Input Parameters:
		None
	Output Parameters:
		Return value:	Newly created stack.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		Stack storage has been allocated.
		Stack is empty.
	Functions Referenced:
		assert		(assert.h)
		IsStackEmpty	Test if stack is empty.
	Pseudo Code:

	Allocate storage for stack data structure
	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
-----------------------------------------------------------------------*/

extern Stack CreateStack(void)
{
	Stack stack = (Stack) NULL;

	stack = (Stack) calloc(1, sizeof(stack_struct));
	stack->max_elem = STACK_SIZE_INCR;
	stack->current_elem = -1;
	stack->elems = (int*) malloc(stack->max_elem * sizeof(int));

	assert( stack->elems != NULL );
	assert( IsStackEmpty(stack) );

	return stack;
}

/*-----------------------------------------------------------------------
	Function:	DestroyStack
	Purpose:
		Destroy an instance of the stack ADT.
	Usage:
		Stack	s;
		DestroyStack(s);
	Input Parameters:
		stack	Stack to be destroyed.
	Output Parameters:
		None.
	Side Effects:
		None.
	Preconditions:
		None.
	Postconditions:
		None.
	Functions Referenced:
		free	(stdlib.h)
	Pseudo Code:
	Deallocate storage for stack array.
	Dellocate storage for stack data structure.
-----------------------------------------------------------------------*/

extern void DestroyStack(Stack stack)
{
	free(stack->elems);
	free(stack);
}

/*-----------------------------------------------------------------------
	Function:	PushStack
	Purpose:
		Push an element onto a stack.
	Usage:
		Stack	stack;
		int	elem;
		...
		PushStack(stack,elem);
	Input Parameters:
		stack		Stack variable.
		element	Element to push on stack.
	Output Parameters:
		Stack variable is updated.
	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)
		IsStackEmpty  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.
-----------------------------------------------------------------------*/

extern void PushStack(Stack stack, int element)
{
	if ( stack->current_elem >= (stack->max_elem - 1) )
	{
		size_t	alloc_size;

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

	assert( !IsStackEmpty(stack) );
	assert( stack->current_elem < stack->max_elem );
}

/*-----------------------------------------------------------------------
	Function:	PopStack
	Purpose:
		Pop an element off a stack.
	Usage:
		Stack	stack;
		int	elem;
		...
		elem = PopStack (stack);
	Input Parameters:
		stack	Stack variable.
	Output Parameters:
		Return value: element from top of stack.
		Stack variable is updated.
	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)
		IsStackEmpty	Test if stack is empty.
	Pseudo Code:

	Get current top element.
	Decrement current element index.
	Return prior top element.
-----------------------------------------------------------------------*/

extern int PopStack(Stack stack)
{
	int ret_elem = 0;

	assert( !IsStackEmpty(stack) );

	ret_elem = stack->elems[stack->current_elem--];

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

	return ret_elem;
}

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

	Return top element of stack.
-----------------------------------------------------------------------*/

extern int TopStack(const_Stack stack)
{
	assert( !IsStackEmpty(stack) );

	return stack->elems[stack->current_elem];
}

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

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

extern Boolean IsStackEmpty(const_Stack stack)
{
	return stack->current_elem < 0;
}

