Added C-Style array support.

Existing mapping:
  convert:
  pack:
    char[N]       => STR
    const char[N] => STR
  object:
    char[N]       => STR (v1 only)
    const char[N] => STR (v1 only)
  object_with_zone:
    char[N]       => STR
    const char[N] => STR

Additional mapping:

  convert:
    STR        => char[N]
    ARRAY      => T[N]
  pack:
    T[N]       => ARRAY
    const T[N] => ARRAY
  object:
  object_with_zone:
    T[N]       => ARRAY
    const T[N] => ARRAY
This commit is contained in:
Takatoshi Kondo 2016-05-16 17:18:26 +09:00
parent 068041f05e
commit cc02da0ccf
22 changed files with 869 additions and 143 deletions

View File

@ -183,6 +183,7 @@ IF (MSGPACK_ENABLE_CXX)
include/msgpack/adaptor/boost/msgpack_variant_decl.hpp include/msgpack/adaptor/boost/msgpack_variant_decl.hpp
include/msgpack/adaptor/boost/optional.hpp include/msgpack/adaptor/boost/optional.hpp
include/msgpack/adaptor/boost/string_ref.hpp include/msgpack/adaptor/boost/string_ref.hpp
include/msgpack/adaptor/carray.hpp
include/msgpack/adaptor/char_ptr.hpp include/msgpack/adaptor/char_ptr.hpp
include/msgpack/adaptor/check_container_size.hpp include/msgpack/adaptor/check_container_size.hpp
include/msgpack/adaptor/check_container_size_decl.hpp include/msgpack/adaptor/check_container_size_decl.hpp
@ -255,6 +256,7 @@ IF (MSGPACK_ENABLE_CXX)
include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp
include/msgpack/v1/adaptor/boost/optional.hpp include/msgpack/v1/adaptor/boost/optional.hpp
include/msgpack/v1/adaptor/boost/string_ref.hpp include/msgpack/v1/adaptor/boost/string_ref.hpp
include/msgpack/v1/adaptor/carray.hpp
include/msgpack/v1/adaptor/char_ptr.hpp include/msgpack/v1/adaptor/char_ptr.hpp
include/msgpack/v1/adaptor/check_container_size.hpp include/msgpack/v1/adaptor/check_container_size.hpp
include/msgpack/v1/adaptor/check_container_size_decl.hpp include/msgpack/v1/adaptor/check_container_size_decl.hpp
@ -331,7 +333,6 @@ IF (MSGPACK_ENABLE_CXX)
include/msgpack/v1/preprocessor.hpp include/msgpack/v1/preprocessor.hpp
include/msgpack/v1/sbuffer.hpp include/msgpack/v1/sbuffer.hpp
include/msgpack/v1/sbuffer_decl.hpp include/msgpack/v1/sbuffer_decl.hpp
include/msgpack/v1/type.hpp
include/msgpack/v1/unpack.hpp include/msgpack/v1/unpack.hpp
include/msgpack/v1/unpack_decl.hpp include/msgpack/v1/unpack_decl.hpp
include/msgpack/v1/version.hpp include/msgpack/v1/version.hpp

View File

@ -0,0 +1,15 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2016 KONDO Takatoshi
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef MSGPACK_TYPE_CARRAY_HPP
#define MSGPACK_TYPE_CARRAY_HPP
#include "msgpack/v1/adaptor/carray.hpp"
#endif // MSGPACK_TYPE_CARRAY_HPP

View File

@ -1,6 +1,7 @@
#include "cpp_config.hpp" #include "cpp_config.hpp"
#include "adaptor/array_ref.hpp" #include "adaptor/array_ref.hpp"
#include "adaptor/bool.hpp" #include "adaptor/bool.hpp"
#include "adaptor/carray.hpp"
#include "adaptor/char_ptr.hpp" #include "adaptor/char_ptr.hpp"
#include "adaptor/deque.hpp" #include "adaptor/deque.hpp"
#include "adaptor/ext.hpp" #include "adaptor/ext.hpp"

View File

@ -50,27 +50,61 @@ struct object_with_zone {
template <typename T> template <typename T>
inline inline
msgpack::object const& operator>> (msgpack::object const& o, T& v) { typename msgpack::enable_if<
!is_array<T>::value,
msgpack::object const&
>::type
operator>> (msgpack::object const& o, T& v) {
return msgpack::adaptor::convert<T>()(o, v); return msgpack::adaptor::convert<T>()(o, v);
} }
template <typename T, std::size_t N>
inline
msgpack::object const& operator>> (msgpack::object const& o, T(&v)[N]) {
return msgpack::adaptor::convert<T[N]>()(o, v);
}
template <typename Stream, typename T> template <typename Stream, typename T>
inline inline
msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, T const& v) { typename msgpack::enable_if<
!is_array<T>::value,
msgpack::packer<Stream>&
>::type
operator<< (msgpack::packer<Stream>& o, T const& v) {
return msgpack::adaptor::pack<T>()(o, v); return msgpack::adaptor::pack<T>()(o, v);
} }
template <typename Stream, typename T, std::size_t N>
template <typename T>
inline inline
void operator<< (msgpack::object& o, T const& v) { msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const T(&v)[N]) {
msgpack::adaptor::object<T>()(o, v); return msgpack::adaptor::pack<T[N]>()(o, v);
} }
template <typename T> template <typename T>
inline inline
void operator<< (msgpack::object::with_zone& o, T const& v) { typename msgpack::enable_if<
!is_array<T>::value
>::type
operator<< (msgpack::object& o, T const& v) {
msgpack::adaptor::object<T>()(o, v);
}
template <typename T, std::size_t N>
inline
void operator<< (msgpack::v1::object& o, const T(&v)[N]) {
msgpack::v1::adaptor::object<T[N]>()(o, v);
}
template <typename T>
inline
typename msgpack::enable_if<
!is_array<T>::value
>::type
operator<< (msgpack::object::with_zone& o, T const& v) {
msgpack::adaptor::object_with_zone<T>()(o, v); msgpack::adaptor::object_with_zone<T>()(o, v);
} }
template <typename T, std::size_t N>
inline
void operator<< (msgpack::object::with_zone& o, const T(&v)[N]) {
msgpack::adaptor::object_with_zone<T[N]>()(o, v);
}
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)

View File

@ -12,6 +12,7 @@
#include "msgpack/versioning.hpp" #include "msgpack/versioning.hpp"
#include "msgpack/object_fwd.hpp" #include "msgpack/object_fwd.hpp"
#include "msgpack/pack.hpp"
namespace msgpack { namespace msgpack {
@ -43,16 +44,38 @@ struct object_with_zone;
// operators // operators
template <typename T> template <typename T>
msgpack::object const& operator>> (msgpack::object const& o, T& v); typename msgpack::enable_if<
!is_array<T>::value,
msgpack::object const&
>::type
operator>> (msgpack::object const& o, T& v);
template <typename T, std::size_t N>
msgpack::object const& operator>> (msgpack::object const& o, T(&v)[N]);
template <typename Stream, typename T> template <typename Stream, typename T>
msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, T const& v); typename msgpack::enable_if<
!is_array<T>::value,
msgpack::packer<Stream>&
>::type
operator<< (msgpack::packer<Stream>& o, T const& v);
template <typename Stream, typename T, std::size_t N>
msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const T(&v)[N]);
template <typename T> template <typename T>
void operator<< (msgpack::object& o, T const& v); typename msgpack::enable_if<
!is_array<T>::value
>::type
operator<< (msgpack::object& o, T const& v);
template <typename T, std::size_t N>
void operator<< (msgpack::object& o, const T(&v)[N]);
template <typename T> template <typename T>
void operator<< (msgpack::object::with_zone& o, T const& v); typename msgpack::enable_if<
!is_array<T>::value
>::type
operator<< (msgpack::object::with_zone& o, T const& v);
template <typename T, std::size_t N>
void operator<< (msgpack::object::with_zone& o, const T(&v)[N]);
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)

View File

@ -12,6 +12,7 @@
#include "msgpack/v1/adaptor/array_ref.hpp" #include "msgpack/v1/adaptor/array_ref.hpp"
#include "msgpack/adaptor/check_container_size.hpp" #include "msgpack/adaptor/check_container_size.hpp"
#include "msgpack/cpp_config.hpp"
#include <cstring> #include <cstring>
#include <string> #include <string>
@ -30,6 +31,10 @@ struct array_ref {
T* data; T* data;
std::size_t size() const {
return data->size();
}
template <typename U> template <typename U>
bool operator==(array_ref<U> const& t) const { bool operator==(array_ref<U> const& t) const {
return *data == *t.data; return *data == *t.data;
@ -60,16 +65,88 @@ struct array_ref {
} }
}; };
template <typename T, std::size_t N>
struct array_ref<T[N]> {
array_ref() : data(nullptr) {}
array_ref(T(&t)[N]) : data(t) {}
T* data;
std::size_t size() const {
return N;
}
template <typename U>
bool operator==(array_ref<U> const& t) const {
if (N != t.size()) return false;
T const* pself = data;
U const* pother = t.data;
for (; pself != &data[N]; ++pself, ++pother) {
if (*pself != *pother) return false;
}
return true;
}
template <typename U>
bool operator!=(array_ref<U> const& t) const {
return !(*this == t);
}
template <typename U>
bool operator< (array_ref<U> const& t) const
{
T const* pself = data;
U const* pother = t.data;
for (; pself != &data[N] && pother != t.data[t.size()]; ++pself, ++pother) {
if (*pself < *pother) return true;
}
if (N < t.size()) return true;
return false;
}
template <typename U>
bool operator> (array_ref<U> const& t) const
{
return t.data < data;
}
template <typename U>
bool operator<= (array_ref<U> const& t) const
{
return !(t.data < data);
}
template <typename U>
bool operator>= (array_ref<U> const& t) const
{
return !(data < t.data);
}
};
template <typename T> template <typename T>
inline array_ref<T const> make_array_ref(T const& t) { inline
typename msgpack::enable_if<
!msgpack::is_array<T const>::value,
array_ref<T const>
>::type
make_array_ref(const T& t) {
return array_ref<T const>(t); return array_ref<T const>(t);
} }
template <typename T> template <typename T>
inline array_ref<T> make_array_ref(T& t) { inline
typename msgpack::enable_if<
!msgpack::is_array<T>::value,
array_ref<T>
>::type
make_array_ref(T& t) {
return array_ref<T>(t); return array_ref<T>(t);
} }
template <typename T, std::size_t N>
inline array_ref<const T[N]> make_array_ref(const T(&t)[N]) {
return array_ref<const T[N]>(t);
}
template <typename T, std::size_t N>
inline array_ref<T[N]> make_array_ref(T(&t)[N]) {
return array_ref<T[N]>(t);
}
} // namespace type } // namespace type
@ -80,7 +157,7 @@ struct convert<msgpack::type::array_ref<T> > {
msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<T>& v) const {
if (!v.data) { throw msgpack::type_error(); } if (!v.data) { throw msgpack::type_error(); }
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (v.data->size() < o.via.bin.size) { throw msgpack::type_error(); } if (v.size() < o.via.bin.size) { throw msgpack::type_error(); }
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;
@ -95,6 +172,26 @@ struct convert<msgpack::type::array_ref<T> > {
} }
}; };
template <typename T, std::size_t N>
struct convert<msgpack::type::array_ref<T[N]> > {
msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<T[N]>& v) const {
if (!v.data) { throw msgpack::type_error(); }
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (v.size() < o.via.bin.size) { throw msgpack::type_error(); }
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;
T* it = v.data;
do {
p->convert(*it);
++p;
++it;
} while(p < pend);
}
return o;
}
};
template <typename T> template <typename T>
struct convert<msgpack::type::array_ref<std::vector<T> > > { struct convert<msgpack::type::array_ref<std::vector<T> > > {
msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<std::vector<T> >& v) const { msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<std::vector<T> >& v) const {
@ -120,7 +217,7 @@ struct pack<msgpack::type::array_ref<T> > {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::array_ref<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::array_ref<T>& v) const {
if (!v.data) { throw msgpack::type_error(); } if (!v.data) { throw msgpack::type_error(); }
uint32_t size = checked_get_container_size(v.data->size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for (typename T::const_iterator it(v.data->begin()), it_end(v.data->end()); for (typename T::const_iterator it(v.data->begin()), it_end(v.data->end());
it != it_end; ++it) { it != it_end; ++it) {
@ -130,6 +227,21 @@ struct pack<msgpack::type::array_ref<T> > {
} }
}; };
template <typename T, std::size_t N>
struct pack<msgpack::type::array_ref<T[N]> > {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::array_ref<T[N]>& v) const {
if (!v.data) { throw msgpack::type_error(); }
uint32_t size = checked_get_container_size(v.size());
o.pack_array(size);
for (T const* it = v.data;
it != &v.data[v.size()]; ++it) {
o.pack(*it);
}
return o;
}
};
template <typename T> template <typename T>
struct object_with_zone<msgpack::type::array_ref<T> > { struct object_with_zone<msgpack::type::array_ref<T> > {
void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref<T>& v) const { void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref<T>& v) const {
@ -140,7 +252,7 @@ struct object_with_zone<msgpack::type::array_ref<T> > {
o.via.array.size = 0; o.via.array.size = 0;
} }
else { else {
uint32_t size = checked_get_container_size(v.data->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;
o.via.array.ptr = p; o.via.array.ptr = p;
@ -162,6 +274,26 @@ struct object_with_zone<msgpack::type::array_ref<T> > {
} }
}; };
template <typename T, std::size_t N>
struct object_with_zone<msgpack::type::array_ref<T[N]> > {
void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref<T[N]>& v) const {
if (!v.data) { throw msgpack::type_error(); }
o.type = msgpack::type::ARRAY;
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;
o.via.array.ptr = p;
o.via.array.size = size;
T const* it = v.data;
do {
*p = msgpack::object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
};
} // namespace adaptor } // namespace adaptor
/// @cond /// @cond

View File

@ -25,10 +25,24 @@ template <typename T>
struct array_ref; struct array_ref;
template <typename T> template <typename T>
array_ref<T const> make_array_ref(T const& t); typename msgpack::enable_if<
!msgpack::is_array<T const>::value,
array_ref<T const>
>::type
make_array_ref(T const& t);
template <typename T> template <typename T>
array_ref<T> make_array_ref(T& t); typename msgpack::enable_if<
!msgpack::is_array<T>::value,
array_ref<T>
>::type
make_array_ref(T& t);
template <typename T, std::size_t N>
array_ref<const T[N]> make_array_ref(const T(&t)[N]);
template <typename T, std::size_t N>
array_ref<T[N]> make_array_ref(T(&t)[N]);
} // namespace type } // namespace type

View File

@ -0,0 +1,234 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2016 KONDO Takatoshi
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef MSGPACK_V1_TYPE_CARRAY_HPP
#define MSGPACK_V1_TYPE_CARRAY_HPP
#include "msgpack/versioning.hpp"
#include "msgpack/object_fwd.hpp"
#include "msgpack/adaptor/adaptor_base.hpp"
#include "msgpack/adaptor/check_container_size.hpp"
namespace msgpack {
/// @cond
MSGPACK_API_VERSION_NAMESPACE(v1) {
/// @endcond
namespace adaptor {
template <typename T, std::size_t N>
struct convert<T[N]> {
msgpack::object const& operator()(msgpack::object const& o, T* v) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (o.via.array.size > N) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr;
msgpack::object* const pend = o.via.array.ptr + o.via.array.size;
do {
p->convert(*v);
++p;
++v;
} while(p < pend);
return o;
}
};
template <std::size_t N>
struct convert<char[N]> {
msgpack::object const& operator()(msgpack::object const& o, char(&v)[N]) const {
switch (o.type) {
case msgpack::type::BIN:
if (o.via.bin.size > N) { throw msgpack::type_error(); }
std::memcpy(v, o.via.bin.ptr, o.via.bin.size);
break;
case msgpack::type::STR:
if (o.via.str.size + 1 > N) { throw msgpack::type_error(); }
std::memcpy(v, o.via.str.ptr, o.via.str.size);
v[o.via.str.size] = '\0';
break;
default:
throw msgpack::type_error();
break;
}
return o;
}
};
template <std::size_t N>
struct convert<unsigned char[N]> {
msgpack::object const& operator()(msgpack::object const& o, unsigned char(&v)[N]) const {
switch (o.type) {
case msgpack::type::BIN:
if (o.via.bin.size > N) { throw msgpack::type_error(); }
std::memcpy(v, o.via.bin.ptr, o.via.bin.size);
break;
case msgpack::type::STR:
if (o.via.str.size + 1 > N) { throw msgpack::type_error(); }
std::memcpy(v, o.via.str.ptr, o.via.str.size);
v[o.via.str.size] = '\0';
break;
default:
throw msgpack::type_error();
break;
}
return o;
}
};
template <typename T, std::size_t N>
struct pack<T[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const T(&v)[N]) const {
o.pack_array(N);
const T* ptr = v;
for (; ptr != &v[N]; ++ptr) o.pack(*ptr);
return o;
}
};
template <std::size_t N>
struct pack<char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const char(&v)[N]) const {
char const* p = v;
uint32_t size = checked_get_container_size(std::strlen(p));
o.pack_str(size);
o.pack_str_body(p, size);
return o;
}
};
template <std::size_t N>
struct pack<const char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const char(&v)[N]) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.pack_str(size);
o.pack_str_body(v, size);
return o;
}
};
template <std::size_t N>
struct pack<unsigned char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const unsigned char(&v)[N]) const {
unsigned char const* p = v;
uint32_t size = checked_get_container_size(N);
o.pack_bin(size);
o.pack_bin_body(reinterpret_cast<char const*>(p), size);
return o;
}
};
template <std::size_t N>
struct pack<const unsigned char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const unsigned char(&v)[N]) const {
unsigned char const* p = v;
uint32_t size = checked_get_container_size(N);
o.pack_bin(size);
o.pack_bin_body(reinterpret_cast<char const*>(p), size);
return o;
}
};
template <typename T, std::size_t N>
struct object_with_zone<T[N]> {
void operator()(msgpack::object::with_zone& o, const T(&v)[N]) const {
o.type = msgpack::type::ARRAY;
msgpack::object* ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object) * N));
o.via.array.ptr = ptr;
o.via.array.size = N;
const T* pv = v;
for (; pv != &v[N]; ++pv) {
*ptr++ = msgpack::object(*pv, o.zone);
}
}
};
template <std::size_t N>
struct object_with_zone<char[N]> {
void operator()(msgpack::object::with_zone& o, const char(&v)[N]) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.str.ptr = ptr;
o.via.str.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object_with_zone<const char[N]> {
void operator()(msgpack::object::with_zone& o, const char(&v)[N]) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.str.ptr = ptr;
o.via.str.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object_with_zone<unsigned char[N]> {
void operator()(msgpack::object::with_zone& o, const unsigned char(&v)[N]) const {
uint32_t size = checked_get_container_size(N);
o.type = msgpack::type::BIN;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.bin.ptr = ptr;
o.via.bin.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object_with_zone<const unsigned char[N]> {
void operator()(msgpack::object::with_zone& o, const unsigned char(&v)[N]) const {
uint32_t size = checked_get_container_size(N);
o.type = msgpack::type::BIN;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.bin.ptr = ptr;
o.via.bin.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object<char[N]> {
void operator()(msgpack::object& o, const char(&v)[N]) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
o.via.str.ptr = v;
o.via.str.size = size;
}
};
template <std::size_t N>
struct object<const char[N]> {
void operator()(msgpack::object& o, const char(&v)[N]) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
o.via.str.ptr = v;
o.via.str.size = size;
}
};
} // namespace adaptor
/// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond
} // namespace msgpack
#endif // MSGPACK_V1_TYPE_CARRAY_HPP

View File

@ -81,72 +81,6 @@ struct object<char*> {
} }
}; };
template <std::size_t N>
struct pack<char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.pack_str(size);
o.pack_str_body(v, size);
return o;
}
};
template <std::size_t N>
struct object_with_zone<char[N]> {
void operator()(msgpack::object::with_zone& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.str.ptr = ptr;
o.via.str.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object<char[N]> {
void operator()(msgpack::object& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
o.via.str.ptr = v;
o.via.str.size = size;
}
};
template <std::size_t N>
struct pack<const char[N]> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.pack_str(size);
o.pack_str_body(v, size);
return o;
}
};
template <std::size_t N>
struct object_with_zone<const char[N]> {
void operator()(msgpack::object::with_zone& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
char* ptr = static_cast<char*>(o.zone.allocate_align(size));
o.via.str.ptr = ptr;
o.via.str.size = size;
std::memcpy(ptr, v, size);
}
};
template <std::size_t N>
struct object<const char[N]> {
void operator()(msgpack::object& o, const char* v) const {
uint32_t size = checked_get_container_size(std::strlen(v));
o.type = msgpack::type::STR;
o.via.str.ptr = v;
o.via.str.size = size;
}
};
} // namespace adaptor } // namespace adaptor
/// @cond /// @cond

View File

@ -70,6 +70,54 @@ struct underlying_type {
typedef int type; typedef int type;
}; };
template<class T>
struct is_array : false_type {};
template<class T>
struct is_array<T[]> : true_type {};
template<class T, std::size_t N>
struct is_array<T[N]> : true_type {};
template<class T>
struct remove_const {
typedef T type;
};
template<class T>
struct remove_const<const T> {
typedef T type;
};
template<class T>
struct remove_volatile {
typedef T type;
};
template<class T>
struct remove_volatile<volatile T> {
typedef T type;
};
template<class T>
struct remove_cv {
typedef typename msgpack::remove_volatile<
typename msgpack::remove_const<T>::type
>::type type;
};
namespace detail {
template<class T>
struct is_pointer_helper : false_type {};
template<class T>
struct is_pointer_helper<T*> : true_type {};
} // namespace detail
template<class T> struct is_pointer : detail::is_pointer_helper<typename remove_cv<T>::type> {};
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond /// @endcond

View File

@ -63,6 +63,19 @@ struct is_same;
template<typename T> template<typename T>
struct underlying_type; struct underlying_type;
template<class T>
struct is_array;
template<class T>
struct remove_const;
template<class T>
struct remove_volatile;
template<class T>
struct remove_cv;
template<class T>
struct is_pointer;
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond /// @endcond
@ -91,6 +104,11 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
using std::enable_if; using std::enable_if;
using std::is_same; using std::is_same;
using std::underlying_type; using std::underlying_type;
using std::is_array;
using std::remove_const;
using std::remove_volatile;
using std::remove_cv;
using std::is_pointer;
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)

View File

@ -38,6 +38,9 @@ template<std::size_t... Is> struct seq;
template<std::size_t N, std::size_t... Is> template<std::size_t N, std::size_t... Is>
struct gen_seq; struct gen_seq;
template <typename T>
struct is_non_const_pointer;
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v1) } // MSGPACK_API_VERSION_NAMESPACE(v1)
/// @endcond /// @endcond

View File

@ -526,7 +526,19 @@ inline object::implicit_type object::convert() const
} }
template <typename T> template <typename T>
inline T& object::convert(T& v) const inline
typename msgpack::enable_if<
!msgpack::is_array<T>::value && !msgpack::is_pointer<T>::value,
T&
>::type
object::convert(T& v) const
{
msgpack::operator>>(*this, v);
return v;
}
template <typename T, std::size_t N>
inline T(&object::convert(T(&v)[N]) const)[N]
{ {
msgpack::operator>>(*this, v); msgpack::operator>>(*this, v);
return v; return v;
@ -534,7 +546,12 @@ inline T& object::convert(T& v) const
#if !defined(MSGPACK_DISABLE_LEGACY_CONVERT) #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
template <typename T> template <typename T>
inline T* object::convert(T* v) const inline
typename msgpack::enable_if<
msgpack::is_pointer<T>::value,
T
>::type
object::convert(T v) const
{ {
convert(*v); convert(*v);
return v; return v;

View File

@ -138,7 +138,14 @@ struct object {
* @return The reference of `v`. * @return The reference of `v`.
*/ */
template <typename T> template <typename T>
T& convert(T& v) const; typename msgpack::enable_if<
!msgpack::is_array<T>::value && !msgpack::is_pointer<T>::value,
T&
>::type
convert(T& v) const;
template <typename T, std::size_t N>
T (&convert(T(&v)[N]) const)[N];
#if !defined(MSGPACK_DISABLE_LEGACY_CONVERT) #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
@ -150,7 +157,11 @@ struct object {
* @return The pointer of `v`. * @return The pointer of `v`.
*/ */
template <typename T> template <typename T>
T* convert(T* v) const; typename msgpack::enable_if<
msgpack::is_pointer<T>::value,
T
>::type
convert(T v) const;
#endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT) #endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
/// Convert the object if not nil /// Convert the object if not nil

View File

@ -1,52 +0,0 @@
#include "cpp_config.hpp"
#include "adaptor/array_ref.hpp"
#include "adaptor/bool.hpp"
#include "adaptor/char_ptr.hpp"
#include "adaptor/deque.hpp"
#include "adaptor/ext.hpp"
#include "adaptor/fixint.hpp"
#include "adaptor/float.hpp"
#include "adaptor/int.hpp"
#include "adaptor/list.hpp"
#include "adaptor/map.hpp"
#include "adaptor/nil.hpp"
#include "adaptor/pair.hpp"
#include "adaptor/raw.hpp"
#include "adaptor/v4raw.hpp"
#include "adaptor/set.hpp"
#include "adaptor/string.hpp"
#include "adaptor/vector.hpp"
#include "adaptor/vector_bool.hpp"
#include "adaptor/vector_char.hpp"
#include "adaptor/vector_unsigned_char.hpp"
#include "adaptor/msgpack_tuple.hpp"
#include "adaptor/define.hpp"
#if defined(MSGPACK_USE_CPP03)
#include "adaptor/tr1/unordered_map.hpp"
#include "adaptor/tr1/unordered_set.hpp"
#else // defined(MSGPACK_USE_CPP03)
#include "adaptor/cpp11/array.hpp"
#include "adaptor/cpp11/array_char.hpp"
#include "adaptor/cpp11/array_unsigned_char.hpp"
#include "adaptor/cpp11/forward_list.hpp"
#include "adaptor/cpp11/reference_wrapper.hpp"
#include "adaptor/cpp11/shared_ptr.hpp"
#include "adaptor/cpp11/tuple.hpp"
#include "adaptor/cpp11/unique_ptr.hpp"
#include "adaptor/cpp11/unordered_map.hpp"
#include "adaptor/cpp11/unordered_set.hpp"
#endif // defined(MSGPACK_USE_CPP03)
#if defined(MSGPACK_USE_BOOST)
#include "adaptor/boost/fusion.hpp"
#include "adaptor/boost/msgpack_variant.hpp"
#include "adaptor/boost/optional.hpp"
#include "adaptor/boost/string_ref.hpp"
#endif // defined(MSGPACK_USE_BOOST)

View File

@ -32,7 +32,14 @@ struct pack : v1::adaptor::pack<T, Enabler> {
}; };
template <typename T, typename Enabler> template <typename T, typename Enabler>
struct object<T, Enabler, typename msgpack::enable_if<!msgpack::is_same<T, std::string>::value>::type> : v1::adaptor::object<T, Enabler> { struct object<
T,
Enabler,
typename msgpack::enable_if<
!msgpack::is_same<T, std::string>::value &&
!msgpack::is_array<T>::value
>::type>
: v1::adaptor::object<T, Enabler> {
}; };
template <typename T, typename Enabler> template <typename T, typename Enabler>

View File

@ -32,6 +32,14 @@ using v1::is_same;
using v1::underlying_type; using v1::underlying_type;
using v1::is_array;
using v1::remove_const;
using v1::remove_volatile;
using v1::remove_cv;
using v1::is_pointer;
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v2) } // MSGPACK_API_VERSION_NAMESPACE(v2)
/// @endcond /// @endcond
@ -57,6 +65,13 @@ using v1::swap;
using v1::enable_if; using v1::enable_if;
using v1::is_same; using v1::is_same;
using v1::underlying_type; using v1::underlying_type;
using v1::is_array;
using v1::remove_const;
using v1::remove_volatile;
using v1::remove_cv;
using v1::is_pointer;
/// @cond /// @cond
} // MSGPACK_API_VERSION_NAMESPACE(v2) } // MSGPACK_API_VERSION_NAMESPACE(v2)

View File

@ -172,6 +172,7 @@ nobase_include_HEADERS += \
../include/msgpack/adaptor/boost/msgpack_variant_decl.hpp \ ../include/msgpack/adaptor/boost/msgpack_variant_decl.hpp \
../include/msgpack/adaptor/boost/optional.hpp \ ../include/msgpack/adaptor/boost/optional.hpp \
../include/msgpack/adaptor/boost/string_ref.hpp \ ../include/msgpack/adaptor/boost/string_ref.hpp \
../include/msgpack/adaptor/carray.hpp \
../include/msgpack/adaptor/char_ptr.hpp \ ../include/msgpack/adaptor/char_ptr.hpp \
../include/msgpack/adaptor/check_container_size.hpp \ ../include/msgpack/adaptor/check_container_size.hpp \
../include/msgpack/adaptor/check_container_size_decl.hpp \ ../include/msgpack/adaptor/check_container_size_decl.hpp \
@ -244,6 +245,7 @@ nobase_include_HEADERS += \
../include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp \ ../include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp \
../include/msgpack/v1/adaptor/boost/optional.hpp \ ../include/msgpack/v1/adaptor/boost/optional.hpp \
../include/msgpack/v1/adaptor/boost/string_ref.hpp \ ../include/msgpack/v1/adaptor/boost/string_ref.hpp \
../include/msgpack/v1/adaptor/carray.hpp \
../include/msgpack/v1/adaptor/char_ptr.hpp \ ../include/msgpack/v1/adaptor/char_ptr.hpp \
../include/msgpack/v1/adaptor/check_container_size.hpp \ ../include/msgpack/v1/adaptor/check_container_size.hpp \
../include/msgpack/v1/adaptor/check_container_size_decl.hpp \ ../include/msgpack/v1/adaptor/check_container_size_decl.hpp \
@ -320,7 +322,6 @@ nobase_include_HEADERS += \
../include/msgpack/v1/preprocessor.hpp \ ../include/msgpack/v1/preprocessor.hpp \
../include/msgpack/v1/sbuffer.hpp \ ../include/msgpack/v1/sbuffer.hpp \
../include/msgpack/v1/sbuffer_decl.hpp \ ../include/msgpack/v1/sbuffer_decl.hpp \
../include/msgpack/v1/type.hpp \
../include/msgpack/v1/unpack.hpp \ ../include/msgpack/v1/unpack.hpp \
../include/msgpack/v1/unpack_decl.hpp \ ../include/msgpack/v1/unpack_decl.hpp \
../include/msgpack/v1/version.hpp \ ../include/msgpack/v1/version.hpp \

View File

@ -10,6 +10,7 @@ INCLUDE_DIRECTORIES (
LIST (APPEND check_PROGRAMS LIST (APPEND check_PROGRAMS
array_ref.cpp array_ref.cpp
buffer.cpp buffer.cpp
carray.cpp
cases.cpp cases.cpp
convert.cpp convert.cpp
fixint.cpp fixint.cpp

View File

@ -5,6 +5,7 @@ AM_LDFLAGS = $(top_builddir)/src/libmsgpackc.la -lgtest_main -lgtest -lpthread
check_PROGRAMS = \ check_PROGRAMS = \
array_ref \ array_ref \
buffer \ buffer \
carray \
cases \ cases \
convert \ convert \
fixint \ fixint \
@ -50,6 +51,7 @@ TESTS = $(check_PROGRAMS)
array_ref_SOURCES = array_ref.cpp array_ref_SOURCES = array_ref.cpp
buffer_SOURCES = buffer.cpp buffer_SOURCES = buffer.cpp
carray_SOURCES = carray.cpp
cases_SOURCES = cases.cpp cases_SOURCES = cases.cpp
convert_SOURCES = convert.cpp convert_SOURCES = convert.cpp
fixint_SOURCES = fixint.cpp fixint_SOURCES = fixint.cpp

264
test/carray.cpp Normal file
View File

@ -0,0 +1,264 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
#include <sstream>
TEST(carray, pack_unpack_int)
{
std::stringstream ss;
int v1[] = { 0, 1 };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
int v2[2];
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_int)
{
int v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
int v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_const_int)
{
std::stringstream ss;
const int v1[] = { 0, 1 };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
int v2[2];
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_const_int)
{
const int v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
int v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_string)
{
std::stringstream ss;
std::string v1[] = { "ABC", "DEFG" };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
std::string v2[2];
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_string)
{
std::string v1[] = { "ABC", "DEFG" };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
std::string v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_char)
{
std::stringstream ss;
char v1[] = { 0, 1 };
msgpack::pack(ss, msgpack::type::make_array_ref(v1));
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
char v2[2];
msgpack::type::array_ref<char[2]> ar = msgpack::type::make_array_ref(v2);
oh.get().convert(ar);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_char_as_str)
{
std::stringstream ss;
char v1[2] = { 1, '\0' };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::STR);
EXPECT_EQ(oh.get().via.str.size, 1);
char v2[2] = { 2, 3 };
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_char)
{
char v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(msgpack::type::make_array_ref(v1), z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
char v2[2];
msgpack::type::array_ref<char[2]> ar = msgpack::type::make_array_ref(v2);
o.convert(ar);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_char_as_str)
{
char v1[] = { 1, '\0' };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::STR);
EXPECT_EQ(o.via.str.size, 1);
char v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_unsigned_char)
{
std::stringstream ss;
unsigned char v1[] = { 0, 1 };
msgpack::pack(ss, msgpack::type::make_array_ref(v1));
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
unsigned char v2[2];
msgpack::type::array_ref<unsigned char[2]> ar = msgpack::type::make_array_ref(v2);
oh.get().convert(ar);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_unsigned_char_as_bin)
{
std::stringstream ss;
unsigned char v1[] = { 0, 1 };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::BIN);
EXPECT_EQ(oh.get().via.bin.size, 2);
unsigned char v2[2];
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_unsigned_char)
{
unsigned char v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(msgpack::type::make_array_ref(v1), z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
unsigned char v2[2];
msgpack::type::array_ref<unsigned char[2]> ar = msgpack::type::make_array_ref(v2);
o.convert(ar);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_unsigned_char_as_bin)
{
unsigned char v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::BIN);
EXPECT_EQ(o.via.bin.size, 2);
unsigned char v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, pack_unpack_signed_char)
{
std::stringstream ss;
signed char v1[] = { 0, 1 };
msgpack::pack(ss, v1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
EXPECT_EQ(oh.get().type, msgpack::type::ARRAY);
signed char v2[2];
oh.get().convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
TEST(carray, obj_with_zone_signed_char)
{
signed char v1[] = { 0, 1 };
msgpack::zone z;
msgpack::object o(v1, z);
EXPECT_EQ(o.type, msgpack::type::ARRAY);
signed char v2[2];
o.convert(v2);
EXPECT_EQ(v1[0], v2[0]);
EXPECT_EQ(v1[1], v2[1]);
}
#if MSGPACK_DEFAULT_API_VERSION == 1
TEST(carray, object_as_str)
{
char v1[] = { 1, '\0' };
msgpack::zone z;
msgpack::object o(v1);
EXPECT_EQ(o.type, msgpack::type::STR);
}
TEST(carray, object_as_str_const)
{
const char v1[] = { 1, '\0' };
msgpack::zone z;
msgpack::object o(v1);
EXPECT_EQ(o.type, msgpack::type::STR);
}
#endif // MSGPACK_DEFAULT_API_VERSION == 1

View File

@ -341,6 +341,8 @@ TEST(object_with_zone, char_ptr)
EXPECT_EQ(obj.as<string>()[0], 'a'); EXPECT_EQ(obj.as<string>()[0], 'a');
} }
#if MSGPACK_DEFAULT_API_VERSION == 1
TEST(object_without_zone, char_ptr) TEST(object_without_zone, char_ptr)
{ {
char v[] = "abc"; char v[] = "abc";
@ -351,6 +353,7 @@ TEST(object_without_zone, char_ptr)
EXPECT_EQ(obj.as<string>()[0], 'd'); EXPECT_EQ(obj.as<string>()[0], 'd');
} }
#endif // MSGPACK_DEFAULT_API_VERSION == 1
// raw_ref // raw_ref
TEST(object_with_zone, raw_ref) TEST(object_with_zone, raw_ref)