Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
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. 3
0
/**
 * 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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;
}