msgpack-c icon indicating copy to clipboard operation
msgpack-c copied to clipboard

Variant of MSGPACK_DEFINE that is intrusive

Open pfeatherstone opened this issue 4 years ago • 7 comments

Is it possible to have a variant of MSGPACK_DEFINE that is non-intrusive. For example, instead of :

struct A
{
int a;
int b;
MSGPACK_DEFINE(a,b);
};

we have:

struct A
{
int a;
int b;
};

MSGPACK_DEFINE_EXTERNAL(A, a,b);

This would be useful to extend the functionality of messagepack. For example, how do i support std::complex?

pfeatherstone avatar Apr 14 '20 09:04 pfeatherstone

Mainly, right now i need to support std::complex. I can look at the adaptor for std::pair to write my own. But a macro would make things a lot easier.

pfeatherstone avatar Apr 14 '20 10:04 pfeatherstone

#ifndef MSGPACK_COMPLEX_H
#define MSGPACK_COMPLEX_H

#include <complex>
#include "msgpack/versioning.hpp"
#include "msgpack/adaptor/adaptor_base.hpp"
#include "msgpack/meta.hpp"

namespace msgpack {

/// @cond
MSGPACK_API_VERSION_NAMESPACE(v1) {
/// @endcond

namespace adaptor {

#if !defined(MSGPACK_USE_CPP03)

template <typename T>
struct as<std::complex<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> 
{
    std::complex<T> operator()(msgpack::object const& o) const 
    {
        if (o.type != msgpack::type::ARRAY)
            throw msgpack::type_error();
        if (o.via.array.size != 2) 
            throw msgpack::type_error();
        return std::complex<T>(o.via.array.ptr[0].as<T>(), o.via.array.ptr[1].as<T>());
    }
};

#endif // !defined(MSGPACK_USE_CPP03)

template <typename T>
struct convert<std::complex<T> > 
{
    msgpack::object const& operator()(msgpack::object const& o, std::complex<T>& v) const 
    {
        if(o.type != msgpack::type::ARRAY)
            throw msgpack::type_error();
        if(o.via.array.size != 2)
            throw msgpack::type_error();
        T real = v.real();
        T imag = v.imag();
        o.via.array.ptr[0].convert(real);
        o.via.array.ptr[1].convert(imag);
        v.real(real);
        v.imag(imag);
        return o;
    }
};

template <typename T>
struct pack<std::complex<T> > 
{
    template <typename Stream>
    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::complex<T>& v) const 
    {
        o.pack_array(2);
        o.pack(v.real());
        o.pack(v.imag());
        return o;
    }
};

template <typename T>
struct object_with_zone<std::complex<T> > 
{
    void operator()(msgpack::object::with_zone& o, const std::complex<T>& v) const 
    {
        o.type = msgpack::type::ARRAY;
        msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*2, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
        o.via.array.ptr = p;
        o.via.array.size = 2;
        p[0] = msgpack::object(v.real(), o.zone);
        p[1] = msgpack::object(v.imag(), o.zone);
    }
};

} // namespace adaptor

/// @cond
}  // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond

}  // namespace msgpack


#endif /* MSGPACK_COMPLEX_H */

pfeatherstone avatar Apr 14 '20 10:04 pfeatherstone

Is this ok?

pfeatherstone avatar Apr 14 '20 10:04 pfeatherstone

https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#non-intrusive-approach

This is a document how to write non-intrusive adaptor. You can use that way.

redboltz avatar Apr 14 '20 10:04 redboltz

I've added a pull request for complex type. I think the CI config is broken because the build is failing when trying to apt install stuff from an azure ppa. @redboltz could you have a look at this. I think other people's pull requests are failing due to the same issue.

pfeatherstone avatar Apr 15 '20 11:04 pfeatherstone

Yes, it seems that CI script needs to update. Unfortunately, I don't have much time. @ygj6 , if you have time, could you investigate CI error?

redboltz avatar Apr 15 '20 12:04 redboltz

the build is failing when trying to apt install stuff from an azure ppa.

Indeed, I will fix it as soon as possible.

ygj6 avatar Apr 16 '20 00:04 ygj6