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/cpp11_zone.hpp
include/msgpack/fbuffer.hpp
include/msgpack/meta.hpp
include/msgpack/object.hpp
include/msgpack/object_fwd.hpp
include/msgpack/pack.hpp
@ -201,8 +202,8 @@ IF (MSGPACK_BUILD_TESTS)
ENDIF ()
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-static APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3" )
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 -Wno-mismatched-tags -Werror -g -O3" )
ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

View File

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

View File

@ -33,6 +33,56 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
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>
struct convert<std::array<T, N>> {
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 {
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>
struct convert<std::forward_list<T>> {
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/adaptor/adaptor_base.hpp"
#include "msgpack/adaptor/check_container_size.hpp"
#include "msgpack/meta.hpp"
#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>
struct StdTuplePacker<Stream, Tuple, 0> {
static void pack (
@ -77,6 +69,32 @@ struct pack<std::tuple<Args...>> {
// --- 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>
struct StdTupleConverter {
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>
struct StdTupleConverter<Tuple, 0> {
static void convert (
@ -106,6 +115,16 @@ struct StdTupleConverter<Tuple, 0> {
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>
struct convert<std::tuple<Args...>> {
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>
struct StdTupleToObjectWithZone<Tuple, 0> {
static void convert (

View File

@ -32,6 +32,22 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
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>
struct convert<std::unordered_map<K, V>> {
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>
struct convert<std::unordered_multimap<K, V>> {
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 {
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>
struct convert<std::unordered_set<T>> {
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>
struct convert<std::unordered_multiset<T>> {
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
//
// 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");
// you may not use this file except in compliance with the License.
@ -20,6 +20,7 @@
#include "msgpack/versioning.hpp"
#include "msgpack/object_fwd.hpp"
#include "msgpack/meta.hpp"
#include <tuple>
@ -36,9 +37,7 @@ namespace type {
using std::tuple_element;
using std::uses_allocator;
using std::ignore;
using std::make_tuple;
using std::tie;
using std::forward_as_tuple;
using std::swap;
template< class... Types >
@ -84,8 +83,18 @@ namespace type {
get() && { return std::get<I>(*this); }
};
template <class... 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>
auto tuple_cat(Tuples&&... args) ->
inline auto tuple_cat(Tuples&&... args) ->
decltype(
std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...)
) {
@ -124,11 +133,11 @@ struct MsgpackTuplePacker<Stream, Tuple, 0> {
namespace adaptor {
template <typename... Args>
struct pack<type::tuple<Args...>> {
struct pack<msgpack::type::tuple<Args...>> {
template <typename Stream>
msgpack::packer<Stream>& operator()(
msgpack::packer<Stream>& o,
const type::tuple<Args...>& v) const {
const msgpack::type::tuple<Args...>& v) const {
o.pack_array(sizeof...(Args));
MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
return o;
@ -139,6 +148,32 @@ struct pack<type::tuple<Args...>> {
// --- 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>
struct MsgpackTupleConverter {
static void convert(
@ -169,10 +204,20 @@ struct MsgpackTupleConverter<Tuple, 0> {
namespace adaptor {
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& o,
type::tuple<Args...>& v) const {
msgpack::type::tuple<Args...>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v);
@ -213,10 +258,10 @@ struct MsgpackTupleToObjectWithZone<Tuple, 0> {
namespace adaptor {
template <typename... Args>
struct object_with_zone<type::tuple<Args...>> {
struct object_with_zone<msgpack::type::tuple<Args...>> {
void operator()(
msgpack::object::with_zone& o,
type::tuple<Args...> const& v) const {
msgpack::type::tuple<Args...> const& v) const {
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.size = sizeof...(Args);

View File

@ -32,6 +32,24 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
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>
struct convert<std::list<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::list<T>& v) const {
@ -68,7 +86,8 @@ struct object_with_zone<std::list<T> > {
if (v.empty()) {
o.via.array.ptr = nullptr;
o.via.array.size = 0;
} else {
}
else {
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* const pend = p + size;

View File

@ -35,7 +35,11 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace type {
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 {
template <typename K, typename V>
@ -49,6 +53,28 @@ namespace detail {
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>
struct convert<type::assoc_vector<K, V> > {
msgpack::object const& operator()(msgpack::object const& o, type::assoc_vector<K,V>& v) const {
@ -88,7 +114,8 @@ struct object_with_zone<type::assoc_vector<K, V> > {
if (v.empty()) {
o.via.map.ptr = nullptr;
o.via.map.size = 0;
} else {
}
else {
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* const pend = p + size;
@ -105,6 +132,26 @@ 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>
struct convert<std::map<K, V> > {
msgpack::object const& operator()(msgpack::object const& o, std::map<K, V>& v) const {
@ -152,7 +199,8 @@ struct object_with_zone<std::map<K, V> > {
if (v.empty()) {
o.via.map.ptr = nullptr;
o.via.map.size = 0;
} else {
}
else {
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* const pend = p + size;
@ -169,6 +217,25 @@ 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>
struct convert<std::multimap<K, V> > {
@ -218,7 +285,8 @@ struct object_with_zone<std::multimap<K, V> > {
if (v.empty()) {
o.via.map.ptr = nullptr;
o.via.map.size = 0;
} else {
}
else {
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* const pend = p + size;

View File

@ -30,6 +30,19 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
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>
struct convert<std::pair<T1, T2> > {
msgpack::object const& operator()(msgpack::object const& o, std::pair<T1, T2>& v) const {

View File

@ -32,6 +32,25 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
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>
struct convert<std::set<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::set<T>& v) const {
@ -73,7 +92,8 @@ struct object_with_zone<std::set<T> > {
if (v.empty()) {
o.via.array.ptr = nullptr;
o.via.array.size = 0;
} else {
}
else {
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* const pend = p + size;
@ -89,6 +109,25 @@ 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>
struct convert<std::multiset<T> > {
msgpack::object const& operator()(msgpack::object const& o, std::multiset<T>& v) const {

View File

@ -1,7 +1,7 @@
//
// 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");
// you may not use this file except in compliance with the License.
@ -33,23 +33,26 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor {
#if !defined(MSGPACK_USE_CPP03)
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 {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
std::vector<T> v;
v.reserve(o.via.array.size);
if (o.via.array.size > 0) {
msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
do {
v.emplace_back(p->as<T>());
v.push_back(p->as<T>());
++p;
} while (p < pend);
}
return v;
}
};
#endif
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T>
struct convert<std::vector<T> > {
@ -91,7 +94,8 @@ struct object_with_zone<std::vector<T> > {
if (v.empty()) {
o.via.array.ptr = nullptr;
o.via.array.size = 0;
} else {
}
else {
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* 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;
namespace adaptor {
template <typename T>
template <typename T, typename Enabler = void>
struct as;
} // namespace adaptor

View File

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

View File

@ -64,7 +64,7 @@ FOREACH (source_file ${check_PROGRAMS})
)
ADD_TEST (${source_file_we} ${source_file_we})
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 ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

View File

@ -192,6 +192,18 @@ struct no_def_con {
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 {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
@ -207,6 +219,14 @@ struct as<no_def_con> {
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // 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)
{
no_def_con val1(42);
@ -216,16 +236,29 @@ TEST(MSGPACK_NO_DEF_CON, simple_buffer)
msgpack::unpack(ret, sbuf.data(), sbuf.size());
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 {
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 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 {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
@ -249,7 +282,7 @@ TEST(MSGPACK_NO_DEF_CON_COMPOSITE, simple_buffer)
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
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 {
@ -281,7 +314,191 @@ TEST(MSGPACK_NO_DEF_CON_INHERIT, simple_buffer)
msgpack::unpacked ret;
msgpack::unpack(ret, sbuf.data(), sbuf.size());
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)