#include <stdlib.h>
#include <stdio.h>
#include "stack.h"

#define INIT_SIZE 100
#define RESIZE_FACTOR 2

typedef struct
{
	// The array of values.
	void **values;
	// The top of the stack.
	int top_of_stack;
	// Current size of the stack.
	int size;
} Stack;

void* new_stack()
{
	Stack *stack = (Stack*) malloc(sizeof(Stack));

	stack->values = (void**) malloc(sizeof(void*) * INIT_SIZE);
	stack->size = INIT_SIZE;

	// If the top of the stack is -1, then the stack is empty.
	stack->top_of_stack = -1;

	return stack;
}

void* top(void *stack)
{
	Stack *s = (Stack*) stack;
	if(s->top_of_stack == -1)
	{
		return NULL;
	}

	return s->values[ s->top_of_stack ];
}

int empty(void *stack)
{
	Stack *s = (Stack*) stack;
	return s->top_of_stack == -1;
}

void push(void *stack, void *v)
{
	Stack *s = (Stack*) stack;
	
	// Check to see if the stack needs to be resized.
	if(s->top_of_stack >= s->size - 1)
	{
		s->values = (void**) realloc(s->values, s->size * RESIZE_FACTOR);
	}
	
	// Now add the value to the top of the stack.
	s->top_of_stack++;
	s->values[ s->top_of_stack ] = v;
}

void* pop(void *stack)
{
	Stack *s = (Stack*) stack;

	if( !empty(s) )
	{
		void *v = top(s);
		s->top_of_stack--;
		return v;
	}
	// Else if stack is empty, return NULL.
	return NULL;
}

void free_stack(void *stack)
{	
	Stack *s = (Stack*) stack;
	free(s);
}

