GV * Perl_gv_fetchmethod(pTHX_ HV *stash, const char *name) { PERL_ARGS_ASSERT_GV_FETCHMETHOD; return gv_fetchmethod_autoload(stash, name, TRUE); }
GV * Perl_gv_fetchmethod(pTHX_ HV *stash, const char *name) { return gv_fetchmethod_autoload(stash, name, TRUE); }
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)); } }
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; }