import core.stdc.stdio : Printf = printf; import core.stdc.string : memset; alias i8 = byte; alias i16 = short; alias i32 = int; alias i64 = long; alias u8 = ubyte; alias u16 = ushort; alias u32 = uint; alias u64 = ulong; alias f32 = float; alias f64 = double; alias b32 = uint; alias usize = size_t; const DEFAULT_ALIGNMENT = (void *).sizeof * 2; version(linux) { import core.sys.posix.sys.mman; void* MemAlloc(u64 size) { return mmap(null, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); } void MemFree(void* ptr, u64 size) { assert(munmap(ptr, size) == 0, "MemFree failure"); } } void Logf(Args...)(string fmt, Args args) { try { writefln(fmt, args); } catch (Exception e) { assert(false, "Incompatible format type"); } } void Log(string str) { writeln(str); } void Log(char* str) { writeln(str); } u64 KB(u64 v) { return v * 1024; }; u64 MB(u64 v) { return KB(v) * 1024; }; u64 GB(u64 v) { return MB(v) * 1024; }; struct Node(T) { Node!(T)* next; T value; } struct SLList(T) { Node!(T)* first; Node!(T)* last; } pragma(inline): void Push(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil) { if (CheckNil(nil, list.first)) { list.first = list.last = node; node.next = nil; } else { list.last.next = node; list.last = node; node.next = nil; } } pragma(inline): bool CheckNil(T)(Node!(T)* nil, Node!(T)* node) { return node == null || node == nil; } struct Arena { u8* mem; u64 length; u64 pos; }; Arena CreateArena(u64 size) { Arena arena = { mem: cast(u8 *)MemAlloc(size), length: size, pos: 0, }; assert(arena.mem != null, "Unable to allocate memory for arena"); return arena; }; T[] AllocArray(T)(Arena* arena, u64 count) { void* mem = AllocAlign(arena, T.sizeof * count, DEFAULT_ALIGNMENT); memset(mem, 0, T.sizeof * count); return (cast(T*)mem)[0 .. count]; } T* Alloc(T)(Arena* arena) { void* mem = AllocAlign(arena, T.sizeof, DEFAULT_ALIGNMENT); memset(mem, 0, T.sizeof); return cast(T*)mem; }; void* AllocAlign(Arena* arena, u64 size, u64 alignment) { void* ptr = null; uintptr mem_pos = cast(uintptr)arena.mem; uintptr current = mem_pos + arena.pos; uintptr offset = AlignPow2(current, alignment) - mem_pos; if (offset+size <= arena.length) { ptr = &arena.mem[offset]; arena.pos = offset+size; } else { Printf("AllocAlign failure: out of memory, size requested: %llu", size); assert(0); } return ptr; }; void Reset(Arena* arena) { arena.pos = 0; } void Free(Arena* arena) { (arena.mem); }