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

stack* new_stack(void)
{
    stack* S = malloc(sizeof(stack));
    S->size = 0;
    S->alloc_size = 1;
    S->data = malloc(sizeof(size_t));
    return S;
}

void free_stack(stack* S)
{
    free(S->data);
    free(S);
}

void push_stack(stack* S, size_t elem)
{
    if (S->alloc_size == S->size) {
        S->alloc_size *= 2;
        S->data = realloc(S->data, S->alloc_size * sizeof(size_t));
        if (S->data == NULL) {
            fprintf(stderr, "error during realloc (push_stack): aborting\n");
            exit(2);
        }
    }
    S->data[S->size] = elem;
    S->size += 1;
}

int is_empty_stack(stack* S) { return S->size == 0; }

size_t pop_stack_unsafe(stack* S) { return S->data[--S->size]; }

int pop_stack(stack* S, size_t* elem)
{
    if (is_empty_stack(S)) {
        return 0;
    } else {
        *elem = pop_stack_unsafe(S);
        return 1;
    }
}

void empty_stack(stack* S) { S->size = 0; }

void remove_from_stack(stack* S, size_t elem)
{
    size_t c = 0;
    size_t i = 0;
    size_t j = 0;
    while (j < S->size) {
        if (S->data[j] == elem) {
            j += 1;
            c += 1;
        } else {
            S->data[i] = S->data[j];
            i += 1;
            j += 1;
        }
    }
    S->size -= c;
}

void bulk_remove_from_stack(stack* S, const size_t* ToRemove)
{
    size_t c = 0;
    size_t i = 0;
    size_t j = 0;
    while (j < S->size) {
        if (ToRemove[S->data[j]]) {
            j += 1;
            c += 1;
        } else {
            S->data[i] = S->data[j];
            i += 1;
            j += 1;
        }
    }
    S->size -= c;
}

int contains_stack(stack* S, size_t elem)
{
    for (size_t i = 0; i < S->size; i++) {
        if (S->data[i] == elem) {
            return 1;
        }
    }
    return 0;
}

// vim: textwidth=100 foldmethod=indent
