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

#define SIZE 24

typedef int BOOL;
#define TRUE 1
#define FALSE 0

typedef struct
{
	int head;
	int tail;
	int size;
	int* buffer;
} RingBufferState;

BOOL init_ring_buffer(int size, RingBufferState* state)
{
	if (state == NULL)
		return FALSE;

	int* buffer = malloc(size * sizeof(int));
	if (buffer == NULL)
		return FALSE;

	state->buffer = buffer;
	state->head = 0;
	state->tail = 0;
	state->size = size;

	return TRUE;
}

BOOL free_ring_buffer(RingBufferState* state)
{
	if (state == NULL)
		return FALSE;

	free(state->buffer);
	state->buffer = NULL;
	state->size = 0;
	state->tail = 0;
	state->head = 0;

	return TRUE;
}

BOOL push_to_ring_buffer(int value, RingBufferState* state)
{
	if (state == NULL)
		return FALSE;

	state->buffer[state->head] = value;

	++state->head;
	if (state->head >= state->size)
		state->head = 0;

	if (state->head == state->tail)
		++state->tail;

	return TRUE;
}

BOOL pop_from_ring_buffer(int* value, RingBufferState* state)
{
	if (state == NULL || state->head == state->tail)
		return FALSE;

	--state->head;
	if (state->head < 0)
		state->head = state->size - 1;

	*value = state->buffer[state->head];

	return TRUE;
}

BOOL print_ring_buffer(RingBufferState* state)
{
	if (state == NULL)
		return FALSE;

	printf("h: %d; t: %d; s: %d\n", state->head, state->tail, state->size);
	for (int i = 0; i < state->size; ++i)
	{
		if (i == state->tail)
			printf("|");
		printf("%d ", state->buffer[i]);
		if (i == state->head)
			printf("^");
	}
	printf("\n");

	return TRUE;
}

int main()
{
	RingBufferState state;
	init_ring_buffer(SIZE, &state);
	for (int i = 0; i < SIZE; ++i)
		push_to_ring_buffer(i, &state);
	print_ring_buffer(&state);
	printf("----\n");
	push_to_ring_buffer(999, &state);
	push_to_ring_buffer(999, &state);
	print_ring_buffer(&state);
	int value = 0;
	pop_from_ring_buffer(&value, &state);
	printf("---\n");
	printf("g: %d\n", value);
	print_ring_buffer(&state);
	printf("---\n");
	push_to_ring_buffer(6969, &state);
	print_ring_buffer(&state);
	pop_from_ring_buffer(&value, &state);
	pop_from_ring_buffer(&value, &state);
	pop_from_ring_buffer(&value, &state);
	pop_from_ring_buffer(&value, &state);
	pop_from_ring_buffer(&value, &state);
	print_ring_buffer(&state);
	push_to_ring_buffer(6969, &state);
	push_to_ring_buffer(6969, &state);
	print_ring_buffer(&state);
}