diff --git a/include/msgpack/object.h b/include/msgpack/object.h index 560008fe..3d0d1225 100644 --- a/include/msgpack/object.h +++ b/include/msgpack/object.h @@ -69,6 +69,12 @@ typedef struct { const char* ptr; } msgpack_object_bin; +typedef struct { + int8_t type; + uint32_t size; + const char* ptr; +} msgpack_object_ext; + typedef union { bool boolean; uint64_t u64; @@ -78,6 +84,7 @@ typedef union { msgpack_object_map map; msgpack_object_str str; msgpack_object_bin bin; + msgpack_object_ext ext; } msgpack_object_union; typedef struct msgpack_object { diff --git a/include/msgpack/pack.h b/include/msgpack/pack.h index d19c3014..ea0fbf70 100644 --- a/include/msgpack/pack.h +++ b/include/msgpack/pack.h @@ -100,6 +100,9 @@ static int msgpack_pack_str_body(msgpack_packer* pk, const void* b, size_t l); static int msgpack_pack_bin(msgpack_packer* pk, size_t l); static int msgpack_pack_bin_body(msgpack_packer* pk, const void* b, size_t l); +static int msgpack_pack_ext(msgpack_packer* pk, size_t l, int8_t type); +static int msgpack_pack_ext_body(msgpack_packer* pk, const void* b, size_t l); + int msgpack_pack_object(msgpack_packer* pk, msgpack_object d); diff --git a/include/msgpack/pack_template.h b/include/msgpack/pack_template.h index f86f6e8d..9426a217 100644 --- a/include/msgpack/pack_template.h +++ b/include/msgpack/pack_template.h @@ -803,6 +803,73 @@ msgpack_pack_inline_func(_bin_body)(msgpack_pack_user x, const void* b, size_t l msgpack_pack_append_buffer(x, (const unsigned char*)b, l); } +/* + * Ext + */ + +msgpack_pack_inline_func(_ext)(msgpack_pack_user x, size_t l, int8_t type) +{ + switch(l) { + case 1: { + char buf[2]; + buf[0] = 0xd4; + buf[1] = type; + msgpack_pack_append_buffer(x, buf, 2); + } break; + case 2: { + char buf[2]; + buf[0] = 0xd5; + buf[1] = type; + msgpack_pack_append_buffer(x, buf, 2); + } break; + case 4: { + char buf[2]; + buf[0] = 0xd6; + buf[1] = type; + msgpack_pack_append_buffer(x, buf, 2); + } break; + case 8: { + char buf[2]; + buf[0] = 0xd7; + buf[1] = type; + msgpack_pack_append_buffer(x, buf, 2); + } break; + case 16: { + char buf[2]; + buf[0] = 0xd8; + buf[1] = type; + msgpack_pack_append_buffer(x, buf, 2); + } break; + default: + l += 1; + if(l < 256) { + char buf[3]; + buf[0] = 0xc7; + buf[1] = l; + buf[2] = type; + msgpack_pack_append_buffer(x, buf, 3); + } else if(l < 65536) { + char buf[4]; + buf[0] = 0xc8; + _msgpack_store16(&buf[1], l); + buf[3] = type; + msgpack_pack_append_buffer(x, buf, 4); + } else { + char buf[6]; + buf[0] = 0xc9; + _msgpack_store32(&buf[1], l); + buf[5] = type; + msgpack_pack_append_buffer(x, buf, 6); + } + break; + } +} + +msgpack_pack_inline_func(_ext_body)(msgpack_pack_user x, const void* b, size_t l) +{ + msgpack_pack_append_buffer(x, (const unsigned char*)b, l); +} + #undef msgpack_pack_inline_func #undef msgpack_pack_user #undef msgpack_pack_append_buffer diff --git a/include/msgpack/unpack_template.h b/include/msgpack/unpack_template.h index 598f552f..7e50692f 100644 --- a/include/msgpack/unpack_template.h +++ b/include/msgpack/unpack_template.h @@ -205,9 +205,10 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c case 0xc5: // bin 16 case 0xc6: // bin 32 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); - //case 0xc7: - //case 0xc8: - //case 0xc9: + case 0xc7: // ext 8 + case 0xc8: // ext 16 + case 0xc9: // ext 32 + again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03)); case 0xca: // float case 0xcb: // double case 0xcc: // unsigned int 8 @@ -219,11 +220,15 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c case 0xd2: // signed int 32 case 0xd3: // signed int 64 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); - //case 0xd4: - //case 0xd5: - //case 0xd6: // big integer 16 - //case 0xd7: // big integer 32 - //case 0xd8: // big float 16 + case 0xd4: // fixext 1 + case 0xd5: // fixext 2 + case 0xd6: // fixext 4 + case 0xd7: // fixext 8 + again_fixed_trail_if_zero(ACS_EXT_VALUE, + (1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero); + case 0xd8: // fixext 16 + again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero); + case 0xd9: // str 8 case 0xda: // str 16 case 0xdb: // str 32 @@ -304,31 +309,22 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c _msgpack_load64(int64_t,n,&tmp); push_fixed_value(_int64, tmp); } - - //case CS_ - //case CS_ - //case CS_BIG_INT_16: - // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load16(uint16_t,n), _big_int_zero); - //case CS_BIG_INT_32: - // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load32(uint32_t,n), _big_int_zero); - //case ACS_BIG_INT_VALUE: - //_big_int_zero: - // // FIXME - // push_variable_value(_big_int, data, n, trail); - - //case CS_BIG_FLOAT_16: - // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load16(uint16_t,n), _big_float_zero); - //case CS_BIG_FLOAT_32: - // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load32(uint32_t,n), _big_float_zero); - //case ACS_BIG_FLOAT_VALUE: - //_big_float_zero: - // // FIXME - // push_variable_value(_big_float, data, n, trail); - + case CS_FIXEXT_1: + again_fixed_trail_if_zero(ACS_EXT_VALUE, 1+1, _ext_zero); + case CS_FIXEXT_2: + again_fixed_trail_if_zero(ACS_EXT_VALUE, 2+1, _ext_zero); + case CS_FIXEXT_4: + again_fixed_trail_if_zero(ACS_EXT_VALUE, 4+1, _ext_zero); + case CS_FIXEXT_8: + again_fixed_trail_if_zero(ACS_EXT_VALUE, 8+1, _ext_zero); + case CS_FIXEXT_16: + again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero); case CS_STR_8: again_fixed_trail_if_zero(ACS_STR_VALUE, *(uint8_t*)n, _str_zero); case CS_BIN_8: again_fixed_trail_if_zero(ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero); + case CS_EXT_8: + again_fixed_trail_if_zero(ACS_EXT_VALUE, *(uint8_t*)n, _ext_zero); case CS_STR_16:{ uint16_t tmp; _msgpack_load16(uint16_t,n,&tmp); @@ -339,6 +335,11 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c _msgpack_load16(uint16_t,n,&tmp); again_fixed_trail_if_zero(ACS_BIN_VALUE, tmp, _bin_zero); } + case CS_EXT_16:{ + uint16_t tmp; + _msgpack_load16(uint16_t,n,&tmp); + again_fixed_trail_if_zero(ACS_EXT_VALUE, tmp, _ext_zero); + } case CS_STR_32:{ uint32_t tmp; _msgpack_load32(uint32_t,n,&tmp); @@ -349,12 +350,20 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c _msgpack_load32(uint32_t,n,&tmp); again_fixed_trail_if_zero(ACS_BIN_VALUE, tmp, _bin_zero); } + case CS_EXT_32:{ + uint32_t tmp; + _msgpack_load32(uint32_t,n,&tmp); + again_fixed_trail_if_zero(ACS_EXT_VALUE, tmp, _ext_zero); + } case ACS_STR_VALUE: _str_zero: push_variable_value(_str, data, n, trail); case ACS_BIN_VALUE: _bin_zero: push_variable_value(_bin, data, n, trail); + case ACS_EXT_VALUE: + _ext_zero: + push_variable_value(_ext, data, n, trail); case CS_ARRAY_16:{ uint16_t tmp; diff --git a/src/objectc.c b/src/objectc.c index ff5f6882..840d4332 100644 --- a/src/objectc.c +++ b/src/objectc.c @@ -68,6 +68,13 @@ int msgpack_pack_object(msgpack_packer* pk, msgpack_object d) return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size); } + case MSGPACK_OBJECT_EXT: + { + int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type); + if(ret < 0) { return ret; } + return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size); + } + case MSGPACK_OBJECT_ARRAY: { int ret = msgpack_pack_array(pk, d.via.array.size); @@ -141,6 +148,13 @@ void msgpack_object_print(FILE* out, msgpack_object o) fprintf(out, "\""); break; + case MSGPACK_OBJECT_EXT: + fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type); + fprintf(out, "\""); + fwrite(o.via.ext.ptr, o.via.ext.size, 1, out); + fprintf(out, "\""); + break; + case MSGPACK_OBJECT_ARRAY: fprintf(out, "["); if(o.via.array.size != 0) { @@ -209,6 +223,11 @@ bool msgpack_object_equal(const msgpack_object x, const msgpack_object y) return x.via.bin.size == y.via.bin.size && memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0; + case MSGPACK_OBJECT_EXT: + return x.via.ext.size == y.via.ext.size && + x.via.ext.type == y.via.ext.type && + memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0; + case MSGPACK_OBJECT_ARRAY: if(x.via.array.size != y.via.array.size) { return false; diff --git a/src/unpack.c b/src/unpack.c index 20a02e4b..33b1bec0 100644 --- a/src/unpack.c +++ b/src/unpack.c @@ -261,6 +261,18 @@ static inline int template_callback_bin(unpack_user* u, const char* b, const cha return 0; } +static inline int template_callback_ext(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o) +{ + MSGPACK_UNUSED(u); + MSGPACK_UNUSED(b); + o->type = MSGPACK_OBJECT_EXT; + o->via.ext.type = *p; + o->via.ext.ptr = p + 1; + o->via.ext.size = l - 1; + u->referenced = true; + return 0; +} + #include "msgpack/unpack_template.h" diff --git a/test/msgpackc_test.cpp b/test/msgpackc_test.cpp index 9c1977b0..7d832002 100644 --- a/test/msgpackc_test.cpp +++ b/test/msgpackc_test.cpp @@ -318,6 +318,260 @@ TEST(MSGPACKC, simple_buffer_false) msgpack_sbuffer_destroy(&sbuf); } +TEST(MSGPACKC, simple_buffer_fixext1) +{ + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + char const buf[] = { 2 }; + + msgpack_pack_ext(&pk, sizeof(buf), 1); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(1, obj.via.ext.size); + EXPECT_EQ(1, obj.via.ext.type); + EXPECT_EQ(2, obj.via.ext.ptr[0]); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext2) +{ + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + char const buf[] = { 2, 3 }; + + msgpack_pack_ext(&pk, sizeof(buf), 0); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(2, obj.via.ext.size); + EXPECT_EQ(0, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext4) +{ + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + char const buf[] = { 2, 3, 4, 5 }; + + msgpack_pack_ext(&pk, sizeof(buf), 1); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(4, obj.via.ext.size); + EXPECT_EQ(1, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext8) +{ + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + char const buf [] = { 2, 3, 4, 5, 6, 7, 8, 9 }; + + msgpack_pack_ext(&pk, sizeof(buf), 1); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(8, obj.via.ext.size); + EXPECT_EQ(1, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext16) +{ + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + char const buf [] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; + + msgpack_pack_ext(&pk, sizeof(buf), 1); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(16, obj.via.ext.size); + EXPECT_EQ(1, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext_1byte_0) +{ + const size_t size = 0; + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + + msgpack_pack_ext(&pk, size, 77); + // fprintf(stderr, "size: %u, data: \"", sbuf.size); + // for (size_t i = 0; i < sbuf.size; i++) + // fprintf(stderr, "%02x ", (uint8_t)sbuf.data[i]); + // fprintf(stderr, "\"\n"); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(size, obj.via.ext.size); + EXPECT_EQ(77, obj.via.ext.type); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext_1byte_255) +{ + const size_t size = 255; + char buf[size]; + for (int i = 0; i != size; ++i) buf[i] = i; + + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + + msgpack_pack_ext(&pk, size, 78); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(size, obj.via.ext.size); + EXPECT_EQ(78, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext_2byte_256) +{ + const size_t size = 256; + char buf[size]; + for (int i = 0; i != size; ++i) buf[i] = i; + + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + + msgpack_pack_ext(&pk, size, 79); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(size, obj.via.ext.size); + EXPECT_EQ(79, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext_2byte_65535) +{ + const size_t size = 65535; + char buf[size]; + for (int i = 0; i != size; ++i) buf[i] = i; + + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + + msgpack_pack_ext(&pk, size, 80); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(size, obj.via.ext.size); + EXPECT_EQ(80, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + +TEST(MSGPACKC, simple_buffer_fixext_4byte_65536) +{ + const size_t size = 65536; + char buf[size]; + for (int i = 0; i != size; ++i) buf[i] = i; + + msgpack_sbuffer sbuf; + msgpack_sbuffer_init(&sbuf); + msgpack_packer pk; + msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); + + msgpack_pack_ext(&pk, size, 81); + msgpack_pack_ext_body(&pk, buf, sizeof(buf)); + msgpack_zone z; + msgpack_zone_init(&z, 2048); + msgpack_object obj; + msgpack_unpack_return ret = + msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); + EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); + EXPECT_EQ(MSGPACK_OBJECT_EXT, obj.type); + EXPECT_EQ(size, obj.via.ext.size); + EXPECT_EQ(81, obj.via.ext.type); + EXPECT_EQ(0, memcmp(buf, obj.via.ext.ptr, sizeof(buf))); + msgpack_zone_destroy(&z); + msgpack_sbuffer_destroy(&sbuf); +} + TEST(MSGPACKC, simple_buffer_array) { unsigned int array_size = 5;