Ejemplo 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;
}
Ejemplo n.º 2
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;
}
Ejemplo 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;
}
Ejemplo n.º 4
0
static int textio_print_sub(Value v_textio, StrBuf *sb, Value v, Ref *r_loc)
{
    RefNode *v_type = Value_type(v);
    int result = TRUE;
    Value vb;
    RefTextIO *tio;

    if (v_textio != VALUE_NULL) {
        Ref *ref = Value_ref(v_textio);
        vb = ref->v[INDEX_TEXTIO_STREAM];
        tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]);
    } else {
        vb = VALUE_NULL;
        tio = NULL;
    }

    // よく使う型
    if (Value_isint(v)) {
        char c_buf[32];
        sprintf(c_buf, "%d", Value_integral(v));
        if (!stream_write_sub_s(vb, sb, c_buf, -1, tio)) {
            result = FALSE;
        }
    } else if (v_type == fs->cls_int) {
        RefInt *mp = Value_vp(v);
        char *c_buf = malloc(BigInt_str_bufsize(&mp->bi, 10));
        BigInt_str(&mp->bi, 10, c_buf, FALSE);
        if (!stream_write_sub_s(vb, sb, c_buf, -1, tio)) {
            result = FALSE;
        }
        free(c_buf);
    } else if (v_type == fs->cls_str) {
        RefStr *rs = Value_vp(v);
        if (!stream_write_sub_s(vb, sb, rs->c, rs->size, tio)) {
            result = FALSE;
        }
    } else if (v_type == fv->cls_strio) {
        RefBytesIO *mb = Value_bytesio(v);
        if (!stream_write_sub_s(vb, sb, mb->buf.p, mb->buf.size, tio)) {
            result = FALSE;
        }
    } else if (v_type == fs->cls_module) {
        RefNode *nd = Value_vp(v);
        RefStr *rs = nd->name;
        if (!stream_write_sub_s(vb, sb, "Module(", 7, tio)) {
            return FALSE;
        }
        if (!stream_write_sub_s(vb, sb, rs->c, rs->size, tio)) {
            return FALSE;
        }
        if (!stream_write_sub_s(vb, sb, ")", 1, tio)) {
            return FALSE;
        }
    } else if (v_type != fs->cls_null) {
        Value vret;
        fs->Value_push("v", v);
        if (!call_member_func(fs->str_tostr, 0, TRUE)) {
            return FALSE;
        }
        vret = fg->stk_top[-1];
        if (Value_type(vret) == fs->cls_str) {
            RefStr *rs = Value_vp(vret);
            if (!stream_write_sub_s(vb, sb, rs->c, rs->size, tio)) {
                return FALSE;
            }
        } else {
        }
        Value_pop();
    }
    return result;
}