--- /dev/null
+#ifndef VG_MEM_H
+#define VG_MEM_H
+
+#include "vg_stdint.h"
+#include "vg_platform.h"
+
+#include <stdlib.h>
+
+typedef struct vg_linear_allocator vg_linear_allocator;
+
+struct
+{
+ void *rtmemory,
+ *scratch;
+}
+static vg_mem;
+
+#pragma pack(push,1)
+struct vg_linear_allocator
+{
+ u32 size, cur;
+
+ /* allows temporarily extendable buffers */
+ void *last_alloc;
+ u32 last_alloc_size;
+};
+#pragma pack(pop)
+
+/*
+ * TODO: Fallback on libc
+ * TODO: 8 byte alignment
+ */
+
+VG_STATIC void vg_error(const char *fmt, ...);
+
+/* allocate something from a linear allocator */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_alloc( void *allocator, u32 size )
+{
+ if( allocator == NULL )
+ vg_fatal_exit_loop( "Null allocator" );
+
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ if( allocptr->cur + size > allocptr->size )
+ {
+ vg_error( "%u(current) + %u(alloc) > %u(max)\n",
+ allocptr->cur, size, allocptr->size );
+
+ vg_fatal_exit_loop( "Linear allocator out of memory" );
+ }
+
+ void *data = allocator + allocptr->cur;
+ allocptr->cur += size;
+ allocptr->last_alloc = data;
+ allocptr->last_alloc_size = size;
+
+ return data;
+}
+
+/* resize latest block of memory from linear */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_resize( void *allocator, void *data, u32 newsize )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ if( allocptr->last_alloc == data )
+ {
+ allocptr->cur -= allocptr->last_alloc_size;
+ return vg_linear_alloc( allocator, newsize );
+ }
+ else
+ {
+ vg_fatal_exit_loop( "Cannot resize this buffer anymore" );
+ }
+
+ return NULL;
+}
+
+VG_STATIC void vg_linear_del( void *allocator, void *data )
+{
+ void *ignore = vg_linear_resize( allocator, data, 0 );
+
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ allocptr->last_alloc = NULL;
+ allocptr->last_alloc_size = 0;
+}
+
+/* extend latest block of memory from linear */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_extend( void *allocator, void *data, u32 extra )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ return vg_linear_resize( allocator, data, allocptr->last_alloc_size+extra );
+}
+
+/* get the current usage of allocator */
+VG_STATIC u32 vg_linear_get_cur( void *allocator )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ return allocptr->cur;
+}
+
+/* get the capacity of allocator */
+VG_STATIC u32 vg_linear_get_capacity( void *allocator )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ return allocptr->size;
+}
+
+/* get the size of the last allocated thing */
+VG_STATIC u32 vg_linear_last_size( void *allocator )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ return allocptr->last_alloc_size;
+}
+
+/* yeet all memory from linear allocator */
+VG_STATIC void vg_linear_clear( void *allocator )
+{
+ vg_linear_allocator *allocptr = allocator;
+ allocptr --;
+
+ allocptr->last_alloc = NULL;
+ allocptr->last_alloc_size = 0;
+ allocptr->cur = 0;
+}
+
+/* allocate a FIXED SIZE linear allocator */
+VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size )
+{
+ u32 total = size + sizeof(vg_linear_allocator);
+ vg_linear_allocator *allocptr;
+
+ if( lin_alloc == NULL )
+ {
+ static int allow_once = 1;
+
+ if( allow_once )
+ {
+ allocptr = malloc( total );
+
+ if( allocptr == NULL )
+ vg_fatal_exit_loop( "Create linear: Malloc failed" );
+
+ allow_once = 0;
+ }
+ else
+ vg_fatal_exit_loop( "Shouldnt call this twice!" );
+ }
+ else
+ {
+ vg_linear_allocator *parent = lin_alloc;
+ parent --;
+
+ allocptr = vg_linear_alloc( lin_alloc, total );
+
+#if 0
+ parent->last_alloc = allocptr+1;
+ parent->last_alloc_size = total;
+#else
+ parent->last_alloc = NULL;
+ parent->last_alloc_size = total;
+#endif
+ }
+
+ allocptr->size = size;
+ allocptr->cur = 0;
+ allocptr->last_alloc = NULL;
+ allocptr->last_alloc_size = 0;
+
+ void *data = allocptr+1;
+ return data;
+}
+
+/* request all the memory we need in advance */
+VG_STATIC void vg_prealloc_quota( u32 size )
+{
+ size = VG_MAX( size, 20*1024*1024 );
+ vg_mem.rtmemory = vg_create_linear_allocator( NULL, size );
+ vg_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory, 10*1024*1024 );
+}
+
+#endif /* VG_MEM_H */