diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c0caa51..d1418f04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,8 @@ IF (MSGPACK_ENABLE_CXX) LIST (APPEND msgpack_HEADERS include/msgpack.hpp include/msgpack/adaptor/bool.hpp + include/msgpack/adaptor/cpp11/array.hpp + include/msgpack/adaptor/cpp11/array_char.hpp include/msgpack/adaptor/cpp11/tuple.hpp include/msgpack/adaptor/define.hpp include/msgpack/adaptor/deque.hpp diff --git a/include/msgpack/adaptor/cpp11/array.hpp b/include/msgpack/adaptor/cpp11/array.hpp new file mode 100644 index 00000000..1e2f6bbb --- /dev/null +++ b/include/msgpack/adaptor/cpp11/array.hpp @@ -0,0 +1,68 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2014 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_ARRAY_HPP +#define MSGPACK_CPP11_ARRAY_HPP + +#include + +#include "msgpack/object.hpp" +#include "msgpack/cpp_config.hpp" + +namespace msgpack { + +template +inline std::array& operator>> (object const& o, std::array& v) { + if(o.type != type::ARRAY) { throw type_error(); } + if(o.via.array.size != N) { throw type_error(); } + if(o.via.array.size > 0) { + object* p = o.via.array.ptr; + object* const pend = o.via.array.ptr + o.via.array.size; + T* it = &v[0]; + do { + p->convert(*it); + ++p; + ++it; + } while(p < pend); + } + return v; +} + +template +inline packer& operator<< (packer& o, const std::array& v) { + o.pack_array(v.size()); + for(auto const& e : v) o.pack(e); + return o; +} + +template +inline void operator<< (object::with_zone& o, const std::array& v) { + o.type = type::ARRAY; + if(v.empty()) { + o.via.array.ptr = nullptr; + o.via.array.size = 0; + } else { + object* p = static_cast(o.zone->allocate_align(sizeof(object)*v.size())); + for (auto const& e : v) *p++ = object(e, o.zone); + } +} + + +} // namespace msgpack + +#endif // MSGPACK_CPP11_ARRAY_HPP diff --git a/include/msgpack/adaptor/cpp11/array_char.hpp b/include/msgpack/adaptor/cpp11/array_char.hpp new file mode 100644 index 00000000..e909f7e1 --- /dev/null +++ b/include/msgpack/adaptor/cpp11/array_char.hpp @@ -0,0 +1,74 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2014 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_TYPE_ARRAY_CHAR_HPP +#define MSGPACK_TYPE_ARRAY_CHAR_HPP + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + +template +inline std::array& operator>> (object const& o, std::array& v) +{ + switch (o.type) { + case type::BIN: + if(o.via.bin.size != N) { throw type_error(); } + std::memcpy(v.data(), o.via.bin.ptr, o.via.bin.size); + break; + case type::STR: + if(o.via.str.size != N) { throw type_error(); } + std::memcpy(v.data(), o.via.str.ptr, N); + break; + default: + throw type_error(); + break; + } + return v; +} + +template +inline packer& operator<< (packer& o, const std::array& v) +{ + o.pack_bin(v.size()); + o.pack_bin_body(v.data(), v.size()); + + return o; +} + +template +inline void operator<< (object& o, const std::array& v) +{ + o.type = type::BIN; + o.via.bin.ptr = v.data(); + o.via.bin.size = static_cast(v.size()); +} + +template +inline void operator<< (object::with_zone& o, const std::array& v) +{ + o.type = type::BIN; + char* ptr = static_cast(o.zone->allocate_align(v.size())); + o.via.bin.ptr = ptr; + o.via.bin.size = static_cast(v.size()); + std::memcpy(ptr, v.data(), v.size()); +} + +} // namespace msgpack + +#endif // MSGPACK_TYPE_ARRAY_CHAR_HPP diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 29ab7348..0a962667 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -20,7 +20,8 @@ #if !defined(MSGPACK_USE_CPP03) +#include "adaptor/cpp11/array.hpp" +#include "adaptor/cpp11/array_char.hpp" #include "adaptor/cpp11/tuple.hpp" #endif // !defined(MSGPACK_USE_CPP03) - diff --git a/src/Makefile.am b/src/Makefile.am index a729e102..2b03b944 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,8 @@ if ENABLE_CXX nobase_include_HEADERS += \ ../include/msgpack.hpp \ ../include/msgpack/adaptor/bool.hpp \ + ../include/msgpack/adaptor/cpp11/array.hpp \ + ../include/msgpack/adaptor/cpp11/array_char.hpp \ ../include/msgpack/adaptor/cpp11/tuple.hpp \ ../include/msgpack/adaptor/define.hpp \ ../include/msgpack/adaptor/deque.hpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 23536a3a..a6b71df0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,6 +23,7 @@ SET (check_PROGRAMS msgpack_tuple.cc msgpack_test.cpp msgpackc_test.cpp + msgpackc_test_cpp11.cpp reference.cc ) diff --git a/test/Makefile.am b/test/Makefile.am index dfa7d3f0..68858e76 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,6 +18,7 @@ check_PROGRAMS = \ msgpack_tuple \ msgpackc_test \ msgpack_test \ + msgpack_test_cpp11 \ reference TESTS = $(check_PROGRAMS) @@ -53,6 +54,8 @@ msgpackc_test_SOURCES = msgpackc_test.cpp msgpack_test_SOURCES = msgpack_test.cpp +msgpack_test_cpp11_SOURCES = msgpack_test_cpp11.cpp + reference_SOURCES = reference.cc EXTRA_DIST = cases.mpac cases_compact.mpac diff --git a/test/msgpack_test.cpp b/test/msgpack_test.cpp index 2340642a..f47aeeee 100644 --- a/test/msgpack_test.cpp +++ b/test/msgpack_test.cpp @@ -862,22 +862,6 @@ TEST(MSGPACK_TR1, simple_buffer_unordered_multiset) } #endif -#if !defined(MSGPACK_USE_CPP03) -// C++11 - -TEST(MSGPACK_CPP11, simple_tuple) -{ - msgpack::sbuffer sbuf; - std::tuple val1(true, "kzk", 12.3); - msgpack::pack(sbuf, val1); - msgpack::unpacked ret; - msgpack::unpack(ret, sbuf.data(), sbuf.size()); - std::tuple val2 = ret.get().as >(); - EXPECT_EQ(val1, val2); - EXPECT_FALSE(ret.referenced()); -} - -#endif // !defined(MSGPACK_USE_CPP03) // User-Defined Structures @@ -984,45 +968,6 @@ TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_member) EXPECT_FALSE(ret.referenced()); } -#if !defined(MSGPACK_USE_CPP03) - -class TestEnumClassMemberClass -{ -public: - TestEnumClassMemberClass() - : t1(TestEnumClassType::STATE_A), t2(TestEnumClassType::STATE_B), t3(TestEnumClassType::STATE_C) {} - - enum class TestEnumClassType:long { - STATE_INVALID = 0, - STATE_A = 1, - STATE_B = 2, - STATE_C = 3 - }; - TestEnumClassType t1; - TestEnumClassType t2; - TestEnumClassType t3; - - MSGPACK_DEFINE(t1, t2, t3); -}; - -MSGPACK_ADD_ENUM(TestEnumClassMemberClass::TestEnumClassType); - -TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member) -{ - TestEnumClassMemberClass val1; - msgpack::sbuffer sbuf; - msgpack::pack(sbuf, val1); - msgpack::unpacked ret; - msgpack::unpack(ret, sbuf.data(), sbuf.size()); - TestEnumClassMemberClass val2 = ret.get().as(); - EXPECT_EQ(val1.t1, val2.t1); - EXPECT_EQ(val1.t2, val2.t2); - EXPECT_EQ(val1.t3, val2.t3); - EXPECT_FALSE(ret.referenced()); -} - -#endif // !defined(MSGPACK_USE_CPP03) - class TestUnionMemberClass { public: diff --git a/test/msgpack_test_cpp11.cpp b/test/msgpack_test_cpp11.cpp new file mode 100644 index 00000000..3ebf4611 --- /dev/null +++ b/test/msgpack_test_cpp11.cpp @@ -0,0 +1,102 @@ +#include "msgpack.hpp" + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +using namespace std; + +const unsigned int kLoop = 10000; +const unsigned int kElements = 100; +const double kEPS = 1e-10; + +#if !defined(MSGPACK_USE_CPP03) + +// C++11 + +TEST(MSGPACK_CPP11, simple_tuple) +{ + msgpack::sbuffer sbuf; + std::tuple val1(true, "kzk", 12.3); + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + std::tuple val2 = ret.get().as >(); + EXPECT_EQ(val1, val2); + EXPECT_FALSE(ret.referenced()); +} + +TEST(MSGPACK_CPP11, simple_array) +{ + for (unsigned int k = 0; k < kLoop; k++) { + array val1; + for (unsigned int i = 0; i < kElements; i++) + val1[i] = rand(); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + EXPECT_EQ(ret.get().type, msgpack::type::ARRAY); + array val2 = ret.get().as >(); + EXPECT_EQ(val1.size(), val2.size()); + EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin())); + EXPECT_FALSE(ret.referenced()); + } +} + +TEST(MSGPACK_CPP11, simple_buffer_array_char) +{ + for (unsigned int k = 0; k < kLoop; k++) { + array val1; + for (unsigned int i = 0; i < kElements; i++) + val1[i] = rand(); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + EXPECT_EQ(ret.get().type, msgpack::type::BIN); + array val2 = ret.get().as >(); + EXPECT_EQ(val1.size(), val2.size()); + EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin())); + } +} + + +class TestEnumClassMemberClass +{ +public: + TestEnumClassMemberClass() + : t1(TestEnumClassType::STATE_A), t2(TestEnumClassType::STATE_B), t3(TestEnumClassType::STATE_C) {} + + enum class TestEnumClassType:long { + STATE_INVALID = 0, + STATE_A = 1, + STATE_B = 2, + STATE_C = 3 + }; + TestEnumClassType t1; + TestEnumClassType t2; + TestEnumClassType t3; + + MSGPACK_DEFINE(t1, t2, t3); +}; + +MSGPACK_ADD_ENUM(TestEnumClassMemberClass::TestEnumClassType); + +TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member) +{ + TestEnumClassMemberClass val1; + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + TestEnumClassMemberClass val2 = ret.get().as(); + EXPECT_EQ(val1.t1, val2.t1); + EXPECT_EQ(val1.t2, val2.t2); + EXPECT_EQ(val1.t3, val2.t3); + EXPECT_FALSE(ret.referenced()); +} + +#endif // !defined(MSGPACK_USE_CPP03)