/*
  arraystack.c
  Implementation of the stack ADT using an array
  Nadeem Abdul Hamid
  Fall 2006 - Berry College - CSC220
*/

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

#define INITIAL_CAPACITY 2


/* the stack data structure */
struct stack 
{
  void** data; /* array of void* pointers */
  int t;       /* top index, -1 if empty */
  int cap;     /* current capacity of the data array */
};


/* creates a new stack with initial capacity */
STACK createStack() 
{
  STACK s = (STACK) malloc(sizeof(struct stack));
  s->cap = INITIAL_CAPACITY;
  s->data = (void**) malloc(s->cap * sizeof(void*));
  s->t = -1;
  return s;
}


/* frees all memory associated with the stack data structure,
   (but does not free any of the actual data items) */
void destroyStack(STACK s) 
{
  free(s->data);
  free(s);
}


/* returns the size of the stack */
int size(STACK s)
{
  return s->t + 1;
}


/* returns whether the stack is empty */
bool isEmpty(STACK s)
{
  return !size(s);
}


/* adds an item to the top of the stack; returns true if successful */
bool push(STACK s, void* item)
{
  if (s->t == s->cap-1) { /* out of space -- make the array bigger */
    void **newdata;
    newdata = (void**) realloc(s->data, 2 * s->cap * sizeof(void*));
    if (!newdata)
      return false;
    s->cap *= 2;
    s->data = newdata;
  }
  
  s->data[++s->t] = item;
  return true;
}


/* removes and returns the item on top of the stack; returns
   NULL if error */
void* pop(STACK s)
{
  if (isEmpty(s))
    return NULL;
  return s->data[s->t--];
}


/* returns the item on top of the stack; returns NULL if error */
void* top(STACK s)
{
  if (isEmpty(s))
    return NULL;
  return s->data[s->t];
}
