mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-15 15:16:51 +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:
@@ -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() { }
|
||||
|
Reference in New Issue
Block a user