#include "generic-stack.h"
#include "common.h"

int create_stack(STACK *s, size_t element_size, PRINTER_FN print_element, uint initial_capacity)
{
    s->element_size = element_size;
    s->print_element = print_element;
    s->capacity = initial_capacity;
    s->top = 0;
    if (NULL == (s->elements = malloc(initial_capacity * element_size))) {
        fprintf(stderr, "create_stack: out of memory\n");
        return -1;
    }
    return 0;
}

void delete_stack(STACK *s)
{
    free(s->elements);
    return;
}


int push(STACK *s, void *element)
{
    void *tmp;

    if (s->top == s->capacity) {
        s->capacity = 2*s->capacity + 100;
        if (NULL == (tmp = realloc(s->elements, s->capacity * s->element_size))) {
            free(s->elements);
            fprintf(stderr, "push: out of memory\n");
            return -1;
        }
        s->elements = tmp;
    }
    memcpy((char *) s->elements + s->top * s->element_size, element, s->element_size);
    s->top++;
    return 0;
}

int pop(STACK *s, void *d)
{
    if (s->top == 0) {
        fprintf(stderr, "pop: underflow (stack empty)\n");
        return -1;
    }
    s->top--;
    memcpy(d, (char *) s->elements + s->top * s->element_size, s->element_size);
    return 0;
}

void print_stack(STACK *s)
{
    long int i;

    if (s->top == 0) {
        printf("Stack empty\n\n");
        return;
    }
    printf("Stack capacity: %lu, top = %lu\n", s->capacity, s->top);
    for (i = s->top-1; i >= 0; i--) {
        printf("%4ld ", i);
        s->print_element((char *) s->elements + i * s->element_size);
    }
    puts("----------------------------------------------------------------------\n");
    return;
}
