#pragma once // ------------------------------------------------------------------------ // standard library #include #include #include #include #include #include #include #include #include #include #include #include #include typedef wchar_t wchar; // ---------------------------------------------------------------------------- // dynamic array typedef struct BufHdr { vlong len; vlong cap; byte buf[]; } BufHdr; #define bufhdr(b) ((BufHdr*)((uint8*)(b)-offsetof(BufHdr, buf))) #define buflen(b) ((b) ? (bufhdr(b)->len) : 0) #define bufcap(b) ((b) ? (bufhdr(b)->cap) : 0) #define bufend(b) ((b) + buflen(b)) #define bufsize(b) ((b) ? (buflen(b) * sizeof((b)[0])) : 0) #define buffree(b) ((b) ? (free(bufhdr(b)), (b) = nil) : 0) #define buffit(b, n) ((n) <= bufcap(b) ? 0 : ((b) = ·bufgrow((b), (n), sizeof(*(b))))) #define bufpush(b, ...) (buffit((b), 1 + buflen(b)), (b)[bufhdr(b)->len++] = (__VA_ARGS__)) #define bufaddn(b, n) (buffit(b, buflen(b)+n), bufhdr(b)->len += n, b+bufhdr(b)->len-n) #define bufpop(b) ((b)[--bufhdr(b)->len]) #define bufdel(b, i) bufdeln((b), (i), 1) #define bufdeln(b, i, n) (memmove((b)+(i), (b)+(i)+(n), sizeof(*(b))*(bufhdr(b)->len-(n)-(i)), bufhdr(b)->len -= (n)) #define bufdelswap(b, i) ((b)[i] = bufend(b)[-1], bufhdr(b)->len-=1) void* ·bufgrow(void*, vlong, vlong); // ----------------------------------------------------------------------------- // memory allocation // TODO(nnoll): Allow for nil iterfaces? /* allocator interface */ typedef struct mem·Allocator { void *(*alloc)(void *heap, uint n, ulong size); void (*free)(void *heap, void *ptr); } mem·Allocator; extern mem·Allocator sys·Memory; typedef struct mem·Reallocator { void *(*alloc)(void *iface, uint n, ulong size); void *(*realloc)(void *iface, void *ptr, uint n, ulong size); void (*free)(void *iface, void *ptr); } mem·Reallocator; extern mem·Reallocator sys·Relocator; /* simple memory arena */ typedef struct mem·Arena mem·Arena; mem·Arena *mem·makearena(mem·Allocator from, void*); void *mem·arenaalloc(mem·Arena *A, uint n, ulong size); void mem·freearena(mem·Arena *A); extern mem·Allocator mem·ArenaAllocator; /* generalized memxxx functions */ void memset64(void *dst, uint64 val, uintptr size); // ----------------------------------------------------------------------------- // coroutines typedef struct Coro Coro; Coro* coro·make(uintptr stk, uintptr (*func)(Coro*, uintptr)); uintptr coro·yield(Coro *c, uintptr arg); error coro·free(Coro *c); // ----------------------------------------------------------------------------- // strings typedef byte* string; /* string helpers */ string str·makecap(const byte *s, vlong len, vlong cap); string str·makelen(const byte *s, vlong len); string str·make(const byte *s); string str·makef(const byte *fmt, ...); void str·free(string s); int str·len(const string s); int str·cap(const string s); void str·clear(string *s); void str·grow(string *s, vlong delta); void str·fit(string *s); int str·appendlen(string *s, vlong len, const byte *b); int str·append(string *s, const byte* b); int str·appendf(string *s, const byte* fmt, ...); int 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); int str·read(string s, int size, int n, void *buf); 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 io·Stream; typedef struct stat io·Stat; enum SeekPos { seek·cur = SEEK_CUR, seek·set = SEEK_SET, seek·end = SEEK_END }; /* XXX: change casing */ enum { ReadOK = R_OK, WriteOK = W_OK, ExecOK = X_OK, }; /* file handling */ io·Stream *io·open(byte *name, byte *mode); int io·fd(io·Stream *s); error io·stat(io·Stream *s, io·Stat *buf); error io·close(io·Stream *s); byte io·getbyte(io·Stream *s); error io·ungetbyte(io·Stream *s, byte c); int io·read(io·Stream *s, int sz, int n, void *buf); int io·readln(io·Stream *s, int n, byte *buf); error io·putbyte(io·Stream *s, byte c); int io·putstring(io·Stream *s, string str); int io·write(io·Stream *s, int sz, int n, void *buf); int io·flush(io·Stream *s); int io·seek(io·Stream *s, long off, enum SeekPos whence); long io·tell(io·Stream *s); /* basic os helpers */ int os·exists(byte *path, int flag); byte *os·basename(byte *path); int os·sep(void); /* io interfaces */ typedef struct io·Reader { int (*read)(void*, int sz, int n, void *buf); } io·Reader; extern io·Reader sys·Reader; typedef struct io·Peeker { byte (*get)(void*); error (*unget)(void*, byte); } io·Peeker; extern io·Peeker sys·Peeker; typedef struct io·Seeker { int (*seek)(void *skr, long off, enum SeekPos whence); long (*tell)(void *skr); } io·Seeker; extern io·Seeker sys·Seeker; typedef struct io·SeekReader { io·Seeker; io·Reader; } io·SeekReader; extern io·SeekReader sys·SeekReader; typedef struct io·PeekReader { io·Reader; io·Peeker; } io·PeekReader; extern io·PeekReader sys·PeekReader; typedef struct io·Writer { int (*write)(void*, int sz, int n, void *buf); } io·Writer; extern io·Writer sys·Writer; typedef struct io·Putter { error (*put) (void*, byte); int (*puts)(void*, string); } io·Putter; extern io·Putter sys·Putter; typedef struct io·PutWriter { io·Writer; io·Putter; } io·PutWriter; extern io·PutWriter sys·PutWriter; typedef struct io·ReadWriter { io·Reader; io·Writer; } io·ReadWriter; extern io·ReadWriter sys·ReadWriter; /* buffered i/o */ typedef struct io·Buffer io·Buffer; enum { bufio·size = 2*4096, bufio·ungets = 8, bufio·eof = -1, bufio·err = -2, bufio·nil = 1 << 0, bufio·rdr = 1 << 1, bufio·wtr = 1 << 2, bufio·end = 1 << 3, }; struct io·Buffer { int state; int runesize; void *h; union { io·Reader rdr; io·Writer wtr; }; vlong size; byte *beg, *pos, *end; byte buf[bufio·size + bufio·ungets]; }; error bufio·initreader(io·Buffer *buf, io·Reader rdr, void *h); void bufio·finireader(io·Buffer *buf); int bufio·getbyte(io·Buffer *buf); error bufio·ungetbyte(io·Buffer *buf, byte c); int bufio·read(io·Buffer *buf, int sz, int n, void *out); // ----------------------------------------------------------------------------- // memory mapped files typedef struct mmap·Reader { vlong len; union { byte *buf; ubyte *ubuf; }; } mmap·Reader; mmap·Reader mmap·open(byte *name); error mmap·close(mmap·Reader rdr); // ----------------------------------------------------------------------------- // filesystem #define iota(x) 1 << (x) enum { fs·preorder = iota(0), fs·nolinks = iota(1), fs·verbose = iota(2), }; #undef iota typedef struct fs·Walker fs·Walker; typedef struct fs·History fs·History; struct fs·Walker { int fd, lev, max, err; uchar flags : 4; fs·History *hist; struct { void *data; int (*func)(void *data, char *relp, char *absp, io·Stat* info); }; char *base, *end, path[4096]; }; int fs·init(fs·Walker *, char *path); void fs·fini(fs·Walker *); void fs·walk(fs·Walker *); // ----------------------------------------------------------------------------- // libflate // NOTE: Experimental! typedef struct flate·Reader flate·Reader; typedef struct flate·Writer flate·Writer; flate·Reader *flate·openreader(io·Reader rdr, void* r, mem·Allocator mem, void* m); int flate·read(flate·Reader *rdr, int sz, int n, void *buf); error flate·closereader(flate·Reader *rdr); flate·Writer *flate·openwriter(io·Writer wtr, void* w, mem·Allocator mem, void* m); int flate·write(flate·Writer *wtr, int sz, int n, void *buf); error flate·closewriter(flate·Writer *wtr); // ----------------------------------------------------------------------------- // libgz typedef void gz·Stream; /* interfaces */ extern io·Reader gz·Reader; extern io·Peeker gz·Peeker; extern io·Seeker gz·Seeker; extern io·SeekReader gz·SeekReader; extern io·PeekReader gz·PeekReader; extern io·Writer gz·Writer; extern io·Putter gz·Putter; extern io·PutWriter gz·PutWriter; extern io·ReadWriter gz·ReadWriter; 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); int gz·seek(gz·Stream *s, long off, enum SeekPos whence); long gz·tell(gz·Stream *s); // ----------------------------------------------------------------------------- // libjson // NOTE: Experimental! // ----------------------------------------------------------------------------- // error handling functions void exits(char *s); void errorf(byte* fmt, ...); void verrorf(byte* fmt, va_list args); void panicf(byte *fmt, ...); void vpanicf(byte *fmt, va_list args); // ----------------------------------------------------------------------------- // 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[]); // ----------------------------------------------------------------------------- // fast random number generation error rng·init(uint64 seed); double rng·random(void); double rng·exponential(double lambda); bool rng·bernoulli(double f); uint64 rng·randi(int max); uint64 rng·poisson(double mean); // ----------------------------------------------------------------------------- // variable arguments /* from plan9 libc */ #define ERRMAX 128 /* max length of error string */ #define SET(x) ((x)=0) #define USED(x) if(x){}else{} #ifdef __GNUC__ # if __GNUC__ >= 3 # undef USED # define USED(x) ((void)(x)) # endif #endif extern char *argv0; int arg·bytetorune(uint32*, byte *); #define ARGBEGIN for((argv0?0:(argv0=*argv)),argv++,argc--; \ argv[0] && argv[0][0]=='-' && argv[0][1]; \ argc--, argv++) { \ byte *_args, *_argt; \ uint32 _argc; \ _args = &argv[0][1]; \ if(_args[0]=='-' && _args[1]==0){ \ argc--; argv++; break; \ } \ _argc = 0; \ while(*_args && (_args += arg·bytetorune(&_argc, _args)))\ switch(_argc) #define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc); #define ARGF() (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) #define EARGF(x) (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) #define ARGC() _argc