///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2021 Wizardry and Steamworks - License: MIT          //
///////////////////////////////////////////////////////////////////////////
//                                                                       //
//   stack                                                               //
//                                                                       //
//   An implementation of a stack.                                       //
//   Implemented functions:                                              //
//       - push                                                          //
//       - pop                                                           //
//       - is empty                                                      //
//       - count                                                         //
//       - size                                                          //
//       - print                                                         //
//                                                                       //
///////////////////////////////////////////////////////////////////////////
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
 
#include <sys/types.h>
#include <sys/stat.h>
 
#include "stack.h"
 
/*
    * Creates a new stack with a given size.
    */
stack* stackCreate(unsigned int size) {
    stack *s;
    s = malloc(sizeof(*s));
    if ((s->store = malloc(size * sizeof(*s->store))) == NULL) {
        free(s);
        s = NULL;
        return NULL;
    }
    s->size = size;
    s->top = 0;
    return s;
}
 
/*
    * Clears a stack and returns a pointer to a new empty stack.
    */
stack* stackClear(stack *s) {
    if (s != NULL) {
        free(s);
        s = NULL;
    }
    return stackCreate(1);
}
 
/*
    * Pushes an element onto the stack.
    */
void stackPush(stack *s, void *e, unsigned int size) {
    if (s->top > s->size - 1) {
        s->store = realloc(s->store, ++s->size * sizeof(*s->store));
    }
    s->store[s->top] = malloc(1 * sizeof(*s->store[s->top]));
    s->store[s->top]->data = malloc(size * sizeof(*s->store[s->top]->data));
    s->store[s->top]->size = size;
    memcpy(s->store[s->top]->data, e, size);
    ++s->top;
}
 
/*
    * Pops an element off the stack or returns NULL in case the
    * stack is empty.
    */
void *stackPop(stack *s) {
    void *e;
    if (stackIsEmpty(s)) {
        return NULL;
    }
    --s->top;
    e = malloc(s->store[s->top]->size);
    memcpy(e, s->store[s->top]->data, s->store[s->top]->size);
    free(s->store[s->top]->data);
    free(s->store[s->top]);
    s->store[s->top] = NULL;
    return e;
}
 
/*
	 * Delete a stack.
	 */
void stackDestroy(stack *s) {
	stackElement *e;
	while(!stackIsEmpty(s)) {
		e = stackPop(s);
		free(e->data);
		free(e);
		e = NULL;
	}
	free(s);
	s = NULL;
}