#include <stdio.h>
#include <string.h>
#include "base_includes.h"
#include "queue.h"
#include "ff.h"

typedef struct stack_element_struct *stack_element_ptr;
typedef struct stack_element_struct {
  char *key, *data;
  stack_element_ptr next;
} stack_element;

typedef struct STACK_TYPE_STRUCT {
/* is_stack = non-zero if we are representing a stack. 0 for a queue */
/* type can be used to make sure you are popping the right type of element */
  int is_stack, type;
  stack_element_ptr top, end;
} STACK_TYPE;

stackptr make_new_stack(int is_stack, int type)
{
  stackptr tmp;
  tmp = (stackptr)mymalloc(sizeof(STACK_TYPE));
  if (tmp) {
    tmp->is_stack = is_stack;
    tmp->type = type;
    tmp->top = tmp->end = NULL;
  }
  return tmp;
}

char *pop_element(stackptr stack, int type, char **key)
{
  char *ret = NULL;
  if (stack->top) {
    if (key) *key = stack->top->key;
    ret = stack->top->data;
    if (stack->top == stack->end) /* single element in list */
      stack->top = stack->end = NULL;
    else
      stack->top = stack->top->next;
  } else {
    ret = NULL;
    if (key) *key = NULL;
  }
  return ret;
}

void push_element(stackptr stack, char *key, char *element, int len,
                  int domalloc)
{
  stack_element_ptr tmp;
  tmp = (stack_element_ptr)mymalloc(sizeof(stack_element));
  if (!tmp) return;
  tmp->key = (key)?m_strcpy(key):NULL;
  if (element)
    tmp->data = domalloc?m_copy(element, len?len:(strlen(element)+1)):element;
  else tmp->data = NULL;
  if (stack->is_stack) {
/* If it's a stack, add the element to the top of the list so it will be
   be popped off first. */
    tmp->next = stack->top;
    stack->top = tmp;
    if (!stack->end) stack->end = tmp;
  } else {
/* If it's a queue (not a stack) add the element to the end of the list so
   that it will be popped off other all elements that were added before it
   are popped off before it. */
    if (stack->end) stack->end->next = tmp;
    if (!stack->top) stack->top = tmp;
    stack->end = tmp;
    tmp->next = NULL;
  }
}
