static int exec_plus(strm_state* state, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_str_p(*args)) { strm_string *str1 = strm_value_str(args[0]); strm_string *str2 = strm_value_str(args[1]); strm_string *str3 = strm_str_new(NULL, str1->len + str2->len); char *p; p = (char*)str3->ptr; memcpy(p, str1->ptr, str1->len); memcpy(p+str1->len, str2->ptr, str2->len); p[str3->len] = '\0'; *ret = strm_ptr_value(str3); return STRM_OK; } if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])+strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])+strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static int exec_plus(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_string_p(*args)) { strm_string str1 = strm_value_str(args[0]); strm_string str2 = strm_value_str(args[1]); strm_string str3 = strm_str_new(NULL, strm_str_len(str1) + strm_str_len(str2)); char *p; p = (char*)strm_str_ptr(str3); memcpy(p, strm_str_ptr(str1), strm_str_len(str1)); memcpy(p+strm_str_len(str1), strm_str_ptr(str2), strm_str_len(str2)); p[strm_str_len(str3)] = '\0'; *ret = strm_str_value(str3); return STRM_OK; } if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])+strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])+strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
strm_string strm_inspect(strm_value v) { if (strm_string_p(v)) { strm_string str = strm_value_str(v); return str_dump(str, str_dump_len(str)); } else if (strm_array_p(v)) { char *buf = malloc(32); strm_int i, bi = 0, capa = 32; strm_array a = strm_value_ary(v); for (i=0; i<strm_ary_len(a); i++) { strm_string str = strm_inspect(strm_ary_ptr(a)[i]); strm_string key = (strm_ary_headers(a) && strm_string_p(strm_ary_ptr(strm_ary_headers(a))[i])) ? strm_value_str(strm_ary_ptr(strm_ary_headers(a))[i]) : strm_str_null; strm_int slen = (key ? (strm_str_len(key)+1) : 0) + strm_str_len(str) + 3; if (bi+slen > capa) { capa *= 2; buf = realloc(buf, capa); } if (bi == 0) { buf[bi++] = '['; } else { buf[bi++] = ','; buf[bi++] = ' '; } if (key) { if (!str_symbol_p(key)) { key = str_dump(key, str_dump_len(key)); } memcpy(buf+bi, strm_str_ptr(key), strm_str_len(key)); bi += strm_str_len(key); buf[bi++] = ':'; } memcpy(buf+bi, strm_str_ptr(str), strm_str_len(str)); bi += strm_str_len(str); } buf[bi++] = ']'; return strm_str_new(buf, bi); } else { return strm_to_str(v); } }
static int str_length(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { strm_int len; if (argc != 1) return STRM_NG; len = strm_str_len(strm_value_str(args[0])); *ret = strm_int_value(len); return STRM_OK; }
static int exec_fwrite(strm_state* state, int argc, strm_value* args, strm_value* ret) { int fd; strm_string *path; assert(argc == 1); assert(strm_str_p(args[0])); path = strm_value_str(args[0]); fd = open(path->ptr, O_WRONLY|O_CREAT, 0644); if (fd < 0) return STRM_NG; *ret = strm_ptr_value(strm_io_new(fd, STRM_IO_WRITE)); return STRM_OK; }
static int exec_fread(strm_state* state, int argc, strm_value* args, strm_value* ret) { int fd; strm_string *path; assert(argc == 1); assert(strm_str_p(args[0])); path = strm_value_str(args[0]); fd = open(path->ptr, O_RDONLY); if (fd < 0) return STRM_NG; *ret = strm_ptr_value(strm_io_new(fd, STRM_IO_READ)); return STRM_OK; }
static int exec_fwrite(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { int fd; strm_string path; char buf[7]; assert(argc == 1); assert(strm_string_p(args[0])); path = strm_value_str(args[0]); fd = open(strm_str_cstr(path, buf), O_WRONLY|O_CREAT, 0644); if (fd < 0) return STRM_NG; *ret = strm_io_new(fd, STRM_IO_WRITE); return STRM_OK; }
static int ary_get(strm_stream* strm, strm_value ary, int argc, strm_value* argv, strm_value* ret) { struct strm_array* a; strm_value idx; if (argc != 1) { strm_raise(strm, "wrong number of arguments"); return STRM_NG; } a = strm_ary_struct(ary); idx = argv[0]; if (strm_num_p(idx)) { strm_int i = strm_value_int(idx); if (i>=a->len) return STRM_NG; *ret = a->ptr[i]; return STRM_OK; } if (strm_string_p(idx)) { if (a->headers) { strm_int i, len = a->len; for (i=0; i<len; i++) { if (strm_str_eq(strm_value_str(idx), strm_value_str(strm_ary_ptr(a->headers)[i]))) { *ret = a->ptr[i]; return STRM_OK; } } } } return STRM_NG; }
strm_string strm_to_str(strm_value v) { char buf[32]; int n; strm_state* ns = strm_value_ns(v); if (ns) { strm_value m; n = strm_var_get(ns, strm_str_intern_lit("string"), &m); if (n == STRM_OK) { n = strm_funcall(NULL, m, 1, &v, &m); if (n == STRM_OK && strm_string_p(m)) return m; } } switch (strm_value_tag(v)) { case STRM_TAG_INT: n = sprintf(buf, "%d", strm_to_int(v)); return strm_str_new(buf, n); case STRM_TAG_BOOL: n = sprintf(buf, strm_to_int(v) ? "true" : "false"); return strm_str_new(buf, n); case STRM_TAG_CFUNC: n = sprintf(buf, "<cfunc:%p>", (void*)strm_value_cfunc(v)); return strm_str_new(buf, n); case STRM_TAG_STRING_I: case STRM_TAG_STRING_6: case STRM_TAG_STRING_O: case STRM_TAG_STRING_F: return strm_value_str(v); case STRM_TAG_ARRAY: case STRM_TAG_STRUCT: return strm_inspect(v); case STRM_TAG_PTR: if (strm_value_val(v) == 0) return strm_str_lit("nil"); else { void *p = strm_ptr(v); switch (strm_ptr_type(p)) { case STRM_PTR_STREAM: n = sprintf(buf, "<stream:%p>", p); break; case STRM_PTR_IO: { strm_io io = (strm_io)p; char *mode; switch (io->mode & 3) { case STRM_IO_READ: mode = "r"; break; case STRM_IO_WRITE: mode = "w"; break; case STRM_IO_READ|STRM_IO_WRITE: mode = "rw"; break; default: mode = "?"; break; } n = sprintf(buf, "<io: fd=%d mode=%s>", io->fd, mode); break; } case STRM_PTR_LAMBDA: n = sprintf(buf, "<lambda:%p>", p); break; case STRM_PTR_AUX: n = sprintf(buf, "<obj:%p>", p); break; } return strm_str_new(buf, n); } default: if (strm_flt_p(v)) { n = sprintf(buf, "%.14g", strm_to_flt(v)); return strm_str_new(buf, n); } n = sprintf(buf, "<%p>", strm_value_vptr(v)); return strm_str_new(buf, n); } /* not reached */ return strm_str_null; }
strm_string strm_to_str(strm_value v) { char buf[32]; int n; switch (strm_value_tag(v)) { case STRM_TAG_INT: n = sprintf(buf, "%d", strm_to_int(v)); return strm_str_new(buf, n); case STRM_TAG_BOOL: n = sprintf(buf, strm_to_int(v) ? "true" : "false"); return strm_str_new(buf, n); case STRM_TAG_CFUNC: n = sprintf(buf, "<cfunc:%p>", (void*)strm_value_cfunc(v)); return strm_str_new(buf, n); case STRM_TAG_STRING_I: case STRM_TAG_STRING_6: case STRM_TAG_STRING_O: case STRM_TAG_STRING_F: return strm_value_str(v); case STRM_TAG_ARRAY: case STRM_TAG_STRUCT: return strm_inspect(v); case STRM_TAG_PTR: if (strm_value_val(v) == 0) return strm_str_new("nil", 3); else { void *p = strm_ptr(v); switch (strm_ptr_type(p)) { case STRM_PTR_TASK: n = sprintf(buf, "<task:%p>", p); break; case STRM_PTR_IO: { strm_io io = (strm_io)p; char *mode; switch (io->mode & 3) { case STRM_IO_READ: mode = "r"; break; case STRM_IO_WRITE: mode = "w"; break; case STRM_IO_READ|STRM_IO_WRITE: mode = "rw"; break; } n = sprintf(buf, "<io: fd=%d mode=%s>", io->fd, mode); break; } case STRM_PTR_LAMBDA: n = sprintf(buf, "<lambda:%p>", p); break; case STRM_PTR_MISC: n = sprintf(buf, "<obj:%p>", p); break; } return strm_str_new(buf, n); break; } default: if (strm_flt_p(v)) { n = sprintf(buf, "%g", strm_to_flt(v)); return strm_str_new(buf, n); } n = sprintf(buf, "<%p>", strm_value_vptr(v)); return strm_str_new(buf, n); } /* not reached */ return strm_str_null; }
static int str_split(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { strm_string str; strm_string sep; const char* s; strm_int slen; const char* t; const char* p; const char* pend; char c; strm_int n = 0; strm_array ary; strm_value* sps; strm_int i; switch (argc) { case 1: str = args[0]; sep = strm_str_lit(" "); break; case 2: str = args[0]; if (!strm_string_p(args[1])) { strm_raise(strm, "need string separator"); return STRM_NG; } sep = strm_value_str(args[1]); break; default: strm_raise(strm, "wrong number of arguments"); return STRM_NG; } /* count number of split strings */ s = strm_str_ptr(sep); slen = strm_str_len(sep); c = s[0]; t = p = strm_str_ptr(str); pend = p + strm_str_len(str) - slen; n = 0; while (p<pend) { if (*p == c) { if (memcmp(p, s, slen) == 0) { if (!(slen == 1 && c == ' ' && (p-t) == 0)) { n++; } t = p + slen; } } p++; } n++; /* actual split */ ary = strm_ary_new(NULL, n); sps = strm_ary_ptr(ary); s = strm_str_ptr(sep); slen = strm_str_len(sep); c = s[0]; t = p = strm_str_ptr(str); pend = p + strm_str_len(str) - slen; i = 0; while (p<pend) { if (*p == c) { if (memcmp(p, s, slen) == 0) { if (!(slen == 1 && c == ' ' && (p-t) == 0)) { sps[i++] = strm_str_new(t, p-t); } t = p + slen; } } p++; } pend = strm_str_ptr(str) + strm_str_len(str); sps[i++] = strm_str_new(t, pend-t); *ret = strm_ary_value(ary); return STRM_OK; }
static int csv_accept(strm_stream* strm, strm_value data) { strm_array ary; strm_string line = strm_value_str(data); strm_value *bp; const char *fbeg; const char *ptr; const char *pend; int fieldcnt; int in_quote = 0, all_str = 1; int i = 0; enum csv_type ftype; enum csv_type* types; struct csv_data *cd = strm->data; if (cd->prev) { strm_int len = strm_str_len(cd->prev)+strm_str_len(line)+1; char* tmp = malloc(len); memcpy(tmp, strm_str_ptr(cd->prev), strm_str_len(cd->prev)); *(tmp+strm_str_len(cd->prev)) = '\n'; memcpy(tmp+strm_str_len(cd->prev)+1, strm_str_ptr(line), strm_str_len(line)); line = strm_str_new(tmp, len); free(tmp); cd->prev = strm_str_null; } fieldcnt = count_fields(line); if (fieldcnt == -1) { cd->prev = line; return STRM_NG; } if (cd->n > 0 && fieldcnt != cd->n) return STRM_NG; ptr = strm_str_ptr(line); pend = ptr + strm_str_len(line); ary = strm_ary_new(NULL, fieldcnt); if (!ary) return STRM_NG; bp = (strm_value*)strm_ary_ptr(ary); types = cd->types; ftype = types ? types[0] : TYPE_UNSPC; for (fbeg=ptr; ptr<pend; ptr++) { if (in_quote) { if (*ptr == '\"') { if (ptr[1] == '\"') { ptr++; ftype = TYPE_ESC; continue; } in_quote = 0; } continue; } switch(*ptr) { case '\"': in_quote = 1; if (ptr == fbeg) { ftype = TYPE_STR; fbeg = ptr+1; } else { ftype = TYPE_ESC; } continue; case ',': *bp = csv_value(fbeg, ptr-fbeg, ftype); if (!strm_string_p(*bp)) all_str = 0; bp++; fbeg = ptr+1; i++; ftype = types ? types[i] : TYPE_UNSPC; break; default: continue; } } /* trim newline at the end */ if (ptr[-1] == '\n') { ptr--; } /* trim carriage return at the end */ if (ptr[-1] == '\r') { ptr--; } *bp = csv_value(fbeg, ptr-fbeg, ftype); if (!strm_string_p(*bp)) all_str = 0; /* check headers */ if (!cd->headers && !cd->types) { if (all_str) { cd->headers = ary; ary = strm_ary_null; } cd->n = fieldcnt; } if (ary) { /* set headers if any */ if (cd->headers) strm_ary_headers(ary) = cd->headers; if (!cd->types) { /* first data line (after optinal header line) */ if (cd->headers) { if (all_str) { /* data line is all string; emit header line */ strm_emit(strm, strm_ary_value(cd->headers), NULL); cd->headers = strm_ary_null; } else { /* intern header strings */ strm_array h = cd->headers; strm_value *p = strm_ary_ptr(h); int i; for (i=0; i<strm_ary_len(h); i++) { strm_string str = strm_value_str(p[i]); p[i] = strm_str_value(strm_str_intern_str(str)); } } } /* initialize types (determined by first data line) */ cd->types = malloc(sizeof(enum csv_type)*fieldcnt); if (!cd->types) return STRM_NG; for (i=0; i<fieldcnt; i++) { cd->types[i] = csv_type(strm_ary_ptr(ary)[i]); } } else { /* type check */ for (i=0; i<fieldcnt; i++) { if (cd->types[i] != csv_type(strm_ary_ptr(ary)[i])) { /* type mismatch (error); skip this line */ strm_raise(strm, "csv type mismatch"); return STRM_NG; } } } strm_emit(strm, strm_str_value(ary), NULL); } return STRM_OK; }
static void csv_accept(strm_task* task, strm_value data) { strm_array *ary; strm_string *line = strm_value_str(data); strm_value *bp; char *tmp, *tptr; const char *ptr; const char *pend; int fieldcnt, len; int in_quote = 0, quoted = 0, all_str = 1;; struct csv_data *cd = task->data; if (cd->prev) { strm_string *str = strm_str_new(NULL, cd->prev->len+line->len+1); tmp = (char*)str->ptr; memcpy(tmp, cd->prev->ptr, cd->prev->len); *(tmp+cd->prev->len) = '\n'; memcpy(tmp+cd->prev->len+1, line->ptr, line->len); line = str; cd->prev = NULL; } fieldcnt = count_fields(line); if (fieldcnt == -1) { cd->prev = line; return; } if (cd->n > 0 && fieldcnt != cd->n) return; ptr = line->ptr; pend = ptr + line->len; ary = strm_ary_new(NULL, fieldcnt); if (!ary) return; bp = (strm_value*)ary->ptr; len = line->len; tmp = malloc(len+1); if (!tmp) return; *tmp='\0'; ptr=line->ptr; tptr=tmp; for (;ptr<pend; ptr++) { if (in_quote) { if (*ptr == '\"') { if (ptr[1] == '\"') { *tptr++ = '\"'; ptr++; continue; } in_quote = 0; } else *tptr++ = *ptr; continue; } switch(*ptr) { case '\"': in_quote = 1; quoted = 1; continue; case ',': if (quoted) { *bp = strm_str_value(tmp, tptr-tmp); } else { *bp = csv_value(tmp, tptr-tmp); } if (!strm_str_p(*bp)) all_str = 0; bp++; tptr = tmp; quoted = 0; break; default: *tptr++ = *ptr; continue; } } /* trim newline at the end */ if (tptr > tmp && tptr[-1] == '\n') { tptr--; } /* trim carriage return at the end */ if (tptr > tmp && tptr[-1] == '\r') { tptr--; } *bp = csv_value(tmp, tptr-tmp); if (!strm_str_p(*bp)) all_str = 0; free(tmp); /* check headers */ if (!cd->headers && !cd->types) { if (all_str) { cd->headers = ary; ary = NULL; } cd->n = fieldcnt; } if (ary) { int i; /* set headers if any */ if (cd->headers) ary->headers = cd->headers; if (!cd->types) { /* first data line (after optinal header line) */ if (cd->headers) { if (all_str) { /* data line is all string; emit header line */ strm_emit(task, strm_ptr_value(cd->headers), NULL); cd->headers = NULL; } else { /* intern header strings */ strm_array *h = cd->headers; strm_value *p = (strm_value*)h->ptr; int i; for (i=0; i<h->len; i++) { strm_string *str = strm_value_str(p[i]); p[i] = strm_ptr_value(strm_str_intern_str(str)); } } } /* initialize types (determined by first data line) */ cd->types = malloc(sizeof(enum csv_type)*fieldcnt); if (!cd->types) return; for (i=0; i<fieldcnt; i++) { cd->types[i] = csv_type(ary->ptr[i]); } } else { /* type check */ for (i=0; i<fieldcnt; i++) { if (cd->types[i] != csv_type(ary->ptr[i])) { if (cd->types[i] == STRING_TYPE) { /* convert value to string */ ((strm_value*)ary->ptr)[i] = strm_ptr_value(strm_to_str(ary->ptr[i])); } else { /* type mismatch (error); skip this line */ return; } } } } strm_emit(task, strm_ptr_value(ary), NULL); } }