/* 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>

/* MaxStack stands for the size of all stack arrays */
#define MaxStack 50  

typedef struct {
  int topPosition;
  char* items[MaxStack];
} stringStack;      /* type for a stack of strings */

/* index of standard stack operations        changes from Version 1*/
void
initialize(stringStack* stack);           /* unchanged */

int
size(const stringStack* stack);           /* unchanged */

int
isEmpty(const stringStack* stack);        /* unchanged */

int
isFull(const stringStack* stack);         /* unchanged */


int
push(stringStack* stack, char* item);     /* must allocate mem, copy string */
/* post-condition:  item string is added to stack
                    length of string is returned 
*/

char*
pop(stringStack* stack);                  /* unchanged */

char*
top(const stringStack* stack);            /* must allocate mem, copy string */

void
print(const stringStack* stack);          /* unchanged */

char*
get(const stringStack* stack, int index); /* must allocate mem, copy string */
/* assume nth indexing starts at 1 */

/* ---------------------------------------------------------------------- */
/* Implementation of stack operations */

void
initialize(stringStack* stack)
{
  stack->topPosition = -1;
}

int
size(const stringStack* stack)
{
  return stack->topPosition+1;
}

int
isEmpty(const stringStack* stack)
{
  return (stack->topPosition == -1);
}

int
isFull(const stringStack* stack)
{
  return (stack->topPosition == (MaxStack-1));
}

int
push(stringStack* stack, char* item)
{
/* post-condition:  item string is added to stack
                    length of string is returned 
*/
  if (isFull(stack))
    return -1;
 
   /* add item to stack */
  (stack->topPosition) ++;
  stack->items[stack->topPosition] = malloc(strlen(item) + 1);
  strcpy(stack->items[stack->topPosition], item);
  return strlen(item);
}

char*
pop (stringStack *stack)
{
  char * item;  /* string [base address] to return */
  /* return -1 if stack empty */
  if (isEmpty(stack))
    return (char *)(-1);

  /* remove item from stack */
  item = stack->items[stack->topPosition];
  (stack->topPosition)--;
  return item;
}
  
char*
top(const stringStack* stack)
{
  char * item;  /* string [base address] to return */  
  /* return -1 if stack empty */
  if (isEmpty(stack))
    return (char *)(-1);

  /* remove item from stack */
  item = malloc(strlen (stack->items[stack->topPosition]) + 1);
  strcpy(item, stack->items[stack->topPosition]);
  return item;
}

void
print(const stringStack* stack)
{
  int i;
  printf("contents of stack from top to bottom:\n");
  for (i = stack->topPosition; i >= 0; i--)
    printf("    %s\n", stack->items[i]);
  printf("end of stack\n");
}

char*
get(const stringStack* stack, int index)
{
  /* assume nth indexing starts at 1
     translate to 0-indexed arrays, counting from topPosition 
     return -1 if invalid index specified */
  char* item;  /* string [base address] to return */
  if ((index < 1) || (index > stack->topPosition+1)) 
    return (char*)(-1);

  item = malloc(strlen(stack->items[stack->topPosition - index + 1]) + 1);
  strcpy(item, stack->items[stack->topPosition - index + 1]);
  return item;
}
