Ejemplo n.º 1
0
GV *
Perl_gv_fetchmethod(pTHX_ HV *stash, const char *name)
{
    PERL_ARGS_ASSERT_GV_FETCHMETHOD;

    return gv_fetchmethod_autoload(stash, name, TRUE);
}
Ejemplo n.º 2
0
GV *
Perl_gv_fetchmethod(pTHX_ HV *stash, const char *name)
{
    return gv_fetchmethod_autoload(stash, name, TRUE);
}
Ejemplo n.º 3
0
void _mpack_item(SV *res, SV *o)
{
	size_t len, res_len, new_len;
	char *s, *res_s;
	res_s = SvPVbyte(res, res_len);
	unsigned i;

	if (!SvOK(o)) {
		new_len = res_len + mp_sizeof_nil();
		res_s = SvGROW(res, new_len);
		SvCUR_set(res, new_len);
		mp_encode_nil(res_s + res_len);
		return;
	}

	if (SvROK(o)) {
		o = SvRV(o);
		if (SvOBJECT(o)) {
			SvGETMAGIC(o);
			HV *stash = SvSTASH(o);
			GV *mtd = gv_fetchmethod_autoload(stash, "msgpack", 0);
			if (!mtd)
				croak("Object has no method 'msgpack'");
			dSP;
			ENTER;
			SAVETMPS;
			PUSHMARK(SP);
			XPUSHs (sv_bless (sv_2mortal (newRV_inc(o)), stash));
			PUTBACK;
			call_sv((SV *)GvCV(mtd), G_SCALAR);
			SPAGAIN;

			SV *pkt = POPs;

			if (!SvOK(pkt))
				croak("O->msgpack returned undef");

			s = SvPV(pkt, len);

			new_len = res_len + len;
			res_s = SvGROW(res, new_len);
			SvCUR_set(res, new_len);
			memcpy(res_s + res_len, s, len);

			PUTBACK;
			FREETMPS;
			LEAVE;

			return;
		}

		switch(SvTYPE(o)) {
			case SVt_PVAV: {
				AV *a = (AV *)o;
				len = av_len(a) + 1;
				new_len = res_len + mp_sizeof_array(len);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_array(res_s + res_len, len);

				for (i = 0; i < len; i++) {
					SV **item = av_fetch(a, i, 0);
					if (!item)
						_mpack_item(res, 0);
					else
						_mpack_item(res, *item);
				}

				break;
			}
			case SVt_PVHV: {
				HV *h = (HV *)o;
				len = hv_iterinit(h);
				new_len = res_len + mp_sizeof_map(len);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_map(res_s + res_len, len);

				for (;;) {
					HE * iter = hv_iternext(h);
					if (!iter)
						break;

					SV *k = hv_iterkeysv(iter);
					SV *v = HeVAL(iter);
					_mpack_item(res, k);
					_mpack_item(res, v);

				}

				break;
			}

			default:
				croak("Can't serialize reference");
		}
		return;
	}

	switch(SvTYPE(o)) {
		case SVt_PV:
		case SVt_PVIV:
		case SVt_PVNV:
		case SVt_PVMG:
		case SVt_REGEXP:
			if (!looks_like_number(o)) {
				s = SvPV(o, len);
				new_len = res_len + mp_sizeof_str(len);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_str(res_s + res_len, s, len);
				break;
			}

		case SVt_NV: {
			NV v = SvNV(o);
			IV iv = (IV)v;

			if (v != iv) {
				new_len = res_len + mp_sizeof_double(v);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_double(res_s + res_len, v);
				break;
			}
		}
		case SVt_IV: {
			IV v = SvIV(o);
			if (v >= 0) {
				new_len = res_len + mp_sizeof_uint(v);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_uint(res_s + res_len, v);
			} else {
				new_len = res_len + mp_sizeof_int(v);
				res_s = SvGROW(res, new_len);
				SvCUR_set(res, new_len);
				mp_encode_int(res_s + res_len, v);
			}
			break;
		}
		default:
			croak("Internal msgpack error %d", SvTYPE(o));
	}
}
Ejemplo n.º 4
0
xh_int_t
xh_h2x_native_attr(xh_h2x_ctx_t *ctx, xh_char_t *key, I32 key_len, SV *value, xh_int_t flag)
{
    xh_uint_t       type;
    size_t          len, i, nattrs, done;
    xh_sort_hash_t *sorted_hash;
    SV             *item_value;
    xh_char_t      *item;
    I32             item_len;
    GV             *method;

    nattrs = 0;

    if (ctx->opts.content[0] != '\0' && xh_strcmp(key, ctx->opts.content) == 0)
        flag = flag | XH_H2X_F_CONTENT;

    value = xh_h2x_resolve_value(ctx, value, &type);

    if (type & XH_H2X_T_BLESSED && (method = gv_fetchmethod_autoload(SvSTASH(value), "iternext", 0)) != NULL) {
        if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;

        while (1) {
            item_value = xh_h2x_call_method(value, method);
            if (!SvOK(item_value)) break;
            (void) xh_h2x_native_attr(ctx, key, key_len, item_value, XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
            SvREFCNT_dec(item_value);
        }
        nattrs++;

        goto FINISH;
    }

    if (type & XH_H2X_T_SCALAR) {
        if (flag & XH_H2X_F_COMPLEX && (flag & XH_H2X_F_SIMPLE || type & XH_H2X_T_RAW)) {
            xh_xml_write_node(&ctx->writer, key, key_len, value, type & XH_H2X_T_RAW);
        }
        else if (flag & XH_H2X_F_COMPLEX && flag & XH_H2X_F_CONTENT) {
            xh_xml_write_content(&ctx->writer, value);
        }
        else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT) && !(type & XH_H2X_T_RAW)) {
            xh_xml_write_attribute(&ctx->writer, key, key_len, value);
            nattrs++;
        }
    }
    else if (type & XH_H2X_T_HASH) {
        if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;

        len = HvUSEDKEYS((SV *) value);
        if (len == 0) {
            xh_xml_write_empty_node(&ctx->writer, key, key_len);
            goto FINISH;
        }

        xh_xml_write_start_tag(&ctx->writer, key, key_len);

        done = 0;

        if (len > 1 && ctx->opts.canonical) {
            sorted_hash = xh_sort_hash((HV *) value, len);

            for (i = 0; i < len; i++) {
                done += xh_h2x_native_attr(ctx, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_SIMPLE);
            }

            if (done == len) {
                xh_xml_write_closed_end_tag(&ctx->writer);
            }
            else {
                xh_xml_write_end_tag(&ctx->writer);

                for (i = 0; i < len; i++) {
                    (void) xh_h2x_native_attr(ctx, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_COMPLEX);
                }

                xh_xml_write_end_node(&ctx->writer, key, key_len);
            }

            free(sorted_hash);
        }
        else {
            hv_iterinit((HV *) value);
            while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
                done += xh_h2x_native_attr(ctx, item, item_len,item_value, XH_H2X_F_SIMPLE);
            }

            if (done == len) {
                xh_xml_write_closed_end_tag(&ctx->writer);
            }
            else {
                xh_xml_write_end_tag(&ctx->writer);

                hv_iterinit((HV *) value);
                while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
                    (void) xh_h2x_native_attr(ctx, item, item_len,item_value, XH_H2X_F_COMPLEX);
                }

                xh_xml_write_end_node(&ctx->writer, key, key_len);
            }
        }

        nattrs++;
    }
    else if (type & XH_H2X_T_ARRAY) {
        if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;

        len = av_len((AV *) value) + 1;
        for (i = 0; i < len; i++) {
            (void) xh_h2x_native_attr(ctx, key, key_len, *av_fetch((AV *) value, i, 0), XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
        }

        nattrs++;
    }
    else {
        if (flag & XH_H2X_F_SIMPLE && flag & XH_H2X_F_COMPLEX) {
            xh_xml_write_empty_node(&ctx->writer, key, key_len);
        }
        else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT)) {
            xh_xml_write_attribute(&ctx->writer, key, key_len, NULL);
            nattrs++;
        }
    }

FINISH:
    ctx->depth--;

    return nattrs;
}