/* Stacks with Arrays Lab
   Version 2:  Stack contains array of strings
               push copies string to stack
*/

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

#include "stack-buffer.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) /* must copy string to stack */
/* post-conditions:  item string is added to stack and returns true
                     or else stack is unmodified and returns false 
                     (when stack is full). */
{
  if (isFull (stack))
    return false;
  
  /* add item to stack */
  (stack->topPosition) ++;
  strncpy (stack->items[stack->topPosition], item, MAX_STRING_LENGTH);
  return true;
} // push


char *
pop (struct string_stack * stack)                  /* must create copied string */
/* pre-condition: stack is not empty
   post-condition: 
     top element is removed from stack, returns copy of it
     if unable to allocate space for copy, returns NULL and stack is unmodified
     memory is allocated for returned value; user is responsible for freeing 
*/
{
  char * item;  /* string [base address] to return */

  assert (!isEmpty(stack));
  
  /* remove item from stack, copying to newly allocated buffer */
  item = malloc (sizeof(char) * (strlen(stack->items[stack->topPosition])+1));

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


char *
top (const struct string_stack * stack)          /* must create copied string */
/* pre-condition: stack is not empty
   post-condition: 
     stack is unmodified, but
     if unable to allocate space for copy, returns NULL
     memory is allocated for returned value; user is responsible for freeing  */
{
  char* item;  /* string [base address] to return */

  assert (!isEmpty(stack));

  /* copy item from stack */  
  item = malloc (sizeof(char) * strlen (stack->items[stack->topPosition])+1);

  if (item==NULL) {
    perror ("Unable to allocate space for top string");
    return NULL;
  }

  strcpy(item, stack->items[stack->topPosition]);
  return item;
} // top


char *
get (const struct string_stack * stack, int index) /* must create copied 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 = malloc (sizeof(char) * (strlen(stack->items[location])+1));

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