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;
|
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%><%}%>>
|
||||||
|
@@ -63,9 +63,9 @@ T& move(T& t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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>
|
template <bool P, typename T = void>
|
||||||
|
@@ -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,89 @@ 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)) { }
|
||||||
|
|
||||||
|
// 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 {
|
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:
|
||||||
|
@@ -340,3 +340,86 @@ 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);
|
||||||
|
#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