/** * 複製 */ int map_dup(Value *vret, Value *v, RefNode *node) { RefMap *src = Value_vp(*v); RefNode *type = FUNC_VP(node); int i; int max = src->entry_num; RefMap *dst = buf_new(type, sizeof(RefMap)); *vret = vp_Value(dst); dst->count = src->count; dst->entry_num = max; dst->entry = malloc(sizeof(HashValueEntry*) * max); for (i = 0; i < max; i++) { HashValueEntry *hsrc = src->entry[i]; HashValueEntry **hdst = &dst->entry[i]; for (; hsrc != NULL; hsrc = hsrc->next) { HashValueEntry *he = malloc(sizeof(HashValueEntry)); he->key = Value_cp(hsrc->key); he->val = Value_cp(hsrc->val); he->hash = hsrc->hash; *hdst = he; hdst = &he->next; } *hdst = NULL; } return TRUE; }
static int textio_new(Value *vret, Value *v, RefNode *node) { RefTextIO *tio; RefCharset *cs = Value_vp(v[2]); Ref *r = ref_new(fs->cls_textio); *vret = vp_Value(r); tio = buf_new(NULL, sizeof(RefTextIO)); r->v[INDEX_TEXTIO_TEXTIO] = vp_Value(tio); r->v[INDEX_TEXTIO_STREAM] = Value_cp(v[1]); tio->in.ic = (void*)-1; tio->out.ic = (void*)-1; tio->cs = cs; tio->trans = FALSE; if (fg->stk_top > v + 3 && Value_bool(v[3])) { tio->trans = TRUE; } if (fg->stk_top > v + 4) { r->v[INDEX_TEXTIO_NEWLINE] = Value_cp(v[4]); } return TRUE; }
static int mapentry_new(Value *vret, Value *v, RefNode *node) { Ref *r = ref_new(fv->cls_entry); *vret = vp_Value(r); r->v[INDEX_ENTRY_KEY] = Value_cp(v[1]); r->v[INDEX_ENTRY_VAL] = Value_cp(v[2]); return TRUE; }
static void v_ctextio_init(void) { Ref *ref = ref_new(fs->cls_textio); fg->v_ctextio = vp_Value(ref); ref->v[INDEX_TEXTIO_STREAM] = Value_cp(fg->v_cio); ref->v[INDEX_TEXTIO_TEXTIO] = vp_Value(fv->ref_textio_utf8); }
static int stdout_printf(Value *vret, Value *v, RefNode *node) { if (fg->v_ctextio == VALUE_NULL) { v_ctextio_init(); } *v = Value_cp(fg->v_ctextio); return textio_printf(vret, v, node); }
// a.get("hoge", "Not Exist") -> "Not Exist" int map_get(Value *vret, Value *v, RefNode *node) { RefMap *rm = Value_vp(*v); HashValueEntry *ep = NULL; Value key = v[1]; if (!refmap_get(&ep, rm, key)) { return FALSE; } if (ep != NULL) { // 一致 *vret = Value_cp(ep->val); } else { if (v + 2 < fg->stk_top) { *vret = Value_cp(v[2]); } } return TRUE; }
/** * 検索して見つかった場合/見つからなかった場合は * 1.true/falseを返す * 2.index/nullを返す */ int map_index_of(Value *vret, Value *v, RefNode *node) { RefMap *rm = Value_vp(*v); int ret_index = FUNC_INT(node); Value v1 = v[1]; RefNode *type = Value_type(v1); int i; RefNode *fn_eq = Hash_get_p(&type->u.c.h, fs->symbol_stock[T_EQ]); if (fn_eq == NULL) { throw_error_select(THROW_NO_MEMBER_EXISTS__NODE_REFSTR, type, fs->symbol_stock[T_EQ]); return FALSE; } rm->lock_count++; for (i = 0; i < rm->entry_num; i++) { HashValueEntry *ep = rm->entry[i]; for (; ep != NULL; ep = ep->next) { Value va = ep->val; if (Value_type(va) == type) { if (type == fs->cls_str) { if (refstr_eq(Value_vp(v1), Value_vp(va))) { break; } } else { Value_push("vv", v1, va); if (!call_function(fn_eq, 1)) { goto ERROR_END; } fg->stk_top--; if (Value_bool(*fg->stk_top)) { unref(*fg->stk_top); if (ret_index) { *vret = Value_cp(ep->key); } else { *vret = VALUE_TRUE; } return TRUE; } } } } } if (!ret_index) { *vret = VALUE_FALSE; } rm->lock_count--; return TRUE; ERROR_END: rm->lock_count--; return FALSE; }
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; }
int map_iterator(Value *vret, Value *v, RefNode *node) { RefMap *rm = Value_vp(*v); int type = FUNC_INT(node); Ref *r = ref_new(cls_mapiter); rm->lock_count++; r->v[INDEX_MAPITER_VAL] = Value_cp(*v); r->v[INDEX_MAPITER_TYPE] = int32_Value(type); r->v[INDEX_MAPITER_PTR] = ptr_Value(NULL); r->v[INDEX_MAPITER_IDX] = int32_Value(0); *vret = vp_Value(r); return TRUE; }
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; }
/** * 同じキーがあれば上書き * なければ追加 * 例外発生時はNULLを返す * keyのカウンタを増やす */ HashValueEntry *refmap_add(RefMap *rm, Value key, int overwrite, int raise_error) { HashValueEntry *ep, **epp; uint32_t hash; if (!map_search_sub(&epp, &hash, rm, key)) { return NULL; } ep = *epp; if (ep != NULL) { if (overwrite) { // 一致(上書き) if (Value_isref(ep->val)) { RefHeader *rh = Value_ref_header(ep->val); if (rh->nref > 0 && --rh->nref == 0) { Value_release_ref(ep->val); } } ep->val = VALUE_NULL; return ep; } else { if (raise_error) { throw_errorf(fs->mod_lang, "IndexError", "Duplicate key detected"); return NULL; } else { return ep; } } } else { // 一致しない(追加) ep = malloc(sizeof(HashValueEntry)); ep->next = NULL; ep->hash = hash; ep->key = Value_cp(key); ep->val = VALUE_NULL; *epp = ep; rm->count++; if (rm->count > rm->entry_num) { map_grow_entry(rm); } return ep; } }
// a["hoge"] int map_index(Value *vret, Value *v, RefNode *node) { RefMap *rm = Value_vp(*v); HashValueEntry *ep = NULL; Value key = v[1]; if (!refmap_get(&ep, rm, key)) { return FALSE; } if (ep != NULL) { // 一致 *vret = Value_cp(ep->val); } else { throw_errorf(fs->mod_lang, "IndexError", "No keys exists %v", key); return FALSE; } return TRUE; }
static int stdout_print(Value *vret, Value *v, RefNode *node) { int new_line = FUNC_INT(node); Value *varg = v + 1; if (fg->v_ctextio == VALUE_NULL) { v_ctextio_init(); } *v = Value_cp(fg->v_ctextio); while (varg < fg->stk_top) { if (!textio_print_sub(*v, NULL, *varg, NULL)) { return FALSE; } varg++; } if (new_line && !stream_write_data(fg->v_cio, "\n", 1)) { return FALSE; } return TRUE; }
static int map_new_elems(Value *vret, Value *v, RefNode *node) { Value *src = v + 1; int argc = fg->stk_top - src; int i; RefMap *rm; if (argc % 2 != 0) { throw_errorf(fs->mod_lang, "ArgumentError", "Argument count must be even"); return FALSE; } rm = refmap_new(argc / 2); *vret = vp_Value(rm); for (i = 0; i < argc; i += 2) { HashValueEntry *ve = refmap_add(rm, src[i], FALSE, TRUE); if (ve == NULL) { return FALSE; } ve->val = Value_cp(src[i + 1]); } return TRUE; }