/** * key同士を比較 */ static int mapentry_cmp(Value *vret, Value *v, RefNode *node) { Value v1 = v[0]; Value v2 = v[1]; Value vr; Value_push("vv", Value_ref(v1)->v[INDEX_ENTRY_KEY], Value_ref(v2)->v[INDEX_ENTRY_KEY]); if (!call_member_func(fs->symbol_stock[T_CMP], 1, TRUE)) { return FALSE; } vr = fg->stk_top[-1]; if (Value_isint(vr) && Value_integral(vr) == 0) { Value_pop(); // keyが同じなら、valueを比較 Value_push("vv", Value_ref(v1)->v[INDEX_ENTRY_VAL], Value_ref(v2)->v[INDEX_ENTRY_VAL]); if (!call_member_func(fs->symbol_stock[T_CMP], 1, TRUE)) { return FALSE; } } *vret = fg->stk_top[-1]; fg->stk_top--; return TRUE; }
/* * 最初の行の最初の列だけ取得 */ static int conn_single(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); sqlite3 *conn = Value_ptr(r->v[INDEX_SQLITE_CONN]); sqlite3_stmt *stmt = NULL; if (!conn_prepare_sub(&stmt, conn, v)) { return FALSE; } if (stmt != NULL) { int result = sqlite3_step(stmt); if (result == SQLITE_ROW) { *vret = cursor_get_sub(stmt, 0); sqlite3_finalize(stmt); } else if (result == SQLITE_ERROR_USER) { fs->throw_errorf(mod_sqlite, "SQLiteError", "%s", sqlite3_errmsg(conn)); return FALSE; } else { sqlite3_finalize(stmt); } } return TRUE; }
static int conn_exec(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); sqlite3 *conn = Value_ptr(r->v[INDEX_SQLITE_CONN]); int result; int count; sqlite3_stmt *stmt = NULL; if (!conn_prepare_sub(&stmt, conn, v)) { return FALSE; } result = sqlite3_step(stmt); if (result != SQLITE_DONE && result != SQLITE_ROW) { // ??? if (result != SQLITE_ERROR_USER) { fs->throw_errorf(mod_sqlite, "SQLiteError", "%s", sqlite3_errmsg(conn)); return FALSE; } //return FALSE; } count = sqlite3_changes(conn); sqlite3_finalize(stmt); *vret = int32_Value(count); return TRUE; }
static int matrix_marshal_write(Value *vret, Value *v, RefNode *node) { const RefMatrix *mat = Value_vp(*v); Value w = Value_ref(v[1])->v[INDEX_MARSHALDUMPER_SRC]; uint8_t *data; int size; int i; if (!fs->stream_write_uint32(w, mat->cols)) { return FALSE; } if (!fs->stream_write_uint32(w, mat->rows)) { return FALSE; } size = mat->cols * mat->rows; data = malloc(8 * size); for (i = 0; i < size; i++) { double_to_bytes(data + i * 8, mat->d[i]); } if (!fs->stream_write_data(w, (const char*)data, 8 * size)) { free(data); return FALSE; } free(data); return TRUE; }
int textio_translit(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); RefTextIO *tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]); *vret = bool_Value(tio != NULL && tio->trans); return TRUE; }
static int mapiter_dispose(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefMap *rm = Value_vp(r->v[INDEX_MAPITER_VAL]); rm->lock_count--; return TRUE; }
static int markdown_dispose(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); Markdown *r = Value_ptr(ref->v[INDEX_MARKDOWN_MD]); fs->Mem_close(&r->mem); free(r); ref->v[INDEX_MARKDOWN_MD] = VALUE_NULL; return TRUE; }
static int textio_gets(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); int trim = FUNC_INT(node); if (!textio_gets_sub(vret, ref, trim)) { return FALSE; } return TRUE; }
int textio_charset(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); RefTextIO *tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]); RefCharset *cs = (tio != NULL ? tio->cs : NULL); if (cs != NULL) { *vret = vp_Value(cs); } return TRUE; }
static int conn_close(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); sqlite3 *conn = Value_ptr(r->v[INDEX_SQLITE_CONN]); if (conn != NULL) { sqlite3_close(conn); r->v[INDEX_SQLITE_CONN] = VALUE_NULL; } return TRUE; }
static int socket_empty(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefFileHandle *fh = Value_vp(r->v[INDEX_FILEIO_HANDLE]); if (fh->fd_read != -1 || fh->fd_write != -1) { *vret = VALUE_FALSE; } else { *vret = VALUE_TRUE; } return TRUE; }
static int textio_next(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); if (!textio_gets_sub(vret, ref, TRUE)) { return FALSE; } if (!Value_bool(*vret)) { throw_stopiter(); return FALSE; } return TRUE; }
static int matrix_marshal_read(Value *vret, Value *v, RefNode *node) { uint8_t *data; uint32_t rows, cols; int size; int rd_size; int i; RefMatrix *mat; Value r = Value_ref(v[1])->v[INDEX_MARSHALDUMPER_SRC]; if (!fs->stream_read_uint32(r, &cols)) { return FALSE; } if (!fs->stream_read_uint32(r, &rows)) { return FALSE; } if (cols > MATRIX_MAX_SIZE || rows > MATRIX_MAX_SIZE) { fs->throw_errorf(fs->mod_lang, "ValueError", "Illigal Matrix size (0 - %d)", MATRIX_MAX_SIZE); return FALSE; } size = cols * rows; if (size > fs->max_alloc || size * sizeof(double) > fs->max_alloc) { fs->throw_error_select(THROW_MAX_ALLOC_OVER__INT, fs->max_alloc); return FALSE; } rd_size = size * sizeof(double); mat = fs->buf_new(cls_matrix, sizeof(RefMatrix) + rd_size); *vret = vp_Value(mat); mat->cols = cols; mat->rows = rows; data = malloc(rd_size); if (!fs->stream_read_data(r, NULL, (char*)data, &rd_size, FALSE, TRUE)) { free(data); return FALSE; } for (i = 0; i < size; i++) { double val = bytes_to_double(data + i * 8); if (isnan(val)) { fs->throw_error_select(THROW_FLOAT_DOMAIN_ERROR); return FALSE; } mat->d[i] = val; } free(data); return TRUE; }
static int socket_close(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefFileHandle *fh = Value_vp(r->v[INDEX_FILEIO_HANDLE]); int ret = fs->stream_flush_sub(*v); if (fh != NULL && fh->fd_read != -1) { closesocket_fox(fh->fd_read); fh->fd_read = -1; fh->fd_write = -1; } return ret; }
int textio_flush(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); Value stream = ref->v[INDEX_TEXTIO_STREAM]; RefNode *s_type = Value_type(stream); if (s_type != fs->cls_bytesio) { Value_push("v", stream); if (!call_member_func(intern("flush", -1), 0, TRUE)) { return FALSE; } } return TRUE; }
/* * 基本的にエラーが発生しても例外をださない */ static int socket_write(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefBytesIO *mb = Value_vp(v[1]); RefFileHandle *fh = Value_vp(r->v[INDEX_FILEIO_HANDLE]); int wrote_size = 0; if (fh->fd_write != -1) { wrote_size = send_fox(fh->fd_write, mb->buf.p, mb->buf.size); } *vret = int32_Value(wrote_size); return TRUE; }
/** * printf("format", ...) * printf(locale, "format", ...) */ static int textio_printf(Value *vret, Value *v, RefNode *node) { int str = FUNC_INT(node); RefNode *v1_type = Value_type(v[1]); RefStr *s_fmt; Ref *r_loc = NULL; int start_arg; if (v1_type == fs->cls_str) { s_fmt = Value_vp(v[1]); start_arg = 2; } else if (v1_type == fs->cls_locale) { if (fg->stk_top > v + 2) { RefNode *v2_type = Value_type(v[2]); if (v2_type != fs->cls_str) { throw_error_select(THROW_ARGMENT_TYPE__NODE_NODE_INT, fs->cls_str, v2_type, 2); return FALSE; } } else { throw_errorf(fs->mod_lang, "ArgumentError", "2 or more arguments excepted (1 given)"); return FALSE; } r_loc = Value_ref(v[1]); s_fmt = Value_vp(v[2]); start_arg = 3; } else { throw_error_select(THROW_ARGMENT_TYPE2__NODE_NODE_NODE_INT, fs->cls_str, fs->cls_locale, v1_type, 1); return FALSE; } if (str) { // sprintf StrBuf buf; StrBuf_init(&buf, 0); if (!textio_printf_sub(VALUE_NULL, &buf, s_fmt, start_arg, r_loc)) { return FALSE; } *vret = cstr_Value(fs->cls_str, buf.p, buf.size); StrBuf_close(&buf); } else { if (!textio_printf_sub(*v, NULL, s_fmt, start_arg, r_loc)) { return FALSE; } } return TRUE; }
static int socket_read(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefBytesIO *mb = Value_vp(v[1]); int size = fs->Value_int64(v[2], NULL); RefFileHandle *fh = Value_vp(r->v[INDEX_FILEIO_HANDLE]); int rd; if (fh->fd_read == -1) { fs->throw_error_select(THROW_NOT_OPENED_FOR_READ); return FALSE; } rd = recv_fox(fh->fd_read, mb->buf.p + mb->buf.size, size); mb->buf.size += rd; return TRUE; }
static int mapentry_tostr(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); StrBuf buf; StrBuf_init(&buf, 0); if (!StrBuf_printf(&buf, "Entry(%v, %v)", r->v[INDEX_ENTRY_KEY], r->v[INDEX_ENTRY_VAL])) { goto ERROR_END; } *vret = cstr_Value(fs->cls_str, buf.p, buf.size); StrBuf_close(&buf); return TRUE; ERROR_END: StrBuf_close(&buf); return FALSE; }
static int map_add_entry(Value *vret, Value *v, RefNode *node) { RefMap *rm = Value_vp(*v); Ref *r = Value_ref(v[1]); HashValueEntry *ve; if (rm->lock_count > 0) { throw_error_select(THROW_CANNOT_MODIFY_ON_ITERATION); return FALSE; } ve = refmap_add(rm, r->v[0], TRUE, FALSE); if (ve == NULL) { return FALSE; } ve->val = Value_cp(r->v[1]); return TRUE; }
static int textio_close(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefTextIO *tio = Value_vp(r->v[INDEX_TEXTIO_TEXTIO]); if (tio != NULL) { if (tio != (RefTextIO*)fv->ref_textio_utf8) { IconvIO_close(&tio->in); IconvIO_close(&tio->out); free(tio); } r->v[INDEX_TEXTIO_TEXTIO] = VALUE_NULL; } Value_dec(r->v[INDEX_TEXTIO_STREAM]); r->v[INDEX_TEXTIO_STREAM] = VALUE_NULL; return TRUE; }
static int conn_query(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); sqlite3 *conn = Value_ptr(r->v[INDEX_SQLITE_CONN]); sqlite3_stmt *stmt = NULL; if (!conn_prepare_sub(&stmt, conn, v)) { return FALSE; } { RefCursor *rc = fs->buf_new(cls_cursor, sizeof(RefCursor)); *vret = vp_Value(rc); rc->connect = fs->Value_cp(*v); rc->stmt = stmt; rc->is_map = FUNC_INT(node); } return TRUE; }
static void CALLBACK timeout_callback(HWND hwnd, UINT msg, UINT_PTR id, DWORD time) { Value *sender_v = GuiHash_get_p(&timer_entry, (const void*)id); if (sender_v != NULL) { Ref *sender_r = Value_ref(*sender_v); Value fn = sender_r->v[INDEX_TIMER_FN]; Value *stk_top = fg->stk_top; int ret_code; int result = TRUE; fs->Value_push("v", fn); *fg->stk_top++ = event_object_new(sender_r); ret_code = fs->call_function_obj(1); if (fg->error != VALUE_NULL) { PostQuitMessage(0); } if (ret_code) { Value vr = fg->stk_top[-1]; if (vr == VALUE_FALSE) { result = FALSE; } } else { result = FALSE; } // エラーの場合、stk_topが不定 while (fg->stk_top > stk_top) { fs->Value_pop(); } if (!result) { sender_r->v[INDEX_TIMER_ID] = VALUE_NULL; // カウンタを1減らす fs->unref(vp_Value(sender_r)); KillTimer(NULL, id); } } else { KillTimer(NULL, id); } }
/** * Function f : スカラ関数 * Class c : 集約関数 * c.new(), c#step(..), c#result() を実装する */ static int conn_create_function(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); sqlite3 *conn = Value_ptr(r->v[INDEX_SQLITE_CONN]); RefStr *name = Value_vp(v[1]); Value v2 = v[2]; const RefNode *v2_type = fs->Value_type(v2); if (v2_type == fs->cls_fn) { Value *vf = conn_create_function_reg(r, v2); sqlite3_create_function_v2(conn, name->c, -1, SQLITE_UTF8, vf, sqlite_callback_func, NULL, NULL, NULL); } else if (v2_type == fs->cls_class) { RefNode *klass = Value_vp(v2); sqlite3_create_function_v2(conn, name->c, -1, SQLITE_UTF8, klass, NULL, sqlite_callback_step, sqlite_callback_final, NULL); } else { fs->throw_error_select(THROW_ARGMENT_TYPE2__NODE_NODE_NODE_INT, fs->cls_fn, fs->cls_class, v2_type, 2); return FALSE; } return TRUE; }
static int vector_marshal_read(Value *vret, Value *v, RefNode *node) { uint8_t *data; uint32_t size; int rd_size; int i; RefVector *vec; Value r = Value_ref(v[1])->v[INDEX_MARSHALDUMPER_SRC]; if (!fs->stream_read_uint32(r, &size)) { return FALSE; } if (size > fs->max_alloc || size * sizeof(double) > fs->max_alloc) { fs->throw_error_select(THROW_MAX_ALLOC_OVER__INT, fs->max_alloc); return FALSE; } rd_size = size * sizeof(double); vec = fs->buf_new(cls_vector, sizeof(RefVector) + rd_size); *vret = vp_Value(vec); vec->size = size; data = malloc(rd_size); if (!fs->stream_read_data(r, NULL, (char*)data, &rd_size, FALSE, TRUE)) { free(data); return FALSE; } for (i = 0; i < vec->size; i++) { double val = bytes_to_double(data + i * 8); if (isnan(val)) { fs->throw_error_select(THROW_FLOAT_DOMAIN_ERROR); return FALSE; } vec->d[i] = val; } free(data); return TRUE; }
static int mapiter_next(Value *vret, Value *v, RefNode *node) { Ref *r = Value_ref(*v); RefMap *map = Value_vp(r->v[INDEX_MAPITER_VAL]); int idx = Value_integral(r->v[INDEX_MAPITER_IDX]); HashValueEntry *ep = Value_ptr(r->v[INDEX_MAPITER_PTR]); if (ep != NULL) { ep = ep->next; } while (ep == NULL && idx < map->entry_num) { ep = map->entry[idx]; idx++; } r->v[INDEX_MAPITER_IDX] = int32_Value(idx); r->v[INDEX_MAPITER_PTR] = ptr_Value(ep); if (ep != NULL) { switch (Value_integral(r->v[INDEX_MAPITER_TYPE])) { case ITERATOR_KEY: *vret = Value_cp(ep->key); break; case ITERATOR_VAL: *vret = Value_cp(ep->val); break; default: { Ref *r2 = ref_new(fv->cls_entry); *vret = vp_Value(r2); r2->v[INDEX_ENTRY_KEY] = Value_cp(ep->key); r2->v[INDEX_ENTRY_VAL] = Value_cp(ep->val); break; } } } else { throw_stopiter(); return FALSE; } return TRUE; }
static int vector_marshal_write(Value *vret, Value *v, RefNode *node) { const RefVector *vec = Value_vp(*v); Value w = Value_ref(v[1])->v[INDEX_MARSHALDUMPER_SRC]; uint8_t *data; int i; if (!fs->stream_write_uint32(w, vec->size)) { return FALSE; } data = malloc(8 * vec->size); for (i = 0; i < vec->size; i++) { double_to_bytes(data + i * 8, vec->d[i]); } if (!fs->stream_write_data(w, (const char*)data, 8 * vec->size)) { free(data); return FALSE; } free(data); return TRUE; }
/** * 0 : 要素数 * 4 : 要素(key, value, key, value, ...) */ static int map_marshal_write(Value *vret, Value *v, RefNode *node) { Value dumper = v[1]; Value w = Value_ref(dumper)->v[INDEX_MARSHALDUMPER_SRC]; RefMap *rm = Value_vp(*v); int is_map = FUNC_INT(node); int i; rm->lock_count++; if (!stream_write_uint32(w, rm->count)) { goto ERROR_END; } for (i = 0; i < rm->entry_num; i++) { HashValueEntry *ep = rm->entry[i]; for (; ep != NULL; ep = ep->next) { Value_push("vv", dumper, ep->key); if (!call_member_func(fs->str_write, 1, TRUE)) { goto ERROR_END; } Value_pop(); if (is_map) { Value_push("vv", dumper, ep->val); if (!call_member_func(fs->str_write, 1, TRUE)) { goto ERROR_END; } Value_pop(); } } } rm->lock_count--; return TRUE; ERROR_END: rm->lock_count--; return FALSE; }
static int textio_print(Value *vret, Value *v, RefNode *node) { Ref *ref = Value_ref(*v); Value *varg = v + 1; int new_line = FUNC_INT(node); Value stream = ref->v[INDEX_TEXTIO_STREAM]; RefNode *s_type = Value_type(stream); StrBuf *sb = NULL; if (s_type == fs->cls_bytesio) { sb = bytesio_get_strbuf(stream); } while (varg < fg->stk_top) { if (!textio_print_sub(*v, sb, *varg, NULL)) { return FALSE; } varg++; } if (new_line) { RefTextIO *tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]); if (tio == NULL || tio->cs->ascii) { if (sb != NULL) { if (!StrBuf_add_c(sb, '\n')) { return FALSE; } } else if (!stream_write_data(stream, "\n", 1)) { return FALSE; } } else { if (!stream_write_sub_s(stream, sb, "\n", 1, tio)) { return FALSE; } } } return TRUE; }
static int map_marshal_read(Value *vret, Value *v, RefNode *node) { Value dumper = v[1]; Value r = Value_ref(dumper)->v[INDEX_MARSHALDUMPER_SRC]; int is_map = FUNC_INT(node); RefMap *rm; uint32_t size; int i; if (!stream_read_uint32(r, &size)) { return FALSE; } if (size > 0xffffff) { throw_errorf(fs->mod_lang, "ValueError", "Invalid size number"); return FALSE; } if (size * sizeof(HashValueEntry) > fs->max_alloc) { throw_error_select(THROW_MAX_ALLOC_OVER__INT, fs->max_alloc); return FALSE; } rm = refmap_new(size); if (!is_map) { rm->rh.type = fs->cls_set; } *vret = vp_Value(rm); for (i = 0; i < size; i++) { Value key; Value_push("v", dumper); if (!call_member_func(fs->str_read, 0, TRUE)) { return FALSE; } fg->stk_top--; key = *fg->stk_top; if (is_map) { Value val; HashValueEntry *ve; Value_push("v", dumper); if (!call_member_func(fs->str_read, 0, TRUE)) { return FALSE; } fg->stk_top--; val = *fg->stk_top; ve = refmap_add(rm, key, TRUE, FALSE); if (ve == NULL) { unref(key); unref(val); return FALSE; } ve->val = val; } else { // Set if (refmap_add(rm, key, TRUE, FALSE) == NULL) { unref(key); return FALSE; } } unref(key); } return TRUE; }