Merge pull request #288 from redboltz/work/add_deep_copy

Added a clone function for msgpack::object.
This commit is contained in:
Takatoshi Kondo 2015-06-01 17:45:46 +09:00
commit d6c5682ef5
7 changed files with 239 additions and 36 deletions

View File

@ -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%><%}%>>

View File

@ -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>

View File

@ -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

View File

@ -36,6 +36,117 @@ 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)) { }
// 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 {
implicit_type(object const& o) : obj(o) { }
~implicit_type() { }

View File

@ -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:
@ -1143,8 +1120,6 @@ private:
#endif // defined(MSGPACK_USE_CPP03)
};
#if !defined(MSGPACK_USE_CPP03)
unpacked unpack(
const char* data, std::size_t len, std::size_t& off, bool& referenced,
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_limit const& limit = unpack_limit());
#endif // !defined(MSGPACK_USE_CPP03)
void unpack(unpacked& result,
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
#if !defined(MSGPACK_USE_CPP03)
inline unpacked unpack(
const char* data, std::size_t len, std::size_t& off, bool& referenced,
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);
}
#endif // !defined(MSGPACK_USE_CPP03)
inline void unpack(unpacked& result,
const char* data, std::size_t len, std::size_t& off, bool& referenced,
unpack_reference_func f, void* user_data, unpack_limit const& limit)

View File

@ -340,3 +340,81 @@ 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);
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()));
}

View File

@ -50,8 +50,6 @@ TEST(pack, myclass)
}
#if !defined(MSGPACK_USE_CPP03)
TEST(unpack, int_ret_no_offset_no_ref)
{
msgpack::sbuffer sbuf;
@ -97,8 +95,6 @@ TEST(unpack, int_ret_offset_ref)
EXPECT_EQ(off, sbuf.size());
}
#endif // !defined(MSGPACK_USE_CPP03)
TEST(unpack, int_no_offset_no_ref)
{
@ -290,3 +286,34 @@ TEST(unpack, sequence)
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>());
}