/* date = June 19th 2023 10:07 pm */

#ifndef CORE_MEMORY_H
#define CORE_MEMORY_H

////////////////////////////////
//- sixten: Common Memory Functions

static void Copy(void *Dest, void *Source, umm Count);
static void CopyReverse(void *Dest, void *Source, umm Count);
static void Fill(void *Dest, u8 Value, umm Count);
#define Move(Dest, Source, Count) memmove(Dest, Source, Count)

////////////////////////////////
//- sixten: Memory Arena Types

struct memory_arena
{
    u64 Position;
    u64 CommitPosition;
    u64 Size;
    u64 Align;
    u64 Unused[4];
};

struct temporary_memory
{
    memory_arena *Arena;
    u64 Position;
};

////////////////////////////////
//~ sixten: Memory Arena Settings
#define MEMORY_ARENA_COMMIT_SIZE        Kilobytes(4)
#define MEMORY_ARENA_DECOMMIT_THRESHOLD Megabytes(64)

////////////////////////////////
//- sixten: Memory Arena Functions

static memory_arena *ArenaAllocate(u64 Size);
static void ArenaRelease(memory_arena *Arena);
static void *ArenaPushNoClear(memory_arena *Arena, u64 Size);
static void *ArenaPush(memory_arena *Arena, u64 Size);
static void ArenaPopTo(memory_arena *Arena, u64 Position);
static void ArenaPop(memory_arena *Arena, u64 Amount);
static void ArenaClear(memory_arena *Arena);
static void ArenaSetAlign(memory_arena *Arena, u64 Align);
#define PushArray(Arena, type, Count)        (type *)ArenaPush((Arena), sizeof(type)*(Count))
#define PushArrayNoClear(Arena, type, Count) (type *)ArenaPushNoClear((Arena), sizeof(type)*(Count))
#define PushStruct(Arena, type)              (type *)ArenaPush((Arena), sizeof(type))
#define PushStructNoClear(Arena, type)       (type *)ArenaPushNoClear((Arena), sizeof(type))

////////////////////////////////
//- sixten: Temporary Memory Functions

static temporary_memory BeginTemporaryMemory(memory_arena *Arena);
static void EndTemporaryMemory(temporary_memory Temp);

#endif //CORE_MEMORY_H
