From 037b1c22dc348206e4a9278e44e3ead9face81d6 Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Mon, 17 Nov 2014 12:51:34 +0900 Subject: [PATCH] Fixed https://github.com/msgpack/msgpack-c/issues/144 This fix is ogirinally from https://github.com/msgpack/msgpack-c/pull/133 I removed raw support and added str, bin, and ext support. --- include/msgpack/object.hpp | 81 ++++++++++++++++++++ include/msgpack/object_fwd.hpp | 6 ++ test/object.cpp | 131 ++++++++++++++++++++++++++++++++- 3 files changed, 214 insertions(+), 4 deletions(-) diff --git a/include/msgpack/object.hpp b/include/msgpack/object.hpp index 8ad06f38..9a1678e8 100644 --- a/include/msgpack/object.hpp +++ b/include/msgpack/object.hpp @@ -195,6 +195,81 @@ inline packer& operator<< (packer& o, const T& v) return detail::packer_serializer::pack(o, v); } +inline void operator<< (object::with_zone& o, const object& v) +{ + o.type = v.type; + + switch(v.type) { + case type::NIL: + case type::BOOLEAN: + case type::POSITIVE_INTEGER: + case type::NEGATIVE_INTEGER: + case type::DOUBLE: + ::memcpy(&o.via, &v.via, sizeof(v.via)); + return; + + case type::STR: { + char* ptr = static_cast(o.zone.allocate_align(v.via.str.size)); + o.via.str.ptr = ptr; + o.via.str.size = v.via.str.size; + ::memcpy(ptr, v.via.str.ptr, v.via.str.size); + return; + } + + case type::BIN: { + char* ptr = static_cast(o.zone.allocate_align(v.via.bin.size)); + o.via.bin.ptr = ptr; + o.via.bin.size = v.via.bin.size; + ::memcpy(ptr, v.via.bin.ptr, v.via.bin.size); + return; + } + + case type::EXT: { + char* ptr = static_cast(o.zone.allocate_align(v.via.ext.size + 1)); + o.via.ext.ptr = ptr; + o.via.ext.size = v.via.ext.size; + ::memcpy(ptr, v.via.ext.ptr, v.via.ext.size + 1); + return; + } + + case type::ARRAY: + o.via.array.ptr = static_cast(o.zone.allocate_align(sizeof(object) * v.via.array.size)); + o.via.array.size = v.via.array.size; + for (object + * po(o.via.array.ptr), + * pv(v.via.array.ptr), + * const pvend(v.via.array.ptr + v.via.array.size); + pv < pvend; + ++po, ++pv) { + new (po) object(*pv, o.zone); + } + return; + + case type::MAP: + o.via.map.ptr = (object_kv*)o.zone.allocate_align(sizeof(object_kv) * v.via.map.size); + o.via.map.size = v.via.map.size; + for(object_kv + * po(o.via.map.ptr), + * pv(v.via.map.ptr), + * const pvend(v.via.map.ptr + v.via.map.size); + pv < pvend; + ++po, ++pv) { + object_kv* kv = new (po) object_kv; + new (&kv->key) object(pv->key, o.zone); + new (&kv->val) object(pv->val, o.zone); + } + return; + + default: + throw type_error(); + } +} + +inline void operator<< (object::with_zone& o, const object::with_zone& v) +{ + return o << static_cast(v); +} + // deconvert operator template inline void operator<< (object::with_zone& o, const T& v) @@ -551,6 +626,12 @@ inline packer& operator<< (packer& o, const object& v) } } +template +packer& operator<< (packer& o, const object::with_zone& v) +{ + return o << static_cast(v); +} + inline std::ostream& operator<< (std::ostream& s, const object& o) { switch(o.type) { diff --git a/include/msgpack/object_fwd.hpp b/include/msgpack/object_fwd.hpp index a8ae4422..0d01e5ff 100644 --- a/include/msgpack/object_fwd.hpp +++ b/include/msgpack/object_fwd.hpp @@ -150,6 +150,9 @@ object const& operator>> (object const& o, T& v); template void operator<< (object::with_zone& o, const T& v); +void operator<< (object::with_zone& o, const object& v); + +void operator<< (object::with_zone& o, const object::with_zone& v); template class packer; @@ -157,6 +160,9 @@ class packer; template packer& operator<< (packer& o, const object& v); +template +packer& operator<< (packer& o, const object::with_zone& v); + template packer& operator<< (packer& o, const T& v); diff --git a/test/object.cpp b/test/object.cpp index 0cb5c889..e61e7133 100644 --- a/test/object.cpp +++ b/test/object.cpp @@ -11,12 +11,14 @@ struct myclass { int num; std::string str; + std::vector vec; + std::map > map; - MSGPACK_DEFINE(num, str); + MSGPACK_DEFINE(num, str, vec, map); bool operator==(const myclass& o) const { - return num == o.num && str == o.str; + return num == o.num && str == o.str && vec == o.vec && map == o.map; } }; @@ -28,7 +30,7 @@ std::ostream& operator<<(std::ostream& o, const myclass& m) TEST(object, convert) { - myclass m1; + myclass m1(1, "custom"); msgpack::sbuffer sbuf; msgpack::pack(sbuf, m1); @@ -45,7 +47,7 @@ TEST(object, convert) TEST(object, as) { - myclass m1; + myclass m1(1, "custom"); msgpack::sbuffer sbuf; msgpack::pack(sbuf, m1); @@ -56,6 +58,127 @@ TEST(object, as) EXPECT_EQ(m1, ret.get().as()); } +TEST(object, cross_zone_copy) +{ + myclass m1(1, "custom"); + m1.vec.push_back(1.0); + m1.vec.push_back(0.1); + std::vector vc; + vc.push_back('t'); + vc.push_back('w'); + vc.push_back('o'); + m1.map["one"] = vc; + + msgpack::zone z1; + msgpack::object::with_zone obj1(z1); + + { + msgpack::zone z2; + msgpack::object::with_zone obj2(z2); + obj2 << m1; + + obj1 << obj2; + + EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.dec, 1.0); + EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr[0], 'o'); + EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr[0], 't'); + EXPECT_NE( + obj1.via.array.ptr[2].via.array.ptr, + obj2.via.array.ptr[2].via.array.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr, + obj2.via.array.ptr[3].via.map.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr, + obj2.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr, + obj2.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr); + } + + EXPECT_EQ(m1, obj1.as()); +} + +TEST(object, cross_zone_copy_construct) +{ + myclass m1(1, "custom"); + m1.vec.push_back(1.0); + m1.vec.push_back(0.1); + std::vector vc; + vc.push_back('t'); + vc.push_back('w'); + vc.push_back('o'); + m1.map["one"] = vc; + + msgpack::zone z1; + msgpack::zone z2; + msgpack::object::with_zone obj2(z2); + obj2 << m1; + + msgpack::object obj1(obj2, z1); + + EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.dec, 1.0); + EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr[0], 'o'); + EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr[0], 't'); + EXPECT_NE( + obj1.via.array.ptr[2].via.array.ptr, + obj2.via.array.ptr[2].via.array.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr, + obj2.via.array.ptr[3].via.map.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr, + obj2.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr); + EXPECT_NE( + obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr, + obj2.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr); + EXPECT_EQ(m1, obj1.as()); +} + +TEST(object, cross_zone_copy_ext) +{ + msgpack::zone z1; + msgpack::zone z2; + msgpack::object::with_zone obj1(z1); + + obj1.type = msgpack::type::EXT; + char* ptr = static_cast(obj1.zone.allocate_align(2)); + ptr[0] = 1; + ptr[1] = 2; + obj1.via.ext.ptr = ptr; + obj1.via.ext.size = 1; + + msgpack::object::with_zone obj2(z2); + obj2 << obj1; + EXPECT_EQ(obj2.via.ext.size, 1); + EXPECT_EQ(obj2.via.ext.ptr[0], 1); + EXPECT_EQ(obj2.via.ext.ptr[1], 2); + EXPECT_NE( + obj1.via.ext.ptr, + obj2.via.ext.ptr); +} + +TEST(object, cross_zone_copy_construct_ext) +{ + msgpack::zone z1; + msgpack::zone z2; + msgpack::object::with_zone obj1(z1); + + obj1.type = msgpack::type::EXT; + char* ptr = static_cast(obj1.zone.allocate_align(2)); + ptr[0] = 1; + ptr[1] = 2; + obj1.via.ext.ptr = ptr; + obj1.via.ext.size = 1; + + msgpack::object obj2(obj1, z2); + EXPECT_EQ(obj2.via.ext.size, 1); + EXPECT_EQ(obj2.via.ext.ptr[0], 1); + EXPECT_EQ(obj2.via.ext.ptr[1], 2); + EXPECT_NE( + obj1.via.ext.ptr, + obj2.via.ext.ptr); +} TEST(object, print) {