#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    int *items;
    size_t len;
    size_t capacity;
} Stack;

Stack stack_new(void)
{
    Stack stack = {
        .items = NULL,
        .len = 0,
        .capacity = 0
    };

    return stack;
}

void stack_push(Stack *stack, int value)
{
    if (stack->len == stack->capacity) {
        size_t new_capacity = stack->capacity == 0
            ? 4
            : stack->capacity * 2;

        int *new_items = realloc(
            stack->items,
            new_capacity * sizeof(int)
        );

        if (new_items == NULL) {
            exit(EXIT_FAILURE);
        }

        stack->items = new_items;
        stack->capacity = new_capacity;
    }

    stack->items[stack->len] = value;
    stack->len++;
}

bool stack_pop(Stack *stack, int *value)
{
    if (stack->len == 0) {
        return false;
    }

    stack->len--;
    *value = stack->items[stack->len];

    return true;
}

bool stack_peek(const Stack *stack, int *value)
{
    if (stack->len == 0) {
        return false;
    }

    *value = stack->items[stack->len - 1];

    return true;
}

bool stack_is_empty(const Stack *stack)
{
    return stack->len == 0;
}

size_t stack_len(const Stack *stack)
{
    return stack->len;
}

void stack_free(Stack *stack)
{
    free(stack->items);

    stack->items = NULL;
    stack->len = 0;
    stack->capacity = 0;
}

int main(void)
{
    Stack stack = stack_new();

    stack_push(&stack, 10);
    stack_push(&stack, 20);
    stack_push(&stack, 30);

    printf("len = %zu\n", stack_len(&stack));

    int value;

    if (stack_peek(&stack, &value)) {
        printf("peek = %d\n", value);
    }

    if (stack_pop(&stack, &value)) {
        printf("pop = %d\n", value);
    }

    if (stack_pop(&stack, &value)) {
        printf("pop = %d\n", value);
    }

    printf("len = %zu\n", stack_len(&stack));
    printf("empty = %s\n",
           stack_is_empty(&stack) ? "true" : "false");

    stack_free(&stack);

    return 0;
}