/** * 検索して見つかった場合/見つからなかった場合は * 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; }
void throw_error_vprintf(RefNode *err_m, const char *err_name, const char *fmt, va_list va) { RefNode *err = Hash_get_p(&err_m->u.m.h, intern(err_name, -1)); Ref *r; if (err == NULL) { const RefStr *m = err_m->name; fatal_errorf("ClassNotFound:%r.%s", m, err_name); } if (fg->error != VALUE_NULL) { unref(fg->error); } r = ref_new(err); fg->error = vp_Value(r); if (fmt != NULL) { StrBuf msg; StrBuf_init_refstr(&msg, 0); StrBuf_vprintf(&msg, fmt, va); r->v[1] = StrBuf_str_Value(&msg, fs->cls_str); } }
/** * printf(format, v1, v2, ...) * printf(format, [v1, v2, ...]) * printf(format, {k1:v1, k2:v2, ...}) * * start_argは1から始まる * * v, sbどちらかが必要 */ static int textio_printf_sub(Value v, StrBuf *sb, RefStr *fmt_src, int start_arg, Ref *r_loc) { const char *p = fmt_src->c; const char *end = p + fmt_src->size; Value *varg = fg->stk_base + start_arg; int vargc = (fg->stk_top - fg->stk_base) - start_arg; HashValueEntry **vhash = NULL; Value stream; RefTextIO *tio; if (v != VALUE_NULL) { Ref *ref = Value_ref(v); stream = ref->v[INDEX_TEXTIO_STREAM]; tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]); } else { stream = VALUE_NULL; tio = NULL; } if (sb == NULL) { RefNode *s_type = Value_type(stream); if (s_type == fs->cls_bytesio) { sb = bytesio_get_strbuf(stream); } } // フォーマットの後の引数が1個の場合はArray,Mapを解析する if (vargc == 1) { RefNode *va_type = Value_type(*varg); if (va_type == fs->cls_map) { RefMap *r2 = Value_vp(*varg); vhash = r2->entry; vargc = r2->entry_num; // hashの場合はhash_entryサイズとして使う } else if (va_type == fs->cls_list) { RefArray *r2 = Value_vp(*varg); varg = r2->p; vargc = r2->size; } } while (p < end) { if (*p == '%') { p++; if (p >= end) { break; } if (*p == '{' || isalnum(*p) || *p == '_') { Str key; Str fmt; Value *val = NULL; if (*p == '{') { // %{key:format} p++; key.p = p; while (p < end && *p != '}' && *p != ':') { p++; } key.size = p - key.p; if (p < end && *p == ':') { p++; fmt.p = p; while (p < end && *p != '}') { p++; } fmt.size = p - fmt.p; } else { fmt.p = NULL; fmt.size = 0; } if (p < end) { p++; } } else { // $key key.p = p; while (p < end && (isalnum(*p) || *p == '_')) { p++; } key.size = p - key.p; fmt.p = NULL; fmt.size = 0; } if (vhash != NULL) { // keyに対応する値をhashから取り出す uint32_t hash = str_hash(key.p, key.size); HashValueEntry *ep = vhash[hash & (vargc - 1)]; for (; ep != NULL; ep = ep->next) { if (hash == ep->hash) { RefNode *key_type = Value_type(ep->key); if (key_type == fs->cls_str) { RefStr *rkey = Value_vp(ep->key); if (key.size == rkey->size && memcmp(key.p, rkey->c, key.size) == 0) { val = &ep->val; break; } } } } } else { // keyを整数に変換して引数のn番目から取り出す int n = parse_int(key.p, key.size, 65536); if (n >= 0 && n < vargc) { val = &varg[n]; } } if (val != NULL) { if (fmt.size > 0) { // to_strを取り出す RefNode *type = Value_type(*val); RefNode *fn = Hash_get_p(&type->u.c.h, fs->str_tostr); RefStr *vs; Value_push("vS", *val, fmt); if (r_loc != NULL) { Value_push("r", r_loc); } if (!call_function(fn, (r_loc != NULL ? 2 : 1))) { return FALSE; } vs = Value_vp(fg->stk_top[-1]); if (!stream_write_sub_s(stream, sb, vs->c, vs->size, tio)) { return FALSE; } Value_pop(); } else { if (!textio_print_sub(v, sb, *val, r_loc)) { return FALSE; } } } else { throw_errorf(fs->mod_lang, "IndexError", "Index %Q not found", key); return FALSE; } } else if (*p == '%') { // %%は%にして出力 if (!stream_write_sub_s(stream, sb, "%", 1, tio)) { return FALSE; } p++; } else { throw_errorf(fs->mod_lang, "FormatError", "Invalid character after '%%'"); return FALSE; } } else { // %が出るまでそのまま出力 const char *top = p; while (p < end && *p != '%') { p++; } if (p > top) { if (!stream_write_sub_s(stream, sb, top, p - top, tio)) { return FALSE; } } } } return TRUE; }