diff --git a/include/msgpack/unpack.hpp b/include/msgpack/unpack.hpp index d6199145..e7be9f20 100644 --- a/include/msgpack/unpack.hpp +++ b/include/msgpack/unpack.hpp @@ -964,6 +964,24 @@ private: unpacker& operator=(const unpacker&); }; +#if !defined(MSGPACK_USE_CPP03) + +inline unpacked unpack( + const char* data, std::size_t len, std::size_t& off, bool& referenced, + unpack_reference_func f = nullptr, void* user_data = nullptr); +inline unpacked unpack( + const char* data, std::size_t len, std::size_t& off, + unpack_reference_func f = nullptr, void* user_data = nullptr); +inline unpacked unpack( + const char* data, std::size_t len, bool& referenced, + unpack_reference_func f = nullptr, void* user_data = nullptr); +inline unpacked unpack( + const char* data, std::size_t len, + unpack_reference_func f = nullptr, void* user_data = nullptr); + +#endif // !defined(MSGPACK_USE_CPP03) + + inline void unpack(unpacked& result, const char* data, std::size_t len, std::size_t& off, bool& referenced, unpack_reference_func f = nullptr, void* user_data = nullptr); @@ -1312,6 +1330,61 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off, } // detail // reference version + +#if !defined(MSGPACK_USE_CPP03) + +inline unpacked unpack( + const char* data, std::size_t len, std::size_t& off, bool& referenced, + unpack_reference_func f, void* user_data) +{ + object obj; + msgpack::unique_ptr z(new zone); + referenced = false; + unpack_return ret = detail::unpack_imp( + data, len, off, *z, obj, referenced, f, user_data); + + switch(ret) { + case UNPACK_SUCCESS: + return unpacked(obj, msgpack::move(z)); + case UNPACK_EXTRA_BYTES: + return unpacked(obj, msgpack::move(z)); + case UNPACK_CONTINUE: + throw unpack_error("insufficient bytes"); + case UNPACK_PARSE_ERROR: + default: + throw unpack_error("parse error"); + } + return unpacked(); +} + +inline unpacked unpack( + const char* data, std::size_t len, std::size_t& off, + unpack_reference_func f, void* user_data) +{ + bool referenced; + return unpack(data, len, off, referenced, f, user_data); +} + +inline unpacked unpack( + const char* data, std::size_t len, bool& referenced, + unpack_reference_func f, void* user_data) +{ + std::size_t off = 0; + return unpack(data, len, off, referenced, f, user_data); +} + +inline unpacked unpack( + const char* data, std::size_t len, + unpack_reference_func f, void* user_data) +{ + bool referenced; + std::size_t off = 0; + return unpack(data, len, off, referenced, f, user_data); +} + +#endif // !defined(MSGPACK_USE_CPP03) + + inline void unpack(unpacked& result, const char* data, std::size_t len, std::size_t& off, bool& referenced, unpack_reference_func f, void* user_data) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3c971a29..59bf41d8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ LIST (APPEND check_PROGRAMS IF (MSGPACK_CXX11) LIST (APPEND check_PROGRAMS msgpack_cpp11.cpp + reference_cpp11.cpp ) ENDIF () diff --git a/test/Makefile.am b/test/Makefile.am index 35859b3a..c12c56d2 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -23,6 +23,7 @@ check_PROGRAMS = \ msgpack_stream \ msgpack_vref \ msgpack_cpp11 \ + reference_cpp11 \ reference TESTS = $(check_PROGRAMS) @@ -70,4 +71,6 @@ msgpack_cpp11_SOURCES = msgpack_cpp11.cpp reference_SOURCES = reference.cpp +reference_cpp11_SOURCES = reference_cpp11.cpp + EXTRA_DIST = cases.mpac cases_compact.mpac diff --git a/test/pack_unpack.cpp b/test/pack_unpack.cpp index b95bccde..da635683 100644 --- a/test/pack_unpack.cpp +++ b/test/pack_unpack.cpp @@ -49,7 +49,58 @@ TEST(pack, myclass) msgpack::pack(sbuf, m); } -TEST(unpack, int_no_offset) + +#if !defined(MSGPACK_USE_CPP03) + +TEST(unpack, int_ret_no_offset_no_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + + msgpack::unpacked msg = msgpack::unpack(sbuf.data(), sbuf.size()); + EXPECT_EQ(1, msg.get().as()); +} + +TEST(unpack, int_ret_offset_no_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + + std::size_t off = 0; + + msgpack::unpacked msg = msgpack::unpack(sbuf.data(), sbuf.size(), off); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(off, sbuf.size()); +} + +TEST(unpack, int_ret_no_offset_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + bool referenced; + + msgpack::unpacked msg = msgpack::unpack(sbuf.data(), sbuf.size(), referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(false, referenced); +} + +TEST(unpack, int_ret_offset_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + std::size_t off = 0; + bool referenced; + + msgpack::unpacked msg = msgpack::unpack(sbuf.data(), sbuf.size(), off, referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(false, referenced); + EXPECT_EQ(off, sbuf.size()); +} + +#endif // !defined(MSGPACK_USE_CPP03) + + +TEST(unpack, int_no_offset_no_ref) { msgpack::sbuffer sbuf; msgpack::pack(sbuf, 1); @@ -59,7 +110,7 @@ TEST(unpack, int_no_offset) EXPECT_EQ(1, msg.get().as()); } -TEST(unpack, int_offset) +TEST(unpack, int_offset_no_ref) { msgpack::sbuffer sbuf; msgpack::pack(sbuf, 1); @@ -72,7 +123,34 @@ TEST(unpack, int_offset) EXPECT_EQ(off, sbuf.size()); } -TEST(unpack, int_pointer) +TEST(unpack, int_no_offset_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + msgpack::unpacked msg; + bool referenced; + + msgpack::unpack(msg, sbuf.data(), sbuf.size(), referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(false, referenced); +} + +TEST(unpack, int_offset_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + msgpack::unpacked msg; + std::size_t off = 0; + bool referenced; + + msgpack::unpack(msg, sbuf.data(), sbuf.size(), off, referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(false, referenced); + EXPECT_EQ(off, sbuf.size()); +} + + +TEST(unpack, int_pointer_off_no_ref) { msgpack::sbuffer sbuf; msgpack::pack(sbuf, 1); @@ -86,17 +164,49 @@ TEST(unpack, int_pointer) EXPECT_EQ(off, sbuf.size()); } -TEST(unpack, int_null_pointer) +TEST(unpack, int_pointer_off_no_ref_explicit) { msgpack::sbuffer sbuf; msgpack::pack(sbuf, 1); msgpack::unpacked msg; + std::size_t off = 0; + // obsolete - msgpack::unpack(&msg, sbuf.data(), sbuf.size(), nullptr); + msgpack::unpack(&msg, sbuf.data(), sbuf.size(), &off, nullptr); EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(off, sbuf.size()); } +TEST(unpack, int_pointer_no_off_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + msgpack::unpacked msg; + bool referenced; + + // obsolete + msgpack::unpack(&msg, sbuf.data(), sbuf.size(), nullptr, &referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(false, referenced); +} + +TEST(unpack, int_pointer_off_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + msgpack::unpacked msg; + bool referenced; + std::size_t off = 0; + + // obsolete + msgpack::unpack(&msg, sbuf.data(), sbuf.size(), &off, &referenced); + EXPECT_EQ(1, msg.get().as()); + EXPECT_EQ(off, sbuf.size()); + EXPECT_EQ(false, referenced); +} + + TEST(unpack, int_default_null_pointer) { msgpack::sbuffer sbuf; diff --git a/test/reference_cpp11.cpp b/test/reference_cpp11.cpp new file mode 100644 index 00000000..e4112024 --- /dev/null +++ b/test/reference_cpp11.cpp @@ -0,0 +1,232 @@ +#include +#include + +#if !defined(MSGPACK_USE_CPP03) + +TEST(reference, unpack_int) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + bool referenced; + + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced); + EXPECT_FALSE(referenced); +} + +TEST(reference, unpack_string) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, std::string("abcdefg")); + bool referenced; + + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced); + EXPECT_FALSE(referenced); +} + +TEST(reference, unpack_bin) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char c[] = { 1, 2, 3, 4, 5, 6 }; + packer.pack_bin(sizeof(c)); + packer.pack_bin_body(c, sizeof(c)); + + bool referenced; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced); + EXPECT_FALSE(referenced); +} + +TEST(reference, unpack_ext) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char const buf [] = { 2 }; + + packer.pack_ext(sizeof(buf), 1); + packer.pack_ext_body(buf, sizeof(buf)); + bool referenced; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced); + EXPECT_FALSE(referenced); +} + +bool never_called(msgpack::type::object_type, std::size_t, void*) +{ + EXPECT_TRUE(false); + return false; +} + +bool always_reference(msgpack::type::object_type, std::size_t, void*) +{ + return true; +} + +TEST(reference, unpack_int_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + bool referenced; + + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, never_called); + EXPECT_FALSE(referenced); +} + +TEST(reference, unpack_string_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, std::string("abcdefg")); + bool referenced; + + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, always_reference); + EXPECT_TRUE(referenced); +} + +TEST(reference, unpack_bin_ref) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char c[] = { 1, 2, 3, 4, 5, 6 }; + packer.pack_bin(sizeof(c)); + packer.pack_bin_body(c, sizeof(c)); + + bool referenced; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, always_reference); + EXPECT_TRUE(referenced); +} + +TEST(reference, unpack_ext_ref) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char const buf [] = { 2 }; + + packer.pack_ext(sizeof(buf), 1); + packer.pack_ext_body(buf, sizeof(buf)); + bool referenced; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, always_reference); + EXPECT_TRUE(referenced); +} + +static void* s_p; + +bool sized_reference(msgpack::type::object_type t, std::size_t s, void* p) +{ + s_p = p; + switch (t) { + case msgpack::type::STR: + if (s >= 5) return true; + break; + case msgpack::type::BIN: + if (s >= 6) return true; + break; + case msgpack::type::EXT: + if (s >= 7) return true; + break; + default: + EXPECT_TRUE(false); + } + return false; +} + +TEST(reference, unpack_int_sized_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 1); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, never_called, &sbuf); + EXPECT_FALSE(referenced); + EXPECT_EQ(nullptr, s_p); +} + +TEST(reference, unpack_string_sized_ref_4) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, std::string("1234")); + + bool referenced; + s_p = nullptr; + // the last argument sbuf is any pointer as a user data. + // That is stored to s_p in sized_reference + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_FALSE(referenced); + // compare the passed argument with stored s_p. + EXPECT_EQ(&sbuf, s_p); +} + +TEST(reference, unpack_string_sized_ref_5) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, std::string("12345")); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_TRUE(referenced); + EXPECT_EQ(&sbuf, s_p); +} + + +TEST(reference, unpack_bin_sized_ref_5) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char c[] = { 1, 2, 3, 4, 5 }; + packer.pack_bin(sizeof(c)); + packer.pack_bin_body(c, sizeof(c)); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_FALSE(referenced); + EXPECT_EQ(&sbuf, s_p); +} + +TEST(reference, unpack_bin_sized_ref_6) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char c[] = { 1, 2, 3, 4, 5, 6 }; + packer.pack_bin(sizeof(c)); + packer.pack_bin_body(c, sizeof(c)); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_TRUE(referenced); + EXPECT_EQ(&sbuf, s_p); +} + +TEST(reference, unpack_ext_sized_ref_6) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char const buf [] = { 1, 2, 3, 4, 5 }; + + packer.pack_ext(sizeof(buf), 1); // 5 + 1(type) = 6 + packer.pack_ext_body(buf, sizeof(buf)); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_FALSE(referenced); + EXPECT_EQ(&sbuf, s_p); +} + +TEST(reference, unpack_ext_sized_ref_7) +{ + msgpack::sbuffer sbuf; + msgpack::packer packer(sbuf); + char const buf [] = { 1, 2, 3, 4, 5, 6 }; + + packer.pack_ext(sizeof(buf), 1); // 6 + 1(type) = 7 + packer.pack_ext_body(buf, sizeof(buf)); + + bool referenced; + s_p = nullptr; + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size(), referenced, sized_reference, &sbuf); + EXPECT_TRUE(referenced); + EXPECT_EQ(&sbuf, s_p); +} + +#endif // !defined(MSGPACK_USE_CPP03)