mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-14 15:05:37 +02:00
Added a clone function for msgpack::object.
The function prepares zone's chunk that has minimal size to deep copy.
This commit is contained in:
@@ -308,6 +308,12 @@ inline void zone::undo_allocate(size_t 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
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
|
@@ -63,9 +63,9 @@ T& move(T& t)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T const& move(T const& t)
|
||||
T& move(T const& t)
|
||||
{
|
||||
return t;
|
||||
return const_cast<T&>(t);
|
||||
}
|
||||
|
||||
template <bool P, typename T = void>
|
||||
|
@@ -353,6 +353,12 @@ inline void zone::undo_allocate(size_t 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
|
||||
|
||||
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
|
||||
} // MSGPACK_API_VERSION_NAMESPACE(v1)
|
||||
/// @endcond
|
||||
|
@@ -36,6 +36,89 @@ namespace msgpack {
|
||||
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||
/// @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)) { }
|
||||
|
||||
// deprecated
|
||||
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;
|
||||
};
|
||||
|
||||
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));
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object newobj = z.get() ? msgpack::move(msgpack::object(obj, *z)) : msgpack::move(obj);
|
||||
return msgpack::move(object_handle(newobj, msgpack::move(z)));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object newobj = z ? msgpack::object(obj, *z) : obj;
|
||||
return object_handle(newobj, msgpack::move(z));
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
}
|
||||
|
||||
struct object::implicit_type {
|
||||
implicit_type(object const& o) : obj(o) { }
|
||||
~implicit_type() { }
|
||||
|
@@ -991,30 +991,7 @@ inline int context::execute(const char* data, std::size_t len, std::size_t& off)
|
||||
} // detail
|
||||
|
||||
|
||||
class 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;
|
||||
};
|
||||
|
||||
typedef object_handle unpacked;
|
||||
|
||||
class unpacker {
|
||||
public:
|
||||
|
@@ -340,3 +340,86 @@ TEST(object, construct_class_enum_outer)
|
||||
}
|
||||
|
||||
#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);
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::move(msgpack::clone(obj));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::clone(obj);
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
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);
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::move(msgpack::clone(obj));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::clone(obj);
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
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);
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::move(msgpack::clone(obj));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::clone(obj);
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
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);
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::move(msgpack::clone(obj));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::clone(obj);
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
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);
|
||||
#if defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::move(msgpack::clone(obj));
|
||||
#else // defined(MSGPACK_USE_CPP03)
|
||||
msgpack::object_handle h = msgpack::clone(obj);
|
||||
#endif // defined(MSGPACK_USE_CPP03)
|
||||
EXPECT_EQ(h.get(), obj);
|
||||
EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
|
||||
}
|
||||
|
Reference in New Issue
Block a user