static int test_nils(void) { plan(6); header(); const char *d1 = mp_encode_nil(data); const char *d2 = data; const char *d3 = data; const char *d4 = data; note("nil"); mp_decode_nil(&d2); mp_next(&d3); ok(!mp_check(&d4, d3 + 1), "mp_check_nil()"); is((d1 - data), 1, "len(mp_encode_nil() == 1"); is(d1, d2, "len(mp_decode_nil()) == 1"); is(d1, d3, "len(mp_next_nil()) == 1"); is(d1, d4, "len(mp_check_nil()) == 1"); is(mp_sizeof_nil(), 1, "mp_sizeof_nil() == 1"); footer(); return check_plan(); }
int test_mp_print() { plan(10); header(); char msgpack[128]; char *d = msgpack; d = mp_encode_array(d, 6); d = mp_encode_int(d, -5); d = mp_encode_uint(d, 42); d = mp_encode_str(d, "kill bill", 9); d = mp_encode_map(d, 6); d = mp_encode_str(d, "bool true", 9); d = mp_encode_bool(d, true); d = mp_encode_str(d, "bool false", 10); d = mp_encode_bool(d, false); d = mp_encode_str(d, "null", 4); d = mp_encode_nil(d); d = mp_encode_str(d, "float", 5); d = mp_encode_float(d, 3.14); d = mp_encode_str(d, "double", 6); d = mp_encode_double(d, 3.14); d = mp_encode_uint(d, 100); d = mp_encode_uint(d, 500); *d++ = 0xd4; /* let's pack smallest fixed ext */ *d++ = 0; *d++ = 0; char bin[] = "\x12test\x34\b\t\n\"bla\\-bla\"\f\r"; d = mp_encode_bin(d, bin, sizeof(bin)); assert(d <= msgpack + sizeof(msgpack)); const char *expected = "[-5, 42, \"kill bill\", " "{\"bool true\": true, \"bool false\": false, \"null\": null, " "\"float\": 3.14, \"double\": 3.14, 100: 500}, undefined, " "\"\\u0012test4\\b\\t\\n\\\"bla\\\\-bla\\\"\\f\\r\\u0000\"]"; int esize = strlen(expected); char result[256]; int fsize = mp_snprint(result, sizeof(result), msgpack); ok(fsize == esize, "mp_snprint return value"); ok(strcmp(result, expected) == 0, "mp_snprint result"); fsize = mp_snprint(NULL, 0, msgpack); ok(fsize == esize, "mp_snprint limit = 0"); fsize = mp_snprint(result, 1, msgpack); ok(fsize == esize && result[0] == '\0', "mp_snprint limit = 1"); fsize = mp_snprint(result, 2, msgpack); ok(fsize == esize && result[1] == '\0', "mp_snprint limit = 2"); fsize = mp_snprint(result, esize, msgpack); ok(fsize == esize && result[esize - 1] == '\0', "mp_snprint limit = expected"); fsize = mp_snprint(result, esize + 1, msgpack); ok(fsize == esize && result[esize] == '\0', "mp_snprint limit = expected + 1"); FILE *tmpf = tmpfile(); if (tmpf != NULL) { int fsize = mp_fprint(tmpf, msgpack); ok(fsize == esize, "mp_fprint return value"); (void) rewind(tmpf); int rsize = fread(result, 1, sizeof(result), tmpf); ok(rsize == esize && memcmp(result, expected, esize) == 0, "mp_fprint result"); fclose(tmpf); } /* stdin is read-only */ int rc = mp_fprint(stdin, msgpack); is(rc, -1, "mp_fprint I/O error"); footer(); return check_plan(); }
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)); } }