diff --git a/CMakeLists.txt b/CMakeLists.txt index 8af0b372..d7ac4200 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,9 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/adaptor/cpp11/array.hpp include/msgpack/adaptor/cpp11/array_char.hpp include/msgpack/adaptor/cpp11/forward_list.hpp + include/msgpack/adaptor/cpp11/shared_ptr.hpp include/msgpack/adaptor/cpp11/tuple.hpp + include/msgpack/adaptor/cpp11/unique_ptr.hpp include/msgpack/adaptor/cpp11/unordered_map.hpp include/msgpack/adaptor/cpp11/unordered_set.hpp include/msgpack/adaptor/define.hpp diff --git a/include/msgpack/adaptor/cpp11/shared_ptr.hpp b/include/msgpack/adaptor/cpp11/shared_ptr.hpp new file mode 100644 index 00000000..176e6e45 --- /dev/null +++ b/include/msgpack/adaptor/cpp11/shared_ptr.hpp @@ -0,0 +1,90 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef MSGPACK_CPP11_SHARED_PTR_HPP +#define MSGPACK_CPP11_SHARED_PTR_HPP + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" + +#include + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace adaptor { + +template +struct as, typename std::enable_if::value>::type> { + std::shared_ptr operator()(msgpack::object const& o) const { + if(o.is_nil()) return nullptr; + return std::make_shared(o.as()); + } +}; + +template +struct convert> { + msgpack::object const& operator()(msgpack::object const& o, std::shared_ptr& v) const { + if(o.is_nil()) v.reset(); + else { + v = std::make_shared(); + msgpack::adaptor::convert()(o, *v); + } + return o; + } +}; + +template +struct pack> { + template + msgpack::packer& operator()(msgpack::packer& o, const std::shared_ptr& v) const { + if (v) o.pack(*v); + else o.pack_nil(); + return o; + } +}; + +template +struct object > { + void operator()(msgpack::object& o, const std::shared_ptr& v) const { + if (v) msgpack::adaptor::object()(o, *v); + else o.type = msgpack::type::NIL; + } +}; + +template +struct object_with_zone> { + void operator()(msgpack::object::with_zone& o, const std::shared_ptr& v) const { + if (v) msgpack::adaptor::object_with_zone()(o, *v); + else o.type = msgpack::type::NIL; + } +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_CPP11_SHARED_PTR_HPP diff --git a/include/msgpack/adaptor/cpp11/unique_ptr.hpp b/include/msgpack/adaptor/cpp11/unique_ptr.hpp new file mode 100644 index 00000000..4ed813c6 --- /dev/null +++ b/include/msgpack/adaptor/cpp11/unique_ptr.hpp @@ -0,0 +1,90 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef MSGPACK_CPP11_UNIQUE_PTR_HPP +#define MSGPACK_CPP11_UNIQUE_PTR_HPP + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" + +#include + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace adaptor { + +template +struct as, typename std::enable_if::value>::type> { + std::unique_ptr operator()(msgpack::object const& o) const { + if(o.is_nil()) return nullptr; + return std::unique_ptr(new T(o.as())); + } +}; + +template +struct convert> { + msgpack::object const& operator()(msgpack::object const& o, std::unique_ptr& v) const { + if(o.is_nil()) v.reset(); + else { + v.reset(new T); + msgpack::adaptor::convert()(o, *v); + } + return o; + } +}; + +template +struct pack> { + template + msgpack::packer& operator()(msgpack::packer& o, const std::unique_ptr& v) const { + if (v) o.pack(*v); + else o.pack_nil(); + return o; + } +}; + +template +struct object > { + void operator()(msgpack::object& o, const std::unique_ptr& v) const { + if (v) msgpack::adaptor::object()(o, *v); + else o.type = msgpack::type::NIL; + } +}; + +template +struct object_with_zone> { + void operator()(msgpack::object::with_zone& o, const std::unique_ptr& v) const { + if (v) msgpack::adaptor::object_with_zone()(o, *v); + else o.type = msgpack::type::NIL; + } +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_CPP11_UNIQUE_PTR_HPP diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 349f7ad1..4619fe0f 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -30,7 +30,9 @@ #include "adaptor/cpp11/array.hpp" #include "adaptor/cpp11/array_char.hpp" #include "adaptor/cpp11/forward_list.hpp" +#include "adaptor/cpp11/shared_ptr.hpp" #include "adaptor/cpp11/tuple.hpp" +#include "adaptor/cpp11/unique_ptr.hpp" #include "adaptor/cpp11/unordered_map.hpp" #include "adaptor/cpp11/unordered_set.hpp" diff --git a/src/Makefile.am b/src/Makefile.am index 6fcd9b45..0cb15be8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,7 +64,9 @@ nobase_include_HEADERS += \ ../include/msgpack/adaptor/cpp11/array.hpp \ ../include/msgpack/adaptor/cpp11/array_char.hpp \ ../include/msgpack/adaptor/cpp11/forward_list.hpp \ + ../include/msgpack/adaptor/cpp11/shared_ptr.hpp \ ../include/msgpack/adaptor/cpp11/tuple.hpp \ + ../include/msgpack/adaptor/cpp11/unique_ptr.hpp \ ../include/msgpack/adaptor/cpp11/unordered_map.hpp \ ../include/msgpack/adaptor/cpp11/unordered_set.hpp \ ../include/msgpack/adaptor/define.hpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7a16b9a2..5775fd2a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,30 +8,30 @@ INCLUDE_DIRECTORIES ( ) LIST (APPEND check_PROGRAMS - zone.cpp - pack_unpack.cpp - pack_unpack_c.cpp - streaming.cpp - streaming_c.cpp - object.cpp - object_with_zone.cpp - version.cpp - convert.cpp buffer.cpp cases.cpp + convert.cpp fixint.cpp fixint_c.cpp - msgpack_tuple.cpp + json.cpp + limit.cpp msgpack_basic.cpp + msgpack_c.cpp msgpack_container.cpp msgpack_stream.cpp + msgpack_tuple.cpp msgpack_vref.cpp - msgpack_c.cpp - reference.cpp - limit.cpp - json.cpp + object.cpp + object_with_zone.cpp + pack_unpack.cpp + pack_unpack_c.cpp raw.cpp + reference.cpp + streaming.cpp + streaming_c.cpp user_class.cpp + version.cpp + zone.cpp ) IF (MSGPACK_BOOST) @@ -44,9 +44,11 @@ ENDIF () IF (MSGPACK_CXX11) LIST (APPEND check_PROGRAMS - msgpack_cpp11.cpp - reference_cpp11.cpp iterator_cpp11.cpp + msgpack_cpp11.cpp + shared_ptr_cpp11.cpp + unique_ptr_cpp11.cpp + reference_cpp11.cpp ) ENDIF () diff --git a/test/Makefile.am b/test/Makefile.am index 80b409af..8848b53c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,101 +3,85 @@ AM_C_CPPFLAGS = -I$(top_srcdir)/include AM_LDFLAGS = $(top_builddir)/src/libmsgpack.la -lgtest_main -lgtest -pthread check_PROGRAMS = \ - zone \ - pack_unpack \ - pack_unpack_c \ - streaming \ - streaming_c \ - object \ - object_with_zone \ - convert \ buffer \ cases \ + convert \ fixint \ fixint_c \ - version \ - msgpack_tuple \ - msgpack_c \ + json \ + limit \ msgpack_basic \ + msgpack_c \ msgpack_container \ msgpack_stream \ + msgpack_tuple \ msgpack_vref \ - msgpack_cpp11 \ - multi_file \ - reference_cpp11 \ - reference \ - limit \ - json \ + object \ + object_with_zone \ + pack_unpack \ + pack_unpack_c \ raw \ + reference \ + streaming \ + streaming_c \ user_class \ - iterator_cpp11 \ + version \ + zone + +check_PROGRAMS += \ boost_fusion \ boost_optional \ boost_string_ref +check_PROGRAMS += \ + iterator_cpp11 \ + msgpack_cpp11 \ + reference_cpp11 \ + shared_ptr_cpp11 \ + unique_ptr_cpp11 + +check_PROGRAMS += \ + multi_file + TESTS = $(check_PROGRAMS) +buffer_SOURCES = buffer.cpp +cases_SOURCES = cases.cpp +convert_SOURCES = convert.cpp +fixint_SOURCES = fixint.cpp +fixint_c_SOURCES = fixint_c.cpp +json_SOURCES = json.cpp +limit_SOURCES = limit.cpp +msgpack_basic_SOURCES = msgpack_basic.cpp +msgpack_c_SOURCES = msgpack_c.cpp +msgpack_container_SOURCES = msgpack_container.cpp +msgpack_stream_SOURCES = msgpack_stream.cpp +msgpack_tuple_SOURCES = msgpack_tuple.cpp +msgpack_vref_SOURCES = msgpack_vref.cpp +object_SOURCES = object.cpp +object_with_zone_SOURCES = object_with_zone.cpp +pack_unpack_SOURCES = pack_unpack.cpp +pack_unpack_c_SOURCES = pack_unpack_c.cpp +raw_SOURCES = raw.cpp +reference_SOURCES = reference.cpp +streaming_SOURCES = streaming.cpp +streaming_c_SOURCES = streaming_c.cpp +user_class_SOURCES = user_class.cpp +version_SOURCES = version.cpp zone_SOURCES = zone.cpp -pack_unpack_SOURCES = pack_unpack.cpp - -pack_unpack_c_SOURCES = pack_unpack_c.cpp - -streaming_SOURCES = streaming.cpp - -streaming_c_SOURCES = streaming_c.cpp - -object_SOURCES = object.cpp - -object_with_zone_SOURCES = object_with_zone.cpp - -convert_SOURCES = convert.cpp - -buffer_SOURCES = buffer.cpp -buffer_LDADD = -lz - -cases_SOURCES = cases.cpp - -fixint_SOURCES = fixint.cpp - -fixint_c_SOURCES = fixint_c.cpp - -version_SOURCES = version.cpp - -msgpack_tuple_SOURCES = msgpack_tuple.cpp - -msgpack_c_SOURCES = msgpack_c.cpp - -msgpack_basic_SOURCES = msgpack_basic.cpp - -msgpack_container_SOURCES = msgpack_container.cpp - -msgpack_stream_SOURCES = msgpack_stream.cpp - -msgpack_vref_SOURCES = msgpack_vref.cpp - -msgpack_cpp11_SOURCES = msgpack_cpp11.cpp - -reference_SOURCES = reference.cpp - -reference_cpp11_SOURCES = reference_cpp11.cpp - -limit_SOURCES = limit.cpp - -json_SOURCES = json.cpp - -raw_SOURCES = raw.cpp - -user_class_SOURCES = user_class.cpp - iterator_cpp11_SOURCES = iterator_cpp11.cpp +msgpack_cpp11_SOURCES = msgpack_cpp11.cpp +reference_cpp11_SOURCES = reference_cpp11.cpp +shared_ptr_cpp11_SOURCES = shared_ptr_cpp11.cpp +unique_ptr_cpp11_SOURCES = unique_ptr_cpp11.cpp + +boost_fusion_SOURCES = boost_fusion.cpp +boost_optional_SOURCES = boost_optional.cpp +boost_string_ref_SOURCES = boost_string_ref.cpp multi_file_SOURCES = multi_file1.cpp multi_file2.cpp -boost_fusion_SOURCES = boost_fusion.cpp - -boost_optional_SOURCES = boost_optional.cpp - -boost_string_ref_SOURCES = boost_string_ref.cpp +buffer_LDADD = -lz EXTRA_DIST = cases.mpac cases_compact.mpac diff --git a/test/shared_ptr_cpp11.cpp b/test/shared_ptr_cpp11.cpp new file mode 100644 index 00000000..31fc6d80 --- /dev/null +++ b/test/shared_ptr_cpp11.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if !defined(MSGPACK_USE_CPP03) + +TEST(SHARED_PTR, pack_convert_nil) +{ + std::stringstream ss; + std::shared_ptr val1; + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::shared_ptr val2 = ret.get().as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(SHARED_PTR, pack_convert_int) +{ + std::stringstream ss; + std::shared_ptr val1(new int(1)); + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::shared_ptr val2 = ret.get().as>(); + EXPECT_TRUE(*val1 == *val2); +} + +TEST(SHARED_PTR, object_nil) +{ + std::shared_ptr val1; + msgpack::object obj(val1); + std::shared_ptr val2 = obj.as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(SHARED_PTR, object_int) +{ + std::shared_ptr val1(new int(1)); + msgpack::object obj(val1); + std::shared_ptr val2 = obj.as>(); + EXPECT_TRUE(*val1 == *val2); +} + +// Compile error as expected +// object::with_zone is required not object +/* +TEST(SHARED_PTR, object_vector) +{ + typedef std::shared_ptr> ovi_t; + ovi_t val1(new std::vector()); + msgpack::object obj(val1); + ovi_t val2 = obj.as(); + EXPECT_TRUE(val1 == val2); +} +*/ + +TEST(SHARED_PTR, object_with_zone_nil) +{ + msgpack::zone z; + std::shared_ptr val1; + msgpack::object obj(val1, z); + std::shared_ptr val2 = obj.as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(SHARED_PTR, object_with_zone_int) +{ + msgpack::zone z; + std::shared_ptr val1(new int(1)); + msgpack::object obj(val1, z); + std::shared_ptr val2 = obj.as>(); + EXPECT_TRUE(*val1 == *val2); +} + +struct no_def_con { + no_def_con() = delete; + no_def_con(int i):i(i) {} + int i; + MSGPACK_DEFINE(i); +}; + +inline bool operator==(no_def_con const& lhs, no_def_con const& rhs) { + return lhs.i == rhs.i; +} + +inline bool operator!=(no_def_con const& lhs, no_def_con const& rhs) { + return !(lhs == rhs); +} + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { +namespace adaptor { +template <> +struct as { + no_def_con operator()(msgpack::object const& o) const { + if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); + if (o.via.array.size != 1) throw msgpack::type_error(); + return no_def_con(o.via.array.ptr[0].as()); + } +}; +} // adaptor +} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) +} // msgpack + +TEST(SHARED_PTR, pack_convert_nil_no_def_con) +{ + std::stringstream ss; + std::shared_ptr val1(new no_def_con(1)); + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::shared_ptr val2 = ret.get().as>(); + EXPECT_TRUE(*val1 == *val2); +} + + +#endif // !defined(MSGPACK_USE_CPP03) diff --git a/test/unique_ptr_cpp11.cpp b/test/unique_ptr_cpp11.cpp new file mode 100644 index 00000000..2dec446c --- /dev/null +++ b/test/unique_ptr_cpp11.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if !defined(MSGPACK_USE_CPP03) + +TEST(UNIQUE_PTR, pack_convert_nil) +{ + std::stringstream ss; + std::unique_ptr val1; + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::unique_ptr val2 = ret.get().as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(UNIQUE_PTR, pack_convert_int) +{ + std::stringstream ss; + std::unique_ptr val1(new int(1)); + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::unique_ptr val2 = ret.get().as>(); + EXPECT_TRUE(*val1 == *val2); +} + +TEST(UNIQUE_PTR, object_nil) +{ + std::unique_ptr val1; + msgpack::object obj(val1); + std::unique_ptr val2 = obj.as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(UNIQUE_PTR, object_int) +{ + std::unique_ptr val1(new int(1)); + msgpack::object obj(val1); + std::unique_ptr val2 = obj.as>(); + EXPECT_TRUE(*val1 == *val2); +} + +// Compile error as expected +// object::with_zone is required not object +/* +TEST(UNIQUE_PTR, object_vector) +{ + typedef std::unique_ptr> ovi_t; + ovi_t val1(new std::vector()); + msgpack::object obj(val1); + ovi_t val2 = obj.as(); + EXPECT_TRUE(val1 == val2); +} +*/ + +TEST(UNIQUE_PTR, object_with_zone_nil) +{ + msgpack::zone z; + std::unique_ptr val1; + msgpack::object obj(val1, z); + std::unique_ptr val2 = obj.as>(); + EXPECT_TRUE(val1 == val2); +} + +TEST(UNIQUE_PTR, object_with_zone_int) +{ + msgpack::zone z; + std::unique_ptr val1(new int(1)); + msgpack::object obj(val1, z); + std::unique_ptr val2 = obj.as>(); + EXPECT_TRUE(*val1 == *val2); +} + +struct no_def_con { + no_def_con() = delete; + no_def_con(int i):i(i) {} + int i; + MSGPACK_DEFINE(i); +}; + +inline bool operator==(no_def_con const& lhs, no_def_con const& rhs) { + return lhs.i == rhs.i; +} + +inline bool operator!=(no_def_con const& lhs, no_def_con const& rhs) { + return !(lhs == rhs); +} + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { +namespace adaptor { +template <> +struct as { + no_def_con operator()(msgpack::object const& o) const { + if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); + if (o.via.array.size != 1) throw msgpack::type_error(); + return no_def_con(o.via.array.ptr[0].as()); + } +}; +} // adaptor +} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) +} // msgpack + +TEST(UNIQUE_PTR, pack_convert_nil_no_def_con) +{ + std::stringstream ss; + std::unique_ptr val1(new no_def_con(1)); + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + std::unique_ptr val2 = ret.get().as>(); + EXPECT_TRUE(*val1 == *val2); +} + + +#endif // !defined(MSGPACK_USE_CPP03)