static void unpack_test(void) { /*************** Test of unpack *****************/ cw_pack_context pc; cw_unpack_context uc; mpack_reader_t mr; cmp_ctx_t cc; cmp_object_t cobj; BEFORE_UTEST(cw_pack_nil(&pc)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_read_tag(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; BEFORE_UTEST(cw_pack_signed(&pc, -1)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_read_tag(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; BEFORE_UTEST(cw_pack_signed(&pc, 100000)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_read_tag(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; BEFORE_UTEST(cw_pack_float(&pc, (float)3.14)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_read_tag(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; BEFORE_UTEST(cw_pack_double(&pc, 3.14)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_read_tag(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; BEFORE_UTEST(cw_pack_str(&pc, "Claes",5)); UTEST("CMP", cmp_read_object(&cc, &cobj)); UTEST("MPack", mpack_skip_bytes(&mr,mpack_expect_str(&mr));mpack_done_str(&mr)); UTEST("CWPack", cw_unpack_next(&uc)); AFTER_UTEST; }
float mpack_expect_float_strict(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_float) return var.v.f; mpack_reader_flag_error(reader, mpack_error_type); return 0.0f; }
uint32_t mpack_expect_bin(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_bin) return var.v.l; mpack_reader_flag_error(reader, mpack_error_type); return 0; }
double mpack_expect_double_strict(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_float) return (double)var.v.f; else if (var.type == mpack_type_double) return var.v.d; mpack_reader_flag_error(reader, mpack_error_type); return 0.0; }
uint64_t mpack_expect_u64(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_uint) { return var.v.u; } else if (var.type == mpack_type_int) { if (var.v.i >= 0) return (uint64_t)var.v.i; } mpack_reader_flag_error(reader, mpack_error_type); return 0; }
int16_t mpack_expect_i16(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_uint) { if (var.v.u <= INT16_MAX) return (int16_t)var.v.u; } else if (var.type == mpack_type_int) { if (var.v.i >= INT16_MIN && var.v.i <= INT16_MAX) return (int16_t)var.v.i; } mpack_reader_flag_error(reader, mpack_error_type); return 0; }
uint32_t mpack_expect_u32(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_uint) { if (var.v.u <= UINT32_MAX) return (uint32_t)var.v.u; } else if (var.type == mpack_type_int) { if (var.v.i >= 0 && var.v.i <= UINT32_MAX) return (uint32_t)var.v.i; } mpack_reader_flag_error(reader, mpack_error_type); return 0; }
float mpack_expect_float(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_uint) return (float)var.v.u; else if (var.type == mpack_type_int) return (float)var.v.i; else if (var.type == mpack_type_float) return var.v.f; else if (var.type == mpack_type_double) return (float)var.v.d; mpack_reader_flag_error(reader, mpack_error_type); return 0.0f; }
bool mpack_expect_array_or_nil(mpack_reader_t* reader, uint32_t* count) { mpack_tag_t var = mpack_read_tag(reader); if (var.type == mpack_type_nil) { *count = 0; return false; } if (var.type == mpack_type_array) { *count = var.v.n; return true; } mpack_reader_flag_error(reader, mpack_error_type); *count = 0; return false; }
static void test_reader_miscellaneous() { // 0xc1 is reserved; it should always raise mpack_error_invalid TEST_SIMPLE_READ_ERROR("\xc1", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); // simple truncated tags (testing discard of additional // temporary data in mpack_parse_tag()) TEST_SIMPLE_READ_ERROR("\xcc", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xcd", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xce", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xcf", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xd0", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xd1", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xd2", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); TEST_SIMPLE_READ_ERROR("\xd3", mpack_tag_equal(mpack_read_tag(&reader), mpack_tag_nil()), mpack_error_invalid); // truncated discard errors TEST_SIMPLE_READ_ERROR("\x91", (mpack_discard(&reader), true), mpack_error_invalid); // array TEST_SIMPLE_READ_ERROR("\x81", (mpack_discard(&reader), true), mpack_error_invalid); // map }
void mpack_discard(mpack_reader_t* reader) { mpack_tag_t var = mpack_read_tag(reader); if (mpack_reader_error(reader)) return; switch (var.type) { case mpack_type_str: mpack_skip_bytes(reader, var.v.l); mpack_done_str(reader); break; case mpack_type_bin: mpack_skip_bytes(reader, var.v.l); mpack_done_bin(reader); break; case mpack_type_ext: mpack_skip_bytes(reader, var.v.l); mpack_done_ext(reader); break; case mpack_type_array: { for (; var.v.n > 0; --var.v.n) { mpack_discard(reader); if (mpack_reader_error(reader)) break; } mpack_done_array(reader); break; } case mpack_type_map: { for (; var.v.n > 0; --var.v.n) { mpack_discard(reader); mpack_discard(reader); if (mpack_reader_error(reader)) break; } mpack_done_map(reader); break; } default: break; } }
static bool element(mpack_reader_t* reader, yajl_gen gen, options_t* options, int depth) { const mpack_tag_t tag = mpack_read_tag(reader); if (mpack_reader_error(reader) != mpack_ok) return false; if (!options->debug && depth == 0 && (tag.type != mpack_type_map && tag.type != mpack_type_array)) { fprintf(stderr, "%s: Top-level object must be a map or array. Try debug viewing mode (-d)\n", options->command); return false; } // TODO check not depth zero switch (tag.type) { case mpack_type_bool: return yajl_gen_bool(gen, tag.v.b) == yajl_gen_status_ok; case mpack_type_nil: return yajl_gen_null(gen) == yajl_gen_status_ok; case mpack_type_int: return yajl_gen_integer(gen, tag.v.i) == yajl_gen_status_ok; case mpack_type_float: return yajl_gen_double(gen, tag.v.f) == yajl_gen_status_ok; case mpack_type_double: return yajl_gen_double(gen, tag.v.d) == yajl_gen_status_ok; case mpack_type_uint: if (tag.v.u > (uint64_t)INT64_MAX) { char buf[32]; snprintf(buf, sizeof(buf), "%" PRIu64, tag.v.u); return yajl_gen_string(gen, (const unsigned char*)buf, strlen(buf)) == yajl_gen_status_ok; } return yajl_gen_integer(gen, (int64_t)tag.v.u) == yajl_gen_status_ok; case mpack_type_str: return string(reader, gen, options, tag.v.l); case mpack_type_bin: if (options->base64) { return base64_bin(reader, gen, options, tag.v.l, options->base64_prefix); } else if (options->debug) { mpack_skip_bytes(reader, tag.v.l); mpack_done_bin(reader); // output nothing to allow us to print our debug string skip_quotes = true; if (yajl_gen_string(gen, (const unsigned char*)"", 0) != yajl_gen_status_ok) return false; skip_quotes = false; char buf[64]; snprintf(buf, sizeof(buf), "<bin of size %u>", tag.v.l); print(out_file, buf, strlen(buf)); return true; } else { fprintf(stderr, "%s: bin unencodable in JSON. Try debug viewing mode (-d)\n", options->command); return false; } case mpack_type_ext: if (options->base64) { return base64_ext(reader, gen, options, tag.exttype, tag.v.l); } else if (options->debug) { mpack_skip_bytes(reader, tag.v.l); mpack_done_ext(reader); // output nothing to allow us to print our debug string skip_quotes = true; if (yajl_gen_string(gen, (const unsigned char*)"", 0) != yajl_gen_status_ok) return false; skip_quotes = false; char buf[64]; snprintf(buf, sizeof(buf), "<ext of type %i size %u>", tag.exttype, tag.v.l); print(out_file, buf, strlen(buf)); return true; } else { fprintf(stderr, "%s: ext type %i unencodable in JSON. Try debug viewing mode (-d)\n", options->command, tag.exttype); return false; } case mpack_type_array: if (yajl_gen_array_open(gen) != yajl_gen_status_ok) return false; for (size_t i = 0; i < tag.v.l; ++i) if (!element(reader, gen, options, depth + 1)) return false; mpack_done_array(reader); return yajl_gen_array_close(gen) == yajl_gen_status_ok; case mpack_type_map: if (yajl_gen_map_open(gen) != yajl_gen_status_ok) return false; for (size_t i = 0; i < tag.v.l; ++i) { if (options->debug) { element(reader, gen, options, depth + 1); } else { uint32_t len = mpack_expect_str(reader); if (mpack_reader_error(reader) != mpack_ok) { fprintf(stderr, "%s: map key is not a string. Try debug viewing mode (-d)\n", options->command); return false; } if (!string(reader, gen, options, len)) return false; } if (!element(reader, gen, options, depth + 1)) return false; } mpack_done_map(reader); return yajl_gen_map_close(gen) == yajl_gen_status_ok; } return true; }
void mpack_expect_tag(mpack_reader_t* reader, mpack_tag_t expected) { mpack_tag_t actual = mpack_read_tag(reader); if (!mpack_tag_equal(actual, expected)) mpack_reader_flag_error(reader, mpack_error_type); }
static void mpack_print_element(mpack_reader_t* reader, size_t depth, FILE* file) { mpack_tag_t val = mpack_read_tag(reader); if (mpack_reader_error(reader) != mpack_ok) return; switch (val.type) { case mpack_type_nil: fprintf(file, "null"); break; case mpack_type_bool: fprintf(file, val.v.b ? "true" : "false"); break; case mpack_type_float: fprintf(file, "%f", val.v.f); break; case mpack_type_double: fprintf(file, "%f", val.v.d); break; case mpack_type_int: fprintf(file, "%" PRIi64, val.v.i); break; case mpack_type_uint: fprintf(file, "%" PRIu64, val.v.u); break; case mpack_type_bin: fprintf(file, "<binary data of length %u>", val.v.l); mpack_skip_bytes(reader, val.v.l); mpack_done_bin(reader); break; case mpack_type_ext: fprintf(file, "<ext data of type %i and length %u>", val.exttype, val.v.l); mpack_skip_bytes(reader, val.v.l); mpack_done_ext(reader); break; case mpack_type_str: putc('"', file); for (size_t i = 0; i < val.v.l; ++i) { char c; mpack_read_bytes(reader, &c, 1); if (mpack_reader_error(reader) != mpack_ok) return; switch (c) { case '\n': fprintf(file, "\\n"); break; case '\\': fprintf(file, "\\\\"); break; case '"': fprintf(file, "\\\""); break; default: putc(c, file); break; } } putc('"', file); mpack_done_str(reader); break; case mpack_type_array: fprintf(file, "[\n"); for (size_t i = 0; i < val.v.n; ++i) { for (size_t j = 0; j < depth + 1; ++j) fprintf(file, " "); mpack_print_element(reader, depth + 1, file); if (mpack_reader_error(reader) != mpack_ok) return; if (i != val.v.n - 1) putc(',', file); putc('\n', file); } for (size_t i = 0; i < depth; ++i) fprintf(file, " "); putc(']', file); mpack_done_array(reader); break; case mpack_type_map: fprintf(file, "{\n"); for (size_t i = 0; i < val.v.n; ++i) { for (size_t j = 0; j < depth + 1; ++j) fprintf(file, " "); mpack_print_element(reader, depth + 1, file); if (mpack_reader_error(reader) != mpack_ok) return; fprintf(file, ": "); mpack_print_element(reader, depth + 1, file); if (mpack_reader_error(reader) != mpack_ok) return; if (i != val.v.n - 1) putc(',', file); putc('\n', file); } for (size_t i = 0; i < depth; ++i) fprintf(file, " "); putc('}', file); mpack_done_map(reader); break; } }