static int equal(naRef a, naRef b) { if(IS_NUM(a)) return a.num == b.num; if(PTR(a).obj == PTR(b).obj) return 1; if(naStr_len(a) != naStr_len(b)) return 0; return memcmp(naStr_data(a), naStr_data(b), naStr_len(a)) == 0; }
static naRef f_open(naContext c, naRef me, int argc, naRef* args) { FILE* f; naRef file = argc > 0 ? naStringValue(c, args[0]) : naNil(); naRef mode = argc > 1 ? naStringValue(c, args[1]) : naNil(); if(!IS_STR(file)) naRuntimeError(c, "bad argument to open()"); f = fopen(naStr_data(file), IS_STR(mode) ? naStr_data(mode) : "rb"); if(!f) naRuntimeError(c, strerror(errno)); return naIOGhost(c, f); }
static naRef f_write(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc > 0 ? ioghost(args[0]) : 0; naRef str = argc > 1 ? args[1] : naNil(); if(!g || !IS_STR(str)) naRuntimeError(c, "bad argument to write()"); return naNum(g->type->write(c, g->handle, naStr_data(str), naStr_len(str))); }
static naRef f_setfld(naContext c, naRef me, int argc, naRef* args) { naRef s = argc > 0 ? args[0] : naNil(); int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1; int len = argc > 2 ? (int)naNumValue(args[2]).num : -1; naRef val = argc > 3 ? naNumValue(args[3]) : naNil(); if(!argc || !MUTABLE(args[0])|| bit < 0 || len < 0 || IS_NIL(val)) naRuntimeError(c, "missing/bad argument to setfld"); setfld(c, (void*)naStr_data(s), naStr_len(s), bit, len, (unsigned int)val.num); return naNil(); }
static naRef f_read(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc > 0 ? ioghost(args[0]) : 0; naRef str = argc > 1 ? args[1] : naNil(); naRef len = argc > 2 ? naNumValue(args[2]) : naNil(); if(!g || !MUTABLE(str) || !IS_NUM(len)) naRuntimeError(c, "bad argument to read()"); if(naStr_len(str) < (int)len.num) naRuntimeError(c, "string not big enough for read"); return naNum(g->type->read(c, g->handle, naStr_data(str), (int)len.num)); }
static unsigned int refhash(naRef key) { if(IS_STR(key)) { struct naStr* s = PTR(key).str; if(s->hashcode) return s->hashcode; return s->hashcode = hash32((void*)naStr_data(key), naStr_len(key)); } else { /* must be a number */ union { double d; unsigned int u[2]; } n; n.d = key.num == -0.0 ? 0.0 : key.num; /* remember negative zero! */ return mix32(mix32(n.u[0]) ^ n.u[1]); } }
static naRef dofld(naContext c, int argc, naRef* args, int sign) { naRef s = argc > 0 ? args[0] : naNil(); int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1; int len = argc > 2 ? (int)naNumValue(args[2]).num : -1; unsigned int f; if(!naIsString(s) || !MUTABLE(args[0]) || bit < 0 || len < 0) naRuntimeError(c, "missing/bad argument to fld/sfld"); f = fld(c, (void*)naStr_data(s), naStr_len(s), bit, len); if(!sign) return naNum(f); if(f & (1 << (len-1))) f |= ~((1<<len)-1); // sign extend return naNum((signed int)f); }
static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args) { int n=0; struct stat s; naRef result, path = argc > 0 ? naStringValue(ctx, args[0]) : naNil(); if(!IS_STR(path)) naRuntimeError(ctx, "bad argument to stat()"); if(stat(naStr_data(path), &s) < 0) { if(errno == ENOENT) return naNil(); naRuntimeError(ctx, strerror(errno)); } result = naNewVector(ctx); naVec_setsize(result, 12); #define FLD(x) naVec_set(result, n++, naNum(s.st_##x)); FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid); FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime); #undef FLD naVec_set(result, n++, ftype(ctx, s.st_mode)); return result; }