Esempio n. 1
0
/**
 * 検索して見つかった場合/見つからなかった場合は
 * 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;
}
Esempio n. 2
0
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);
    }
}
Esempio n. 3
0
/**
 * 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;
}