#pragma once

// ::Allocator::Arena::Header::

#define ARENA_HEADER_SIZE 64

typedef struct Arena_t
{
	u8		*buffer;
	isize length;
	isize pos;
	u32   init_line_no;
} Arena;

typedef struct TempArena_t
{
	Arena *arena;
	u64   pos;
} TempArena;

static Arena *CreateArena(rawptr buffer, isize length);
static rawptr ArenaAllocAlign(Arena *arena, isize size, isize align);
static rawptr ArenaAlloc(Arena *arena, isize size);
static void ArenaFree(Arena *arena);
static void ArenaFreeZeroed(Arena *arena);
static void DeallocArena(Arena *arena);
static Arena *CreateArenaDebug(rawptr buffer, isize length, u32 init_line_no);

// ::Allocator::FreeList::Header::

typedef enum FLNodeColor_e
{
	RB_RED,
	RB_BLACK,
} FLNodeColor;

typedef struct FLNode_t FLNode;

typedef struct FLNode_t
{
	FLNode      *parent;
	FLNode      *left;
	FLNode      *right;
	i32         value;
	rawptr      data;
	FLNodeColor color;
} FLNode;

typedef struct FreeListBuffer_t
{
	rawptr buf;
	u32 	 size;
	u32		 free_size;
} FreeListBuffer;

typedef struct FreeListAlloc_t
{
	FLNode         *head;
	FLNode         *nil;
	FreeListBuffer *buffers;
	isize          grow_size;
	u8             buf_len;
} FreeListAlloc;

static FreeListAlloc *CreateFreeListAlloc(isize init_size, isize grow_size);
static void DeallocFreeListAlloc(FreeListAlloc *alloc);
static inline b32 FLNodeInsert(FreeListAlloc *alloc, FLNode *node);
static inline void FLNodeDelete(FLNode *node);
static inline void FLNodeLeftRotate(FLNode *node);
static inline void FLNodeRightRotate(FLNode *node);
