diff --git a/src/msgpack/object.hpp b/src/msgpack/object.hpp index 76fe4cae..8c160eaf 100644 --- a/src/msgpack/object.hpp +++ b/src/msgpack/object.hpp @@ -234,6 +234,59 @@ void operator<< (object::with_zone& o, const T& v) v.msgpack_object(static_cast(&o), o.zone); } +template <> +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::RAW: + o.via.raw.ptr = static_cast(o.zone->malloc(v.via.raw.size)); + o.via.raw.size = v.via.raw.size; + ::memcpy(const_cast(o.via.raw.ptr), v.via.raw.ptr, v.via.raw.size); + return; + + case type::ARRAY: + o.via.array.ptr = static_cast(o.zone->malloc(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 = static_cast(o.zone->malloc(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(); + } +} + +template <> +inline void operator<< (object::with_zone& o, const object::with_zone& v) +{ + return o << static_cast(v); +} + inline bool operator==(const object x, const object y) { @@ -412,6 +465,12 @@ packer& operator<< (packer& o, const object& v) } } +template +packer& operator<< (packer& o, const object::with_zone& v) +{ + return o << static_cast(v); +} + } // namespace msgpack diff --git a/test/object.cc b/test/object.cc index 5390c4ae..5d187224 100644 --- a/test/object.cc +++ b/test/object.cc @@ -1,22 +1,27 @@ #include +#include +#include +#include #include struct myclass { myclass() : num(0), str("default") { } - myclass(int num, const std::string& str) : - num(0), str("default") { } + myclass(int n, const std::string& s) : + num(n), str(s) { } ~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 +33,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); @@ -49,7 +54,7 @@ TEST(object, convert) TEST(object, as) { - myclass m1; + myclass m1(1, "custom"); msgpack::sbuffer sbuf; msgpack::pack(sbuf, m1); @@ -65,6 +70,37 @@ TEST(object, as) } +TEST(object, cross_zone_copy) +{ + myclass m1(1, "custom"); + m1.vec.push_back(1.0); + m1.vec.push_back(0.1); + m1.map["one"] = "two"; + + 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].val.via.raw.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[0].val.via.raw.ptr, + obj2.via.array.ptr[3].via.map.ptr[0].val.via.raw.ptr); + } + + EXPECT_EQ(m1, obj1.as()); +} + + TEST(object, print) { msgpack::object obj;