/* Stacks with Arrays Lab
   Version 3:  Stack contains pointers to strings
               copies of strings made during push, top, get_nth operations
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#include "stack-pointer.h"   /* Include definition of buffer-based stack */
#include "stack.h"

#include "stack.c" /* Include the common/shared function implementations */


bool
push (struct string_stack * stack, char * item)  /* allocate mem, copy string */
{
  /* post-conditions:  item string is added to stack and returns true
     or else stack is unmodified and returns false 
     (when stack is full or space allocation fails). */

  if (isFull (stack))
    return false;

  char * topData = malloc (sizeof(char)*(strlen(item) + 1));
  
  if (topData == NULL) {
    perror ("Unable to allocate space for item");
    return false;
  }
  
  /* add item to stack */
  (stack->topPosition) ++;
  stack->items[stack->topPosition] = topData;
  strcpy (topData, item);
  return true;
} // push


char *
pop (struct string_stack * stack)
/* pre-condition: stack is not empty
   post-condition: top element is removed from stack */
{ 
  assert (!isEmpty(stack));

  char * item;  /* string [base address] to return */
  
  /* remove item from stack */
  item = stack->items[stack->topPosition];
  (stack->topPosition)--;
  return item;
} // pop


char *
top (const struct string_stack * stack)            /* must allocate mem, copy string */
/* pre-condition: stack is not empty
   post-condition: stack is unmodified, but
                   if unable to allocate space for copy, returns NULL
   produces: reference to item at top of stack */

{
  /* return -1 if stack empty */
  assert (!isEmpty (stack));
  /* remove item from stack */
  char * item = malloc (sizeof(char) *
                        strlen (stack->items[stack->topPosition]) + 1);

  if (item == NULL)
  {
    perror ("Unable to allocate space for top item");
    return NULL;
  }
  
  strcpy (item, stack->items[stack->topPosition]);
  return item;
} // top


char *
get (const struct string_stack * stack, int index) /* must allocate mem, copy string */
{
  /* assume nth indexing starts at 1
     translate to 0-indexed arrays, counting from topPosition 
     abort if invalid index specified */

  assert ( (index >= 1) && (index <= stack->topPosition+1));

  int location = stack->topPosition - index + 1;
  char* item;  /* string [base address] to return */

  
  item = malloc (sizeof(char) * (strlen(stack->items[location]) + 1));

  if (item == NULL)
  {
    perror ("Unable to allocate space for item");
    return NULL;
  }
  
  strcpy (item, stack->items[location]);
  return item;
} // get
