Added 'as' support for containers.

This commit is contained in:
Takatoshi Kondo 2015-07-28 17:16:08 +09:00
parent 87f0da1ff1
commit a746afa7cc
18 changed files with 680 additions and 85 deletions

View File

@ -146,6 +146,7 @@ IF (MSGPACK_ENABLE_CXX)
include/msgpack/detail/cpp03_zone.hpp include/msgpack/detail/cpp03_zone.hpp
include/msgpack/detail/cpp11_zone.hpp include/msgpack/detail/cpp11_zone.hpp
include/msgpack/fbuffer.hpp include/msgpack/fbuffer.hpp
include/msgpack/meta.hpp
include/msgpack/object.hpp include/msgpack/object.hpp
include/msgpack/object_fwd.hpp include/msgpack/object_fwd.hpp
include/msgpack/pack.hpp include/msgpack/pack.hpp
@ -201,8 +202,8 @@ IF (MSGPACK_BUILD_TESTS)
ENDIF () ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
SET_PROPERTY (TARGET msgpack APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3 -DPIC") SET_PROPERTY (TARGET msgpack APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Wno-mismatched-tags -Werror -g -O3 -DPIC")
SET_PROPERTY (TARGET msgpack-static APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3" ) SET_PROPERTY (TARGET msgpack-static APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Wno-mismatched-tags -Werror -g -O3" )
ENDIF () ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

View File

@ -6,7 +6,7 @@ AC_SUBST(CFLAGS)
CFLAGS="-O3 -Wall -Wextra -Werror $CFLAGS" CFLAGS="-O3 -Wall -Wextra -Werror $CFLAGS"
AC_SUBST(CXXFLAGS) AC_SUBST(CXXFLAGS)
CXXFLAGS="-O3 -Wall -Wextra -Werror $CXXFLAGS" CXXFLAGS="-O3 -Wall -Wextra -Wno-mismatched-tags -Werror $CXXFLAGS"
AC_PROG_CC AC_PROG_CC

View File

@ -33,6 +33,56 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
namespace detail {
template<std::size_t... Is> struct seq {};
template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...> {};
template<typename T, std::size_t N1, std::size_t... I1, std::size_t N2, std::size_t... I2>
inline std::array<T, N1+N2> concat(
std::array<T, N1>&& a1,
std::array<T, N2>&& a2,
seq<I1...>,
seq<I2...>) {
return {{ std::move(a1[I1])..., std::move(a2[I2])... }};
}
template<typename T, std::size_t N1, std::size_t N2>
inline std::array<T, N1+N2> concat(std::array<T, N1>&& a1, std::array<T, N2>&& a2) {
return concat(std::move(a1), std::move(a2), gen_seq<N1>(), gen_seq<N2>());
}
template <typename T, std::size_t N>
struct as_impl {
static std::array<T, N> as(msgpack::object const& o) {
msgpack::object* p = o.via.array.ptr + N - 1;
return concat(as_impl<T, N-1>::as(o), std::array<T, 1>{{p->as<T>()}});
}
};
template <typename T>
struct as_impl<T, 0> {
static std::array<T, 0> as(msgpack::object const&) {
return std::array<T, 0>();
}
};
} // namespace detail
template <typename T, std::size_t N>
struct as<std::array<T, N>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::array<T, N> operator()(msgpack::object const& o) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if(o.via.array.size != N) { throw msgpack::type_error(); }
return detail::as_impl<T, N>::as(o);
}
};
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct convert<std::array<T, N>> { struct convert<std::array<T, N>> {
msgpack::object const& operator()(msgpack::object const& o, std::array<T, N>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::array<T, N>& v) const {

View File

@ -33,6 +33,21 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
template <typename T>
struct as<std::forward_list<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::forward_list<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
std::forward_list<T> v;
msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pend = o.via.array.ptr;
while (p != pend) {
--p;
v.push_front(p->as<T>());
}
return v;
}
};
template <typename T> template <typename T>
struct convert<std::forward_list<T>> { struct convert<std::forward_list<T>> {
msgpack::object const& operator()(msgpack::object const& o, std::forward_list<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::forward_list<T>& v) const {

View File

@ -21,6 +21,7 @@
#include "msgpack/versioning.hpp" #include "msgpack/versioning.hpp"
#include "msgpack/adaptor/adaptor_base.hpp" #include "msgpack/adaptor/adaptor_base.hpp"
#include "msgpack/adaptor/check_container_size.hpp" #include "msgpack/adaptor/check_container_size.hpp"
#include "msgpack/meta.hpp"
#include <tuple> #include <tuple>
@ -41,15 +42,6 @@ struct StdTuplePacker {
} }
}; };
template <typename Stream, typename Tuple>
struct StdTuplePacker<Stream, Tuple, 1> {
static void pack (
msgpack::packer<Stream>& o,
const Tuple& v) {
o.pack(std::get<0>(v));
}
};
template <typename Stream, typename Tuple> template <typename Stream, typename Tuple>
struct StdTuplePacker<Stream, Tuple, 0> { struct StdTuplePacker<Stream, Tuple, 0> {
static void pack ( static void pack (
@ -77,6 +69,32 @@ struct pack<std::tuple<Args...>> {
// --- Convert from tuple to object --- // --- Convert from tuple to object ---
template <typename... Args>
struct StdTupleAs;
template <typename T, typename... Args>
struct StdTupleAsImpl {
static std::tuple<T, Args...> as(msgpack::object const& o) {
return std::tuple_cat(
std::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
StdTupleAs<Args...>::as(o));
}
};
template <typename... Args>
struct StdTupleAs {
static std::tuple<Args...> as(msgpack::object const& o) {
return StdTupleAsImpl<Args...>::as(o);
}
};
template <>
struct StdTupleAs<> {
static std::tuple<> as (msgpack::object const&) {
return std::tuple<>();
}
};
template <typename Tuple, std::size_t N> template <typename Tuple, std::size_t N>
struct StdTupleConverter { struct StdTupleConverter {
static void convert( static void convert(
@ -87,15 +105,6 @@ struct StdTupleConverter {
} }
}; };
template <typename Tuple>
struct StdTupleConverter<Tuple, 1> {
static void convert (
msgpack::object const& o,
Tuple& v) {
o.via.array.ptr[0].convert<typename std::remove_reference<decltype(std::get<0>(v))>::type>(std::get<0>(v));
}
};
template <typename Tuple> template <typename Tuple>
struct StdTupleConverter<Tuple, 0> { struct StdTupleConverter<Tuple, 0> {
static void convert ( static void convert (
@ -106,6 +115,16 @@ struct StdTupleConverter<Tuple, 0> {
namespace adaptor { namespace adaptor {
template <typename... Args>
struct as<std::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type> {
std::tuple<Args...> operator()(
msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
return StdTupleAs<Args...>::as(o);
}
};
template <typename... Args> template <typename... Args>
struct convert<std::tuple<Args...>> { struct convert<std::tuple<Args...>> {
msgpack::object const& operator()( msgpack::object const& operator()(
@ -131,15 +150,6 @@ struct StdTupleToObjectWithZone {
} }
}; };
template <typename Tuple>
struct StdTupleToObjectWithZone<Tuple, 1> {
static void convert (
msgpack::object::with_zone& o,
const Tuple& v) {
o.via.array.ptr[0] = msgpack::object(std::get<0>(v), o.zone);
}
};
template <typename Tuple> template <typename Tuple>
struct StdTupleToObjectWithZone<Tuple, 0> { struct StdTupleToObjectWithZone<Tuple, 0> {
static void convert ( static void convert (

View File

@ -32,6 +32,22 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
template <typename K, typename V>
struct as<
std::unordered_map<K, V>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::unordered_map<K, V> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_map<K, V> v;
for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>());
}
return v;
}
};
template <typename K, typename V> template <typename K, typename V>
struct convert<std::unordered_map<K, V>> { struct convert<std::unordered_map<K, V>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_map<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_map<K, V>& v) const {
@ -89,6 +105,22 @@ struct object_with_zone<std::unordered_map<K, V>> {
}; };
template <typename K, typename V>
struct as<
std::unordered_multimap<K, V>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::unordered_multimap<K, V> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_multimap<K, V> v;
for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>());
}
return v;
}
};
template <typename K, typename V> template <typename K, typename V>
struct convert<std::unordered_multimap<K, V>> { struct convert<std::unordered_multimap<K, V>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multimap<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_multimap<K, V>& v) const {

View File

@ -32,6 +32,21 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
template <typename T>
struct as<std::unordered_set<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::unordered_set<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_set<T> v;
while (p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
};
template <typename T> template <typename T>
struct convert<std::unordered_set<T>> { struct convert<std::unordered_set<T>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_set<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_set<T>& v) const {
@ -86,6 +101,21 @@ struct object_with_zone<std::unordered_set<T>> {
}; };
template <typename T>
struct as<std::unordered_multiset<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::unordered_multiset<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_multiset<T> v;
while (p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
};
template <typename T> template <typename T>
struct convert<std::unordered_multiset<T>> { struct convert<std::unordered_multiset<T>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multiset<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_multiset<T>& v) const {

View File

@ -1,7 +1,7 @@
// //
// MessagePack for C++ static resolution routine // MessagePack for C++ static resolution routine
// //
// Copyright (C) 2008-2014 FURUHASHI Sadayuki and KONDO Takatoshi // Copyright (C) 2008-2015 FURUHASHI Sadayuki and KONDO Takatoshi
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -20,6 +20,7 @@
#include "msgpack/versioning.hpp" #include "msgpack/versioning.hpp"
#include "msgpack/object_fwd.hpp" #include "msgpack/object_fwd.hpp"
#include "msgpack/meta.hpp"
#include <tuple> #include <tuple>
@ -36,9 +37,7 @@ namespace type {
using std::tuple_element; using std::tuple_element;
using std::uses_allocator; using std::uses_allocator;
using std::ignore; using std::ignore;
using std::make_tuple;
using std::tie; using std::tie;
using std::forward_as_tuple;
using std::swap; using std::swap;
template< class... Types > template< class... Types >
@ -84,8 +83,18 @@ namespace type {
get() && { return std::get<I>(*this); } get() && { return std::get<I>(*this); }
}; };
template< class... Tuples > template <class... Args>
auto tuple_cat(Tuples&&... args) -> inline tuple<Args...> make_tuple(Args&&... args) {
return tuple<Args...>(args...);
}
template<class... Args>
inline tuple<Args&&...> forward_as_tuple (Args&&... args) noexcept {
return tuple<Args&&...>(std::forward<Args>(args)...);
}
template <class... Tuples>
inline auto tuple_cat(Tuples&&... args) ->
decltype( decltype(
std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...) std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...)
) { ) {
@ -124,11 +133,11 @@ struct MsgpackTuplePacker<Stream, Tuple, 0> {
namespace adaptor { namespace adaptor {
template <typename... Args> template <typename... Args>
struct pack<type::tuple<Args...>> { struct pack<msgpack::type::tuple<Args...>> {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()( msgpack::packer<Stream>& operator()(
msgpack::packer<Stream>& o, msgpack::packer<Stream>& o,
const type::tuple<Args...>& v) const { const msgpack::type::tuple<Args...>& v) const {
o.pack_array(sizeof...(Args)); o.pack_array(sizeof...(Args));
MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v); MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
return o; return o;
@ -139,6 +148,32 @@ struct pack<type::tuple<Args...>> {
// --- Convert from tuple to object --- // --- Convert from tuple to object ---
template <typename... Args>
struct MsgpackTupleAs;
template <typename T, typename... Args>
struct MsgpackTupleAsImpl {
static msgpack::type::tuple<T, Args...> as(msgpack::object const& o) {
return msgpack::type::tuple_cat(
msgpack::type::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
MsgpackTupleAs<Args...>::as(o));
}
};
template <typename... Args>
struct MsgpackTupleAs {
static msgpack::type::tuple<Args...> as(msgpack::object const& o) {
return MsgpackTupleAsImpl<Args...>::as(o);
}
};
template <>
struct MsgpackTupleAs<> {
static msgpack::type::tuple<> as (msgpack::object const&) {
return msgpack::type::tuple<>();
}
};
template <typename Tuple, std::size_t N> template <typename Tuple, std::size_t N>
struct MsgpackTupleConverter { struct MsgpackTupleConverter {
static void convert( static void convert(
@ -169,10 +204,20 @@ struct MsgpackTupleConverter<Tuple, 0> {
namespace adaptor { namespace adaptor {
template <typename... Args> template <typename... Args>
struct convert<type::tuple<Args...>> { struct as<msgpack::type::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type> {
msgpack::type::tuple<Args...> operator()(
msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
return MsgpackTupleAs<Args...>::as(o);
}
};
template <typename... Args>
struct convert<msgpack::type::tuple<Args...>> {
msgpack::object const& operator()( msgpack::object const& operator()(
msgpack::object const& o, msgpack::object const& o,
type::tuple<Args...>& v) const { msgpack::type::tuple<Args...>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v); MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v);
@ -213,10 +258,10 @@ struct MsgpackTupleToObjectWithZone<Tuple, 0> {
namespace adaptor { namespace adaptor {
template <typename... Args> template <typename... Args>
struct object_with_zone<type::tuple<Args...>> { struct object_with_zone<msgpack::type::tuple<Args...>> {
void operator()( void operator()(
msgpack::object::with_zone& o, msgpack::object::with_zone& o,
type::tuple<Args...> const& v) const { msgpack::type::tuple<Args...> const& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*sizeof...(Args))); o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*sizeof...(Args)));
o.via.array.size = sizeof...(Args); o.via.array.size = sizeof...(Args);

View File

@ -32,15 +32,33 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
#if !defined(MSGPACK_USE_CPP03)
template <typename T>
struct as<std::list<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::list<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
std::list<T> v;
msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
for (; p < pend; ++p) {
v.push_back(p->as<T>());
}
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct convert<std::list<T> > { struct convert<std::list<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::list<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::list<T>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
v.resize(o.via.array.size); v.resize(o.via.array.size);
msgpack::object* p = o.via.array.ptr; msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size; msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
typename std::list<T>::iterator it = v.begin(); typename std::list<T>::iterator it = v.begin();
for(; p < pend; ++p, ++it) { for (; p < pend; ++p, ++it) {
p->convert(*it); p->convert(*it);
} }
return o; return o;
@ -53,7 +71,7 @@ struct pack<std::list<T> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::list<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::list<T>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::list<T>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::list<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -65,10 +83,11 @@ template <typename T>
struct object_with_zone<std::list<T> > { struct object_with_zone<std::list<T> > {
void operator()(msgpack::object::with_zone& o, const std::list<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::list<T>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if (v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
o.via.array.size = 0; o.via.array.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size)); msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size));
msgpack::object* const pend = p + size; msgpack::object* const pend = p + size;

View File

@ -35,7 +35,11 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace type { namespace type {
template <typename K, typename V> template <typename K, typename V>
class assoc_vector : public std::vector< std::pair<K, V> > {}; class assoc_vector : public std::vector< std::pair<K, V> > {
#if !defined(MSGPACK_USE_CPP03)
using std::vector<std::pair<K, V>>::vector;
#endif // !defined(MSGPACK_USE_CPP03)
};
namespace detail { namespace detail {
template <typename K, typename V> template <typename K, typename V>
@ -49,15 +53,37 @@ namespace detail {
namespace adaptor { namespace adaptor {
#if !defined(MSGPACK_USE_CPP03)
template <typename K, typename V>
struct as<
type::assoc_vector<K, V>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
type::assoc_vector<K, V> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
type::assoc_vector<K, V> v;
v.reserve(o.via.map.size);
msgpack::object_kv* p = o.via.map.ptr;
msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size;
for (; p < pend; ++p) {
v.emplace_back(p->key.as<K>(), p->val.as<V>());
}
std::sort(v.begin(), v.end(), type::detail::pair_first_less<K,V>());
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename K, typename V> template <typename K, typename V>
struct convert<type::assoc_vector<K, V> > { struct convert<type::assoc_vector<K, V> > {
msgpack::object const& operator()(msgpack::object const& o, type::assoc_vector<K,V>& v) const { msgpack::object const& operator()(msgpack::object const& o, type::assoc_vector<K,V>& v) const {
if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
v.resize(o.via.map.size); v.resize(o.via.map.size);
msgpack::object_kv* p = o.via.map.ptr; msgpack::object_kv* p = o.via.map.ptr;
msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size; msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size;
std::pair<K, V>* it(&v.front()); std::pair<K, V>* it(&v.front());
for(; p < pend; ++p, ++it) { for (; p < pend; ++p, ++it) {
p->key.convert(it->first); p->key.convert(it->first);
p->val.convert(it->second); p->val.convert(it->second);
} }
@ -72,7 +98,7 @@ struct pack<type::assoc_vector<K, V> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const type::assoc_vector<K,V>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const type::assoc_vector<K,V>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_map(size); o.pack_map(size);
for(typename type::assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end()); for (typename type::assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(it->first); o.pack(it->first);
o.pack(it->second); o.pack(it->second);
@ -85,10 +111,11 @@ template <typename K, typename V>
struct object_with_zone<type::assoc_vector<K, V> > { struct object_with_zone<type::assoc_vector<K, V> > {
void operator()(msgpack::object::with_zone& o, const type::assoc_vector<K,V>& v) const { void operator()(msgpack::object::with_zone& o, const type::assoc_vector<K,V>& v) const {
o.type = msgpack::type::MAP; o.type = msgpack::type::MAP;
if(v.empty()) { if (v.empty()) {
o.via.map.ptr = nullptr; o.via.map.ptr = nullptr;
o.via.map.size = 0; o.via.map.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size));
msgpack::object_kv* const pend = p + size; msgpack::object_kv* const pend = p + size;
@ -105,14 +132,34 @@ struct object_with_zone<type::assoc_vector<K, V> > {
} }
}; };
#if !defined(MSGPACK_USE_CPP03)
template <typename K, typename V>
struct as<
std::map<K, V>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::map<K, V> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::map<K, V> v;
for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>());
}
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename K, typename V> template <typename K, typename V>
struct convert<std::map<K, V> > { struct convert<std::map<K, V> > {
msgpack::object const& operator()(msgpack::object const& o, std::map<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::map<K, V>& v) const {
if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::map<K, V> tmp; std::map<K, V> tmp;
for(; p != pend; ++p) { for (; p != pend; ++p) {
K key; K key;
p->key.convert(key); p->key.convert(key);
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@ -136,7 +183,7 @@ struct pack<std::map<K, V> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::map<K,V>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::map<K,V>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_map(size); o.pack_map(size);
for(typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(it->first); o.pack(it->first);
o.pack(it->second); o.pack(it->second);
@ -149,10 +196,11 @@ template <typename K, typename V>
struct object_with_zone<std::map<K, V> > { struct object_with_zone<std::map<K, V> > {
void operator()(msgpack::object::with_zone& o, const std::map<K,V>& v) const { void operator()(msgpack::object::with_zone& o, const std::map<K,V>& v) const {
o.type = msgpack::type::MAP; o.type = msgpack::type::MAP;
if(v.empty()) { if (v.empty()) {
o.via.map.ptr = nullptr; o.via.map.ptr = nullptr;
o.via.map.size = 0; o.via.map.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size));
msgpack::object_kv* const pend = p + size; msgpack::object_kv* const pend = p + size;
@ -169,15 +217,34 @@ struct object_with_zone<std::map<K, V> > {
} }
}; };
#if !defined(MSGPACK_USE_CPP03)
template <typename K, typename V>
struct as<
std::multimap<K, V>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::multimap<K, V> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::multimap<K, V> v;
for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>());
}
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename K, typename V> template <typename K, typename V>
struct convert<std::multimap<K, V> > { struct convert<std::multimap<K, V> > {
msgpack::object const& operator()(msgpack::object const& o, std::multimap<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::multimap<K, V>& v) const {
if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::multimap<K, V> tmp; std::multimap<K, V> tmp;
for(; p != pend; ++p) { for (; p != pend; ++p) {
std::pair<K, V> value; std::pair<K, V> value;
p->key.convert(value.first); p->key.convert(value.first);
p->val.convert(value.second); p->val.convert(value.second);
@ -202,7 +269,7 @@ struct pack<std::multimap<K, V> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::multimap<K,V>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::multimap<K,V>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_map(size); o.pack_map(size);
for(typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(it->first); o.pack(it->first);
o.pack(it->second); o.pack(it->second);
@ -215,10 +282,11 @@ template <typename K, typename V>
struct object_with_zone<std::multimap<K, V> > { struct object_with_zone<std::multimap<K, V> > {
void operator()(msgpack::object::with_zone& o, const std::multimap<K,V>& v) const { void operator()(msgpack::object::with_zone& o, const std::multimap<K,V>& v) const {
o.type = msgpack::type::MAP; o.type = msgpack::type::MAP;
if(v.empty()) { if (v.empty()) {
o.via.map.ptr = nullptr; o.via.map.ptr = nullptr;
o.via.map.size = 0; o.via.map.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size));
msgpack::object_kv* const pend = p + size; msgpack::object_kv* const pend = p + size;

View File

@ -30,6 +30,19 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
#if !defined(MSGPACK_USE_CPP03)
template <typename T1, typename T2>
struct as<std::pair<T1, T2>> {
std::pair<T1, T2> 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::make_pair(o.via.array.ptr[0].as<T1>(), o.via.array.ptr[1].as<T2>());
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T1, typename T2> template <typename T1, typename T2>
struct convert<std::pair<T1, T2> > { struct convert<std::pair<T1, T2> > {
msgpack::object const& operator()(msgpack::object const& o, std::pair<T1, T2>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::pair<T1, T2>& v) const {

View File

@ -32,14 +32,33 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
#if !defined(MSGPACK_USE_CPP03)
template <typename T>
struct as<std::set<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::set<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr;
std::set<T> v;
while (p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct convert<std::set<T> > { struct convert<std::set<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::set<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::set<T>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::set<T> tmp; std::set<T> tmp;
while(p > pbegin) { while (p > pbegin) {
--p; --p;
tmp.insert(p->as<T>()); tmp.insert(p->as<T>());
} }
@ -58,7 +77,7 @@ struct pack<std::set<T> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::set<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::set<T>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::set<T>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::set<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -70,10 +89,11 @@ template <typename T>
struct object_with_zone<std::set<T> > { struct object_with_zone<std::set<T> > {
void operator()(msgpack::object::with_zone& o, const std::set<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::set<T>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if (v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
o.via.array.size = 0; o.via.array.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size)); msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size));
msgpack::object* const pend = p + size; msgpack::object* const pend = p + size;
@ -89,14 +109,33 @@ struct object_with_zone<std::set<T> > {
} }
}; };
#if !defined(MSGPACK_USE_CPP03)
template <typename T>
struct as<std::multiset<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::multiset<T> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr;
std::multiset<T> v;
while (p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct convert<std::multiset<T> > { struct convert<std::multiset<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::multiset<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::multiset<T>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::multiset<T> tmp; std::multiset<T> tmp;
while(p > pbegin) { while (p > pbegin) {
--p; --p;
tmp.insert(p->as<T>()); tmp.insert(p->as<T>());
} }
@ -115,7 +154,7 @@ struct pack<std::multiset<T> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::multiset<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::multiset<T>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::multiset<T>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::multiset<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -127,7 +166,7 @@ template <typename T>
struct object_with_zone<std::multiset<T> > { struct object_with_zone<std::multiset<T> > {
void operator()(msgpack::object::with_zone& o, const std::multiset<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::multiset<T>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if (v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
o.via.array.size = 0; o.via.array.size = 0;
} else { } else {

View File

@ -1,7 +1,7 @@
// //
// MessagePack for C++ static resolution routine // MessagePack for C++ static resolution routine
// //
// Copyright (C) 2008-2009 FURUHASHI Sadayuki // Copyright (C) 2008-2015 FURUHASHI Sadayuki and KONDO Takatoshi
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -33,30 +33,33 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
#if !defined(MSGPACK_USE_CPP03) #if !defined(MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct as<std::vector<T>> { struct as<std::vector<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
std::vector<T> operator()(const msgpack::object& o) const { std::vector<T> operator()(const msgpack::object& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
std::vector<T> v; std::vector<T> v;
v.reserve(o.via.array.size);
if (o.via.array.size > 0) { if (o.via.array.size > 0) {
msgpack::object* p = o.via.array.ptr; msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size; msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
do { do {
v.emplace_back(p->as<T>()); v.push_back(p->as<T>());
++p; ++p;
} while (p < pend); } while (p < pend);
} }
return v; return v;
} }
}; };
#endif
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct convert<std::vector<T> > { struct convert<std::vector<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::vector<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::vector<T>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
v.resize(o.via.array.size); v.resize(o.via.array.size);
if(o.via.array.size > 0) { if (o.via.array.size > 0) {
msgpack::object* p = o.via.array.ptr; msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size; msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
typename std::vector<T>::iterator it = v.begin(); typename std::vector<T>::iterator it = v.begin();
@ -76,7 +79,7 @@ struct pack<std::vector<T> > {
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::vector<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::vector<T>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end()); for (typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -88,10 +91,11 @@ template <typename T>
struct object_with_zone<std::vector<T> > { struct object_with_zone<std::vector<T> > {
void operator()(msgpack::object::with_zone& o, const std::vector<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::vector<T>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if (v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
o.via.array.size = 0; o.via.array.size = 0;
} else { }
else {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size)); msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size));
msgpack::object* const pend = p + size; msgpack::object* const pend = p + size;

51
include/msgpack/meta.hpp Normal file
View File

@ -0,0 +1,51 @@
//
// 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_META_HPP
#define MSGPACK_META_HPP
#if !defined(MSGPACK_USE_CPP03)
#include <type_traits>
namespace msgpack {
/// @cond
MSGPACK_API_VERSION_NAMESPACE(v1) {
/// @endcond
namespace detail {
template<bool...> struct bool_pack;
template<bool...values> struct all_of_imp
: std::is_same<bool_pack<values..., true>, bool_pack<true, values...>>{};
} // namespace detail
template<template <class> class T, class... U>
using all_of = detail::all_of_imp<T<U>::value...>;
/// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond
} // namespace msgpack
#endif // !defined(MSGPACK_USE_CPP03)
#endif // MSGPACK_META_HPP

View File

@ -86,7 +86,7 @@ struct object_ext {
struct object; struct object;
namespace adaptor { namespace adaptor {
template <typename T> template <typename T, typename Enabler = void>
struct as; struct as;
} // namespace adaptor } // namespace adaptor

View File

@ -98,6 +98,7 @@ nobase_include_HEADERS += \
../include/msgpack/detail/cpp11_zone.hpp \ ../include/msgpack/detail/cpp11_zone.hpp \
../include/msgpack/fbuffer.hpp \ ../include/msgpack/fbuffer.hpp \
../include/msgpack/iterator.hpp \ ../include/msgpack/iterator.hpp \
../include/msgpack/meta.hpp \
../include/msgpack/object.hpp \ ../include/msgpack/object.hpp \
../include/msgpack/object_fwd.hpp \ ../include/msgpack/object_fwd.hpp \
../include/msgpack/pack.hpp \ ../include/msgpack/pack.hpp \

View File

@ -64,7 +64,7 @@ FOREACH (source_file ${check_PROGRAMS})
) )
ADD_TEST (${source_file_we} ${source_file_we}) ADD_TEST (${source_file_we} ${source_file_we})
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3") SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -Wno-mismatched-tags -g -O3")
ENDIF () ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

View File

@ -192,6 +192,18 @@ struct no_def_con {
MSGPACK_DEFINE(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);
}
inline bool operator<(no_def_con const& lhs, no_def_con const& rhs) {
return lhs.i < rhs.i;
}
namespace msgpack { namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor { namespace adaptor {
@ -207,6 +219,14 @@ struct as<no_def_con> {
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) } // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // msgpack } // msgpack
namespace std {
template <> struct hash<no_def_con> {
size_t operator()(const no_def_con & x) const {
return hash<int>()(x.i);
}
};
} // std
TEST(MSGPACK_NO_DEF_CON, simple_buffer) TEST(MSGPACK_NO_DEF_CON, simple_buffer)
{ {
no_def_con val1(42); no_def_con val1(42);
@ -216,16 +236,29 @@ TEST(MSGPACK_NO_DEF_CON, simple_buffer)
msgpack::unpack(ret, sbuf.data(), sbuf.size()); msgpack::unpack(ret, sbuf.data(), sbuf.size());
no_def_con val2 = ret.get().as<no_def_con>(); no_def_con val2 = ret.get().as<no_def_con>();
EXPECT_EQ(val1.i, val2.i); EXPECT_EQ(val1, val2);
} }
struct no_def_con_composite { struct no_def_con_composite {
no_def_con_composite() = delete; no_def_con_composite() = delete;
no_def_con_composite(int i):ndc(i) {}
no_def_con_composite(no_def_con const& a):ndc(a) {} no_def_con_composite(no_def_con const& a):ndc(a) {}
no_def_con ndc; no_def_con ndc;
MSGPACK_DEFINE(ndc); MSGPACK_DEFINE(ndc);
}; };
inline bool operator==(no_def_con_composite const& lhs, no_def_con_composite const& rhs) {
return lhs.ndc == rhs.ndc;
}
inline bool operator!=(no_def_con_composite const& lhs, no_def_con_composite const& rhs) {
return !(lhs == rhs);
}
inline bool operator<(no_def_con_composite const& lhs, no_def_con_composite const& rhs) {
return lhs.ndc < rhs.ndc;
}
namespace msgpack { namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor { namespace adaptor {
@ -249,7 +282,7 @@ TEST(MSGPACK_NO_DEF_CON_COMPOSITE, simple_buffer)
msgpack::unpacked ret; msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size()); msgpack::unpack(ret, sbuf.data(), sbuf.size());
no_def_con_composite val2 = ret.get().as<no_def_con_composite>(); no_def_con_composite val2 = ret.get().as<no_def_con_composite>();
EXPECT_EQ(val1.ndc.i, val2.ndc.i); EXPECT_EQ(val1, val2);
} }
struct no_def_con_inherit : no_def_con { struct no_def_con_inherit : no_def_con {
@ -281,7 +314,191 @@ TEST(MSGPACK_NO_DEF_CON_INHERIT, simple_buffer)
msgpack::unpacked ret; msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size()); msgpack::unpack(ret, sbuf.data(), sbuf.size());
no_def_con_inherit val2 = ret.get().as<no_def_con_inherit>(); no_def_con_inherit val2 = ret.get().as<no_def_con_inherit>();
EXPECT_EQ(val1.i, val2.i); EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_VECTOR, simple_buffer)
{
std::vector<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::vector<no_def_con> val2 = ret.get().as<std::vector<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_LIST, simple_buffer)
{
std::list<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::list<no_def_con> val2 = ret.get().as<std::list<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_SET, simple_buffer)
{
std::set<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::set<no_def_con> val2 = ret.get().as<std::set<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_MULTISET, simple_buffer)
{
std::multiset<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::multiset<no_def_con> val2 = ret.get().as<std::multiset<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_ASSOC_VECTOR, simple_buffer)
{
msgpack::type::assoc_vector<no_def_con, no_def_con_composite> val1 { {1, 2}, {3, 4}, {5, 6}};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
msgpack::type::assoc_vector<no_def_con, no_def_con_composite> val2
= ret.get().as<msgpack::type::assoc_vector<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_MAP, simple_buffer)
{
std::map<no_def_con, no_def_con_composite> val1 { {1, 2}, {3, 4}, {5, 6}};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::map<no_def_con, no_def_con_composite> val2
= ret.get().as<std::map<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_MULTIMAP, simple_buffer)
{
std::multimap<no_def_con, no_def_con_composite> val1 { {1, 2}, {3, 4}, {5, 6}};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::multimap<no_def_con, no_def_con_composite> val2
= ret.get().as<std::multimap<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_PAIR, simple_buffer)
{
std::pair<no_def_con, no_def_con_composite> val1 {1, 2};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::pair<no_def_con, no_def_con_composite> val2
= ret.get().as<std::pair<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_TUPLE, simple_buffer)
{
std::tuple<no_def_con, no_def_con, no_def_con_composite> val1 {1, 2, 3};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::tuple<no_def_con, no_def_con, no_def_con_composite> val2
= ret.get().as<std::tuple<no_def_con, no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_MSGPACK_TUPLE, simple_buffer)
{
msgpack::type::tuple<no_def_con, no_def_con, no_def_con_composite> val1 {1, 2, 3};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
msgpack::type::tuple<no_def_con, no_def_con, no_def_con_composite> val2
= ret.get().as<msgpack::type::tuple<no_def_con, no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_FORWARD_LIST, simple_buffer)
{
std::forward_list<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::forward_list<no_def_con> val2 = ret.get().as<std::forward_list<no_def_con>>();
EXPECT_TRUE(val1 == val2);
}
TEST(MSGPACK_NO_DEF_CON_UNORDERED_SET, simple_buffer)
{
std::unordered_set<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::unordered_set<no_def_con> val2 = ret.get().as<std::unordered_set<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_UNORDERED_MULTISET, simple_buffer)
{
std::unordered_multiset<no_def_con> val1 { 1, 2, 3 };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::unordered_multiset<no_def_con> val2 = ret.get().as<std::unordered_multiset<no_def_con>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_UNORDERED_MAP, simple_buffer)
{
std::unordered_map<no_def_con, no_def_con_composite> val1 { {1, 2}, {3, 4}, {5, 6}};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::unordered_map<no_def_con, no_def_con_composite> val2
= ret.get().as<std::unordered_map<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_UNORDERED_MULTIMAP, simple_buffer)
{
std::unordered_multimap<no_def_con, no_def_con_composite> val1 { {1, 2}, {3, 4}, {5, 6}};
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::unordered_multimap<no_def_con, no_def_con_composite> val2
= ret.get().as<std::unordered_multimap<no_def_con, no_def_con_composite>>();
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK_NO_DEF_CON_ARRAY, simple_buffer)
{
std::array<no_def_con, 3> val1 { { 1, 2, 3 } };
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
std::array<no_def_con, 3> val2 = ret.get().as<std::array<no_def_con, 3>>();
EXPECT_EQ(val1, val2);
} }
#endif // !defined(MSGPACK_USE_CPP03) #endif // !defined(MSGPACK_USE_CPP03)