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:
Takatoshi Kondo
2015-05-20 12:43:03 +09:00
parent 432c9cc542
commit e18f5b2d52
7 changed files with 187 additions and 26 deletions

View File

@@ -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() { }