/**********************************************************
*      See the LICENSE file for copyright information.     *
**********************************************************/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/* needed for intptr_t */
#include "config.h"
#include <stdint.h>

/*  CONVENTIONS:  All data structures for stacks have the prefix */
/*                "stk_" to prevent name conflicts. */
/*                                                                      */
/*                Function names: Each word in a function name begins with */
/*                a capital letter.  An example function name is  */
/*                CreateRedTree(a,b,c). Furthermore, each function name */
/*                should begin with a capital letter to easily distinguish */
/*                them from variables. */
/*                                                                     */
/*                Variable names: Each word in a variable name begins with */
/*                a capital letter EXCEPT the first letter of the variable */
/*                name.  For example, int newLongInt.  Global variables have */
/*                names beginning with "g".  An example of a global */
/*                variable name is gNewtonsConstant. */

/*  if DATA_TYPE is undefined then stack.h and stack.c will be code for */
/*  stacks of void *, if they are defined then they will be stacks of the */
/*  appropriate data_type */

#ifndef DATA_TYPE
#define DATA_TYPE void *
#endif

typedef struct stk_stack_node {
  DATA_TYPE info;
  struct stk_stack_node * next;
} stk_stack_node;

typedef struct stk_stack { 
  stk_stack_node * top;
  stk_stack_node * tail;
} stk_stack ;

/*  These functions are all very straightforward and self-commenting so */
/*  I didn't think additional comments would be useful */
stk_stack * StackJoin(stk_stack * stack1, stk_stack * stack2);
stk_stack * StackCreate(void);

/** push an item onto the stack
 *
 * @param theStack Stack to operate on
 * @param newInfoPointer Item to push onto the top
 * @return 0 on success
 */
int StackPush(stk_stack * theStack, DATA_TYPE newInfoPointer);

void * StackPop(stk_stack * theStack);
intptr_t StackNotEmpty(stk_stack *);

/** deallocate a previously created stack
 *
 * @param theStack Stack to operate on
 * @param DestFunc Destructor to run on each item remaining on the stack
 */
void StackDestroy(stk_stack * theStack,void DestFunc(void * a));

#ifdef __cplusplus
}
#endif
