/********************************************/
/* Modulo stack.c        Fecha: 9/5/2002    */
/* Autores: Carlos del Cacho Vicente y      */
/*          Jose David Alvarez Valentin     */
/* Grupo J9                                 */
/*                                          */
/* Este modulo contiene las primitivas      */
/* de una pila                              */
/********************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stack.h"


/********************************************/
/* Funcion InitStack                        */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Inicializa una pila                      */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/*           int data_size: tamaņo de los   */
/*           datos de la pila               */
/********************************************/
void InitStack(my_stack_t *pstack, int data_size)
{
   pstack->data_size = data_size;
   pstack->entries = NULL;
}

/********************************************/
/* Funcion InsertStack                      */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Inserta un elemento en la pila           */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/*           const void *data: elemento que */
/*           se inserta                     */
/*  Salida: entrada donde se inserto o NULL */
/********************************************/
my_stack_entry_t *InsertStack(my_stack_t *pstack, const void *data)
{
  my_stack_entry_t *pentry;

  if (!(pentry = malloc(sizeof(my_stack_entry_t))) ||
      !(pentry->data = malloc(pstack->data_size)))
    return NULL;

  memcpy(pentry->data, data, pstack->data_size);

  pentry->next = pstack->entries;
  pstack->entries = pentry;
  return pentry;
}


/********************************************/
/* Funcion ExtractStack                     */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Extrae un elemento de la pila            */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/*           void *data: elemento donde se  */
/*           guarda                         */
/*  Salida: 0 si se extrajo. -1 si esta vacia*/
/********************************************/
void *ExtractStack(my_stack_t *pstack, void *data)
{
   my_stack_entry_t *pentry;

   if (!pstack->entries)
     return NULL;

   pentry = pstack->entries;
   pstack->entries = pstack->entries->next;

   memcpy(data,pentry->data, pstack->data_size);
   free(pentry->data);
   free(pentry);
   return data;
}

/********************************************/
/* Funcion ClearStack                       */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Elimina las entradas de la pila          */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/********************************************/
void ClearStack(my_stack_t *pstack)
{
   my_stack_entry_t *pentry = pstack->entries,
                 *pkill;

   while(pentry)
   {
      pkill = pentry;
      pentry = pentry->next;
      free(pkill->data);
      free(pkill);
   }

   pstack->entries = NULL;
}

/********************************************/
/* Funcion IsEmpty                          */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Comprueba si la pila esta vacia          */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/*  Salida: 1 si lo esta. 0 si no           */
/********************************************/
int IsEmpty(my_stack_t *pstack)
{
   return pstack->entries ? 0 : 1;
}

/********************************************/
/* Funcion PeekStack                        */
/* Fecha: 9/5/2002                          */
/*                                          */
/* Muestra el elemento en una posicion      */
/* Parametros:                              */
/*  Entrada: my_stack_t *pstack: pila          */
/*           int indx: posicion             */
/*  Salida: datos o NULL                    */
/********************************************/
void *PeekStack(my_stack_t *pstack, int indx)
{
   my_stack_entry_t *pentry = pstack->entries;

   while (indx--)
   {
      if (!pentry)
        return NULL;

      pentry = pentry->next;      
   }

   return pentry ? pentry->data : NULL;
}
