#pragma once // ------------------------------------------------------------------------ // standard library #include #include #include #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // dynamic array typedef struct bufHdr { vlong len; vlong cap; byte buf[]; } bufHdr; #define _bufHdr(s) ((bufHdr*)((uint8*)(s)-offsetof(bufHdr, buf))) #define buflen(s) ((s) ? (_bufHdr(s)->len) : 0) #define bufcap(s) ((s) ? (_bufHdr(s)->cap) : 0) #define bufend(s) ((s) + buflen(s)) #define bufsize(s) ((s) ? (buflen(s) * sizeof((s)[0])) : 0) #define buffree(s) ((s) ? (free(_bufHdr(s)), (s) = nil) : 0) #define buffit(s, n) ((n) <= bufcap(s) ? 0 : ((s) = bufgrow((s), (n), sizeof(*(s))))) #define bufresize(s, n) \ do { \ (buffit(s, n)); \ ((_bufHdr(s)->len) = (n)); \ } while (0) #define bufpush(s, ...) (buffit((s), 1 + buflen(s)), (s)[_bufHdr(s)->len++] = (__VA_ARGS__)) #define bufpop(s, i) (_bufpop((s), (i), sizeof(*(s))), (s)[_bufHdr(s)->len]) void* bufgrow(void*, vlong, vlong); void _bufpop(void*, int, vlong); // ----------------------------------------------------------------------------- // interfaces // TODO(nnoll): Think about this idea /* typedef struct Iface { void* impl; byte fcn[]; } Iface; */ // ----------------------------------------------------------------------------- // memory allocation /* allocator interface */ typedef struct mem·Allocator { void *(*alloc)(void *iface, uint n, ulong size); void (*free)(void *iface, void *ptr); } mem·Allocator; /* system implementation */ static void ·free(void* _, void* ptr) { return free(ptr); } static void *·alloc(void* _, uint n, ulong size) { return malloc(n*size); } // TODO(nnoll): Allow for nil iterfaces? static mem·Allocator mem·sys = { .alloc = ·alloc, .free = ·free }; /* simple memory arena */ typedef struct mem·Arena mem·Arena; mem·Arena *mem·newarena(mem·Allocator from, void*); void *mem·arenaalloc(mem·Arena *A, uint n, ulong size); void mem·freearena(mem·Arena *A); /* generalized memxxx functions */ void memset64(void *dst, uint64 val, uintptr size); // ----------------------------------------------------------------------------- // coroutines typedef struct Coro Coro; Coro* coro·new(uintptr stk, uintptr (*func)(Coro*, uintptr)); uintptr coro·yield(Coro *c, uintptr arg); error coro·free(Coro *c); // ----------------------------------------------------------------------------- // Strings // TODO(nnoll): Move here? typedef byte* string; typedef struct str·Hdr { vlong len; vlong cap; byte buf[]; } str·Hdr; // ------------------------------------------------------------------------- // UTF-8 functions. // Perhaps break into own unit // TODO: Add to(upper|lower|title) typedef uint32 Rune; enum { UTFmax = 4, RuneSync = 0x80, RuneSelf = 0x80, RuneErr = 0xFFFD, RuneMax = 0x10FFFF, }; /* utf8 helpers */ int utf8·fullrune(byte *s, int n); byte *utf8·findrune(byte *s, long i); int utf8·chartorune(Rune *r, byte *s); int utf8·runetochar(byte *s, Rune *r); int utf8·len(byte *s); int utf8·runelen(Rune r); int utf8·isletter(Rune r); int utf8·isdigit(Rune r); int utf8·isspace(Rune r); int utf8·istitle(Rune r); /* string helpers */ string str·newcap(const byte *s, vlong len, vlong cap); string str·newlen(const byte *s, vlong len); string str·new(const byte *s); string str·newf(const byte *fmt, ...); void str·free(string s); int str·len(const string s); int str·cap(const string s); string str·clear(string s); string str·grow(string s, vlong delta); string str·fit(string s); string str·appendcount(string s, vlong len, const byte *b); string str·append(string s, const byte* b); string str·appendf(string s, const byte* fmt, ...); string str·appendbyte(string s, const byte b); bool str·equals(const string s, const string t); int str·find(string s, const byte* substr); void str·lower(string s); void str·upper(string s); void str·replace(string s, const byte* from, const byte* to); string* str·split(string s, const byte* tok); string str·join(vlong len, byte** fields, const byte* sep); // ----------------------------------------------------------------------------- // I/O typedef FILE Stream; typedef struct stat io·Stat; enum SeekPos { seek·cur = SEEK_CUR, seek·set = SEEK_SET, seek·end = SEEK_END }; Stream *io·open(byte *name, byte *mode); int io·fd(Stream *s); error io·stat(Stream *s, io·Stat *buf); error io·close(Stream *s); byte io·getbyte(Stream *s); error io·ungetbyte(Stream *s, byte c); int io·read(Stream *s, int sz, int n, void *buf); int io·readln(Stream *s, int n, byte *buf); error io·putbyte(Stream *s, byte c); int io·putstring(Stream *s, string str); int io·write(Stream *s, int sz, int n, void *buf); int io·flush(Stream *s); int io·seek(Stream *s, long off, enum SeekPos whence); /* generic I/O interfaces */ typedef struct io·Reader { int (*read)(void*, int sz, int n, void *buf); } io·Reader; typedef struct io·LineReader { int (*readln)(void*, int n, void *buf); } io·LineReader; typedef struct io·Peeker { byte (*get)(void*); error (*unget)(void*, byte); } io·Peeker; typedef struct io·FullReader { io·Reader; io·Peeker; } io·FullReader; typedef struct io·Writer { int (*write)(void*, int sz, int n, void *buf); } io·Writer; typedef struct io·Putter { error (*put)(void*, byte); int (*putstr)(void*, string); } io·Putter; typedef struct io·FullWriter { io·Writer; io·Putter; } io·FullWriter; typedef struct io·ReadWriter { io·Reader; io·Writer; } io·ReadWriter; // ----------------------------------------------------------------------------- // memory mapped files typedef struct mmap·Reader { vlong len; void* buf; } mmap·Reader; mmap·Reader mmap·open(byte *name); error mmap·close(mmap·Reader rdr); // ----------------------------------------------------------------------------- // libflate // NOTE: Experimental! typedef struct flate·Reader flate·Reader; typedef struct flate·Writer flate·Writer; flate·Reader *flate·newreader(io·Reader rdr, void* r, mem·Allocator mem, void* m); int flate·read(flate·Reader *rdr, int sz, int n, void *buf); error flate·freereader(flate·Reader *rdr); flate·Writer *flate·newwriter(io·Writer wtr, void* w, mem·Allocator mem, void* m); error flate·freewriter(flate·Writer *wtr); int flate·write(flate·Writer *wtr, int sz, int n, void *buf); // ----------------------------------------------------------------------------- // libgz typedef void gz·Stream; gz·Stream* gz·open(byte *path, byte *mode); error gz·close(gz·Stream* s); int gz·read(gz·Stream *s, int sz, int n, void* buf); int gz·readln(gz·Stream *s, int n, byte *buf); byte gz·getbyte(gz·Stream *s); error gz·ungetbyte(gz·Stream *s, byte c); int gz·write(gz·Stream *s, int sz, int n, void* buf); error gz·putbyte(gz·Stream *s, byte str); error gz·putstring(gz·Stream *s, byte *str); int gz·printf(gz·Stream *s, byte *fmt, ...); error gz·flush(gz·Stream *s); vlong gz·seek(gz·Stream *s, long off, enum SeekPos whence); // ----------------------------------------------------------------------------- // error handling functions void errorf(const byte* fmt, ...); #define panicf(...) (errorf(__VA_ARGS__), assert(0)) // ----------------------------------------------------------------------------- // sorting void sort·ints(uintptr n, int arr[]); void sort·int8s(uintptr n, int8 arr[]); void sort·int16s(uintptr n, int16 arr[]); void sort·int32s(uintptr n, int32 arr[]); void sort·int64s(uintptr n, int64 arr[]); void sort·uints(uintptr n, uint arr[]); void sort·uint8s(uintptr n, uint8 arr[]); void sort·uint16s(uintptr n, uint16 arr[]); void sort·uint32s(uintptr n, uint32 arr[]); void sort·uint64s(uintptr n, uint64 arr[]); void sort·floats(uintptr n, float arr[]); void sort·doubles(uintptr n, double arr[]); void sort·strings(uintptr n, byte* arr[]);