diff --git a/Files.cmake b/Files.cmake index daa3a7ea..ad92fb94 100644 --- a/Files.cmake +++ b/Files.cmake @@ -15,6 +15,7 @@ SET (msgpackc_HEADERS include/msgpack/adaptor/char_ptr.hpp include/msgpack/adaptor/check_container_size.hpp include/msgpack/adaptor/check_container_size_decl.hpp + include/msgpack/adaptor/complex.hpp include/msgpack/adaptor/cpp11/array.hpp include/msgpack/adaptor/cpp11/array_char.hpp include/msgpack/adaptor/cpp11/array_unsigned_char.hpp @@ -110,6 +111,7 @@ SET (msgpackc_HEADERS include/msgpack/v1/adaptor/char_ptr.hpp include/msgpack/v1/adaptor/check_container_size.hpp include/msgpack/v1/adaptor/check_container_size_decl.hpp + include/msgpack/v1/adaptor/complex.hpp include/msgpack/v1/adaptor/cpp11/array.hpp include/msgpack/v1/adaptor/cpp11/array_char.hpp include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp diff --git a/include/msgpack/adaptor/complex.hpp b/include/msgpack/adaptor/complex.hpp new file mode 100644 index 00000000..34d578e9 --- /dev/null +++ b/include/msgpack/adaptor/complex.hpp @@ -0,0 +1,15 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2020 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef MSGPACK_TYPE_COMPLEX_HPP +#define MSGPACK_TYPE_COMPLEX_HPP + +#include "msgpack/v1/adaptor/complex.hpp" + +#endif // MSGPACK_TYPE_COMPLEX_HPP diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 8f3a0d64..d2f3ee93 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -8,6 +8,7 @@ #include "adaptor/fixint.hpp" #include "adaptor/float.hpp" #include "adaptor/int.hpp" +#include "adaptor/complex.hpp" #include "adaptor/list.hpp" #include "adaptor/map.hpp" #include "adaptor/nil.hpp" diff --git a/include/msgpack/v1/adaptor/complex.hpp b/include/msgpack/v1/adaptor/complex.hpp new file mode 100644 index 00000000..d631b4ac --- /dev/null +++ b/include/msgpack/v1/adaptor/complex.hpp @@ -0,0 +1,91 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2020 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MSGPACK_V1_TYPE_COMPLEX_HPP +#define MSGPACK_V1_TYPE_COMPLEX_HPP + +#include +#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 +struct as, typename std::enable_if::value>::type> { + std::complex 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(o.via.array.ptr[0].as(), o.via.array.ptr[1].as()); + } +}; + +#endif // !defined(MSGPACK_USE_CPP03) + +template +struct convert > { + msgpack::object const& operator()(msgpack::object const& o, std::complex& v) const { + if(o.type != msgpack::type::ARRAY) + throw msgpack::type_error(); + if(o.via.array.size != 2) + throw msgpack::type_error(); + T real; + T imag; + o.via.array.ptr[0].convert(real); + o.via.array.ptr[1].convert(imag); + v.real(real); + v.imag(imag); + return o; + } +}; + +template +struct pack > { + template + msgpack::packer& operator()(msgpack::packer& o, std::complex const& v) const { + o.pack_array(2); + o.pack(v.real()); + o.pack(v.imag()); + return o; + } +}; + +template +struct object_with_zone > { + void operator()(msgpack::object::with_zone& o, std::complex const& v) const { + o.type = msgpack::type::ARRAY; + msgpack::object* p = static_cast(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_V1_TYPE_COMPLEX_HPP diff --git a/make_file_list.sh b/make_file_list.sh index 11045024..f614dd07 100755 --- a/make_file_list.sh +++ b/make_file_list.sh @@ -2,7 +2,7 @@ find include -name "*.hpp" | sed -e 's/\s\+/\n/g' | LC_ALL=C sort > cpp_headers.tmp -echo 'SET (msgpackc_HEADERS' >> Files.cmake +echo 'SET (msgpackc_HEADERS' > Files.cmake cat cpp_headers.tmp | sed -e 's/^/ /g' >> Files.cmake echo ')' >> Files.cmake diff --git a/test/msgpack_container.cpp b/test/msgpack_container.cpp index 0295bbd1..b521c0ec 100644 --- a/test/msgpack_container.cpp +++ b/test/msgpack_container.cpp @@ -372,6 +372,36 @@ TEST(MSGPACK_STL, simple_buffer_pair) } } +TEST(MSGPACK_STL, simple_buffer_complex_float) +{ + complex val1 = complex(1.23F, 4.56F); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::object_handle oh = + msgpack::unpack(sbuf.data(), sbuf.size()); + complex val2 = oh.get().as >(); + EXPECT_EQ(val1, val2); + complex val3; + oh.get().convert(val3); + EXPECT_EQ(val1, val3); + +} + +TEST(MSGPACK_STL, simple_buffer_complex_double) +{ + complex val1 = complex(1.23, 4.56); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::object_handle oh = + msgpack::unpack(sbuf.data(), sbuf.size()); + complex val2 = oh.get().as >(); + EXPECT_EQ(val1, val2); + complex val3; + oh.get().convert(val3); + EXPECT_EQ(val1, val3); + +} + TEST(MSGPACK_STL, simple_buffer_multimap) { typedef multimap, test::allocator > > type; diff --git a/test/object_with_zone.cpp b/test/object_with_zone.cpp index d3faaa21..e454d778 100644 --- a/test/object_with_zone.cpp +++ b/test/object_with_zone.cpp @@ -365,6 +365,33 @@ TEST(object_with_zone, char_ptr) EXPECT_EQ(obj.as()[0], 'a'); } +// complex +TEST(object_with_zone, complex_float) +{ + typedef std::complex test_t; + test_t v(1.23F, 4.56F); + msgpack::zone z; + msgpack::object obj(v, z); + float r = v.real(); + EXPECT_TRUE(fabs(obj.as().real() - v.real()) <= kEPS); + EXPECT_TRUE(fabs(obj.as().imag() - v.imag()) <= kEPS); + v.real(7.89F); + EXPECT_TRUE(fabs(obj.as().real() - r) <= kEPS); +} + +TEST(object_with_zone, complex_double) +{ + typedef std::complex test_t; + test_t v(1.23, 4.56); + msgpack::zone z; + msgpack::object obj(v, z); + double r = v.real(); + EXPECT_TRUE(fabs(obj.as().real() - v.real()) <= kEPS); + EXPECT_TRUE(fabs(obj.as().imag() - v.imag()) <= kEPS); + v.real(7.89); + EXPECT_TRUE(fabs(obj.as().real() - r) <= kEPS); +} + #if MSGPACK_DEFAULT_API_VERSION == 1 TEST(object_without_zone, char_ptr)