mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-04-26 01:36:19 +02:00
Merge pull request #288 from redboltz/work/add_deep_copy
Added a clone function for msgpack::object.
This commit is contained in:
commit
d6c5682ef5
@ -308,6 +308,12 @@ inline void zone::undo_allocate(size_t size)
|
|||||||
m_chunk_list.m_free += size;
|
m_chunk_list.m_free += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::size_t aligned_size(
|
||||||
|
std::size_t size,
|
||||||
|
std::size_t align = MSGPACK_ZONE_ALIGN) {
|
||||||
|
return (size + align - 1) / align * align;
|
||||||
|
}
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||||
|
@ -353,6 +353,12 @@ inline void zone::undo_allocate(size_t size)
|
|||||||
m_chunk_list.m_free += size;
|
m_chunk_list.m_free += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::size_t aligned_size(
|
||||||
|
std::size_t size,
|
||||||
|
std::size_t align = MSGPACK_ZONE_ALIGN) {
|
||||||
|
return (size + align - 1) / align * align;
|
||||||
|
}
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -363,6 +363,12 @@ T* zone::allocate(Args... args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::size_t aligned_size(
|
||||||
|
std::size_t size,
|
||||||
|
std::size_t align = MSGPACK_ZONE_ALIGN) {
|
||||||
|
return (size + align - 1) / align * align;
|
||||||
|
}
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
} // MSGPACK_API_VERSION_NAMESPACE(v1)
|
} // MSGPACK_API_VERSION_NAMESPACE(v1)
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
@ -36,6 +36,117 @@ namespace msgpack {
|
|||||||
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
class object_handle {
|
||||||
|
public:
|
||||||
|
object_handle() {}
|
||||||
|
|
||||||
|
object_handle(msgpack::object const& obj, msgpack::unique_ptr<msgpack::zone> z) :
|
||||||
|
m_obj(obj), m_zone(msgpack::move(z)) { }
|
||||||
|
|
||||||
|
// obsolete
|
||||||
|
void set(msgpack::object const& obj)
|
||||||
|
{ m_obj = obj; }
|
||||||
|
|
||||||
|
const msgpack::object& get() const
|
||||||
|
{ return m_obj; }
|
||||||
|
|
||||||
|
msgpack::unique_ptr<msgpack::zone>& zone()
|
||||||
|
{ return m_zone; }
|
||||||
|
|
||||||
|
const msgpack::unique_ptr<msgpack::zone>& zone() const
|
||||||
|
{ return m_zone; }
|
||||||
|
|
||||||
|
#if defined(MSGPACK_USE_CPP03)
|
||||||
|
struct object_handle_ref {
|
||||||
|
object_handle_ref(object_handle* oh):m_oh(oh) {}
|
||||||
|
object_handle* m_oh;
|
||||||
|
};
|
||||||
|
|
||||||
|
object_handle(object_handle& other):
|
||||||
|
m_obj(other.m_obj),
|
||||||
|
m_zone(msgpack::move(other.m_zone)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
object_handle(object_handle_ref ref):
|
||||||
|
m_obj(ref.m_oh->m_obj),
|
||||||
|
m_zone(msgpack::move(ref.m_oh->m_zone)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
object_handle& operator=(object_handle& other) {
|
||||||
|
m_obj = other.m_obj;
|
||||||
|
m_zone = msgpack::move(other.m_zone);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_handle& operator=(object_handle_ref ref) {
|
||||||
|
m_obj = ref.m_oh->m_obj;
|
||||||
|
m_zone = msgpack::move(ref.m_oh->m_zone);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator object_handle_ref() {
|
||||||
|
return object_handle_ref(this);
|
||||||
|
}
|
||||||
|
#endif // defined(MSGPACK_USE_CPP03)
|
||||||
|
|
||||||
|
private:
|
||||||
|
msgpack::object m_obj;
|
||||||
|
msgpack::unique_ptr<msgpack::zone> m_zone;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
inline std::size_t add_ext_type_size(std::size_t size) {
|
||||||
|
return size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline std::size_t add_ext_type_size<4>(std::size_t size) {
|
||||||
|
return size == 0xffffffff ? size : size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
inline std::size_t aligned_zone_size(msgpack::object const& obj) {
|
||||||
|
std::size_t s = 0;
|
||||||
|
switch (obj.type) {
|
||||||
|
case msgpack::type::ARRAY:
|
||||||
|
s += sizeof(msgpack::object) * obj.via.array.size;
|
||||||
|
for (uint32_t i = 0; i < obj.via.array.size; ++i) {
|
||||||
|
s += msgpack::aligned_zone_size(obj.via.array.ptr[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case msgpack::type::MAP:
|
||||||
|
s += sizeof(msgpack::object_kv) * obj.via.map.size;
|
||||||
|
for (uint32_t i = 0; i < obj.via.map.size; ++i) {
|
||||||
|
s += msgpack::aligned_zone_size(obj.via.map.ptr[i].key);
|
||||||
|
s += msgpack::aligned_zone_size(obj.via.map.ptr[i].val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case msgpack::type::EXT:
|
||||||
|
s += msgpack::aligned_size(
|
||||||
|
detail::add_ext_type_size<sizeof(std::size_t)>(obj.via.ext.size));
|
||||||
|
break;
|
||||||
|
case msgpack::type::STR:
|
||||||
|
s += msgpack::aligned_size(obj.via.str.size);
|
||||||
|
break;
|
||||||
|
case msgpack::type::BIN:
|
||||||
|
s += msgpack::aligned_size(obj.via.bin.size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object_handle clone(msgpack::object const& obj) {
|
||||||
|
std::size_t size = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::unique_ptr<msgpack::zone> z(size == 0 ? nullptr : new msgpack::zone(size));
|
||||||
|
msgpack::object newobj = z.get() ? msgpack::object(obj, *z) : obj;
|
||||||
|
return object_handle(newobj, msgpack::move(z));
|
||||||
|
}
|
||||||
|
|
||||||
struct object::implicit_type {
|
struct object::implicit_type {
|
||||||
implicit_type(object const& o) : obj(o) { }
|
implicit_type(object const& o) : obj(o) { }
|
||||||
~implicit_type() { }
|
~implicit_type() { }
|
||||||
|
@ -991,30 +991,7 @@ inline int context::execute(const char* data, std::size_t len, std::size_t& off)
|
|||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
|
||||||
class unpacked {
|
typedef object_handle unpacked;
|
||||||
public:
|
|
||||||
unpacked() {}
|
|
||||||
|
|
||||||
unpacked(msgpack::object const& obj, msgpack::unique_ptr<msgpack::zone> z) :
|
|
||||||
m_obj(obj), m_zone(msgpack::move(z)) { }
|
|
||||||
|
|
||||||
void set(msgpack::object const& obj)
|
|
||||||
{ m_obj = obj; }
|
|
||||||
|
|
||||||
const msgpack::object& get() const
|
|
||||||
{ return m_obj; }
|
|
||||||
|
|
||||||
msgpack::unique_ptr<msgpack::zone>& zone()
|
|
||||||
{ return m_zone; }
|
|
||||||
|
|
||||||
const msgpack::unique_ptr<msgpack::zone>& zone() const
|
|
||||||
{ return m_zone; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
msgpack::object m_obj;
|
|
||||||
msgpack::unique_ptr<msgpack::zone> m_zone;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class unpacker {
|
class unpacker {
|
||||||
public:
|
public:
|
||||||
@ -1143,8 +1120,6 @@ private:
|
|||||||
#endif // defined(MSGPACK_USE_CPP03)
|
#endif // defined(MSGPACK_USE_CPP03)
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
unpacked unpack(
|
unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
||||||
unpack_reference_func f = nullptr, void* user_data = nullptr,
|
unpack_reference_func f = nullptr, void* user_data = nullptr,
|
||||||
@ -1162,8 +1137,6 @@ unpacked unpack(
|
|||||||
unpack_reference_func f = nullptr, void* user_data = nullptr,
|
unpack_reference_func f = nullptr, void* user_data = nullptr,
|
||||||
unpack_limit const& limit = unpack_limit());
|
unpack_limit const& limit = unpack_limit());
|
||||||
|
|
||||||
#endif // !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
|
|
||||||
void unpack(unpacked& result,
|
void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
||||||
@ -1554,8 +1527,6 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off,
|
|||||||
|
|
||||||
// reference version
|
// reference version
|
||||||
|
|
||||||
#if !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
inline unpacked unpack(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
||||||
unpack_reference_func f, void* user_data, unpack_limit const& limit)
|
unpack_reference_func f, void* user_data, unpack_limit const& limit)
|
||||||
@ -1605,8 +1576,6 @@ inline unpacked unpack(
|
|||||||
return unpack(data, len, off, referenced, f, user_data, limit);
|
return unpack(data, len, off, referenced, f, user_data, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
inline void unpack(unpacked& result,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
||||||
unpack_reference_func f, void* user_data, unpack_limit const& limit)
|
unpack_reference_func f, void* user_data, unpack_limit const& limit)
|
||||||
|
@ -340,3 +340,81 @@ TEST(object, construct_class_enum_outer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(MSGPACK_USE_CPP03)
|
#endif // !defined(MSGPACK_USE_CPP03)
|
||||||
|
|
||||||
|
TEST(object, clone_int)
|
||||||
|
{
|
||||||
|
int v = 0;
|
||||||
|
msgpack::object obj(v);
|
||||||
|
std::size_t sz1 = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::object_handle h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(object, clone_str)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
std::string v = "123456789";
|
||||||
|
msgpack::object obj(v, z);
|
||||||
|
std::size_t sz1 = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::object_handle h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(object, clone_bin)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
std::vector<char> v;
|
||||||
|
v.push_back('A');
|
||||||
|
v.push_back('B');
|
||||||
|
v.push_back('C');
|
||||||
|
msgpack::object obj(v, z);
|
||||||
|
std::size_t sz1 = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::object_handle h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(object, clone_array)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
std::vector<int> v;
|
||||||
|
v.push_back(1);
|
||||||
|
v.push_back(2);
|
||||||
|
v.push_back(3);
|
||||||
|
msgpack::object obj(v, z);
|
||||||
|
std::size_t sz1 = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::object_handle h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(object, clone_map)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
std::map<int, std::string> v;
|
||||||
|
v.insert(std::map<int, std::string>::value_type(1, "ABC"));
|
||||||
|
v.insert(std::map<int, std::string>::value_type(2, "DEF"));
|
||||||
|
v.insert(std::map<int, std::string>::value_type(3, "GHI"));
|
||||||
|
msgpack::object obj(v, z);
|
||||||
|
std::size_t sz1 = msgpack::aligned_zone_size(obj);
|
||||||
|
msgpack::object_handle h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
h = msgpack::clone(obj);
|
||||||
|
EXPECT_EQ(h.get(), obj);
|
||||||
|
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||||
|
}
|
||||||
|
@ -50,8 +50,6 @@ TEST(pack, myclass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
TEST(unpack, int_ret_no_offset_no_ref)
|
TEST(unpack, int_ret_no_offset_no_ref)
|
||||||
{
|
{
|
||||||
msgpack::sbuffer sbuf;
|
msgpack::sbuffer sbuf;
|
||||||
@ -97,8 +95,6 @@ TEST(unpack, int_ret_offset_ref)
|
|||||||
EXPECT_EQ(off, sbuf.size());
|
EXPECT_EQ(off, sbuf.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(MSGPACK_USE_CPP03)
|
|
||||||
|
|
||||||
|
|
||||||
TEST(unpack, int_no_offset_no_ref)
|
TEST(unpack, int_no_offset_no_ref)
|
||||||
{
|
{
|
||||||
@ -290,3 +286,34 @@ TEST(unpack, sequence)
|
|||||||
|
|
||||||
EXPECT_EQ(off, sbuf.size());
|
EXPECT_EQ(off, sbuf.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(unpack, convert_to_object_handle)
|
||||||
|
{
|
||||||
|
msgpack::sbuffer sbuf;
|
||||||
|
msgpack::pack(sbuf, 1);
|
||||||
|
msgpack::unpacked msg;
|
||||||
|
|
||||||
|
msgpack::unpack(msg, sbuf.data(), sbuf.size());
|
||||||
|
msgpack::object_handle oh(msgpack::move(msg));
|
||||||
|
EXPECT_EQ(1, oh.get().as<int>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unpack, convert_to_object_handle_direct)
|
||||||
|
{
|
||||||
|
msgpack::sbuffer sbuf;
|
||||||
|
msgpack::pack(sbuf, 1);
|
||||||
|
msgpack::object_handle oh(msgpack::unpack(sbuf.data(), sbuf.size()));
|
||||||
|
EXPECT_EQ(1, oh.get().as<int>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unpack, convert_to_object_handle_direct_implicit)
|
||||||
|
{
|
||||||
|
msgpack::sbuffer sbuf;
|
||||||
|
msgpack::pack(sbuf, 1);
|
||||||
|
msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size());
|
||||||
|
EXPECT_EQ(1, oh.get().as<int>());
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user