mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-21 15:51:44 +02:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8c602e8579 | ||
![]() |
0cc87c0a15 | ||
![]() |
9d4ff7fe10 | ||
![]() |
2486aad254 | ||
![]() |
1fb1dad6bc | ||
![]() |
2d65f66b0e | ||
![]() |
4bc88d7f6f | ||
![]() |
35638ead37 | ||
![]() |
f09713e838 | ||
![]() |
6507243913 | ||
![]() |
f2ffcf0b08 | ||
![]() |
df1d126f61 | ||
![]() |
211c50c755 | ||
![]() |
8bd1b7877c | ||
![]() |
d6b2de9243 | ||
![]() |
818d87c9cb | ||
![]() |
327f3d1ad0 | ||
![]() |
ac062e28cb | ||
![]() |
34f8fd65bb | ||
![]() |
706fde4d56 | ||
![]() |
2dd3dbc85f |
1
.github/workflows/coverage.yml
vendored
1
.github/workflows/coverage.yml
vendored
@@ -56,6 +56,7 @@ jobs:
|
||||
-D MSGPACK_BUILD_TESTS=ON \
|
||||
-D CMAKE_BUILD_TYPE=Debug \
|
||||
-D MSGPACK_GEN_COVERAGE=ON \
|
||||
-D MSGPACK_USE_STD_VARIANT_ADAPTOR=ON \
|
||||
-D CMAKE_PREFIX_PATH="$HOME/zlib-prefix/64;$HOME/boost-prefix/64" \
|
||||
-B build \
|
||||
-S . || exit 1
|
||||
|
1
.github/workflows/gha.yml
vendored
1
.github/workflows/gha.yml
vendored
@@ -145,6 +145,7 @@ jobs:
|
||||
3)
|
||||
export CXX="g++-10"
|
||||
export MSGPACK_CXX_VERSION="MSGPACK_CXX17=ON"
|
||||
export MSGPACK_USE_STD_VARIANT_ADAPTOR="MSGPACK_USE_STD_VARIANT_ADAPTOR=ON"
|
||||
;;
|
||||
4)
|
||||
export CXX="clang++-10"
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -49,3 +49,8 @@ Makefile
|
||||
/test/streaming_c
|
||||
/test/version
|
||||
/test/zone
|
||||
|
||||
build
|
||||
*-build
|
||||
.cache
|
||||
compile_commands.json
|
||||
|
@@ -1,3 +1,9 @@
|
||||
# 2023-07-08 version 6.1.0
|
||||
* Remove dependency on boost in chrono.hpp (#1076)
|
||||
* Add support for std::variant behavior (#1075)
|
||||
* Fix msgpack::type::variant behavior to respect MessagePack format (#1071)
|
||||
* Add rebind allocators (#1065)
|
||||
|
||||
# 2023-03-02 version 6.0.0
|
||||
## << breaking changes >>
|
||||
* Change CMake package name of C++ library to msgpack-cxx (#1054)
|
||||
|
@@ -23,16 +23,17 @@ OPTION (MSGPACK_CXX14 "Using c++14 compiler" OFF)
|
||||
OPTION (MSGPACK_CXX17 "Using c++17 compiler" OFF)
|
||||
OPTION (MSGPACK_CXX20 "Using c++20 compiler" OFF)
|
||||
|
||||
OPTION (MSGPACK_32BIT "32bit compile" OFF)
|
||||
OPTION (MSGPACK_USE_BOOST "Use Boost libraried" ON)
|
||||
OPTION (MSGPACK_USE_X3_PARSE "Use Boost X3 parse" OFF)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build tests" OFF)
|
||||
OPTION (MSGPACK_BUILD_DOCS "Build Doxygen documentation" ON)
|
||||
OPTION (MSGPACK_FUZZ_REGRESSION "Enable regression testing" OFF)
|
||||
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples" OFF)
|
||||
OPTION (MSGPACK_GEN_COVERAGE "Generate coverage report" OFF)
|
||||
OPTION (MSGPACK_USE_STATIC_BOOST "Statically link with boost libraries" OFF)
|
||||
OPTION (MSGPACK_CHAR_SIGN "Char sign to use (signed or unsigned)")
|
||||
OPTION (MSGPACK_32BIT "32bit compile" OFF)
|
||||
OPTION (MSGPACK_USE_BOOST "Use Boost libraried" ON)
|
||||
OPTION (MSGPACK_USE_X3_PARSE "Use Boost X3 parse" OFF)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build tests" OFF)
|
||||
OPTION (MSGPACK_BUILD_DOCS "Build Doxygen documentation" ON)
|
||||
OPTION (MSGPACK_FUZZ_REGRESSION "Enable regression testing" OFF)
|
||||
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples" OFF)
|
||||
OPTION (MSGPACK_GEN_COVERAGE "Generate coverage report" OFF)
|
||||
OPTION (MSGPACK_USE_STATIC_BOOST "Statically link with boost libraries" OFF)
|
||||
OPTION (MSGPACK_CHAR_SIGN "Char sign to use (signed or unsigned)")
|
||||
OPTION (MSGPACK_USE_STD_VARIANT_ADAPTOR "Enable the adaptor for std::variant" OFF)
|
||||
|
||||
SET (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@@ -92,6 +93,10 @@ ELSE ()
|
||||
TARGET_COMPILE_DEFINITIONS(msgpack-cxx INTERFACE MSGPACK_DEFAULT_API_VERSION=3)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
TARGET_COMPILE_DEFINITIONS(msgpack-cxx INTERFACE MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.1)
|
||||
INCLUDE (CheckCXXSourceCompiles)
|
||||
|
@@ -33,6 +33,7 @@ SET (msgpack-cxx_HEADERS
|
||||
include/msgpack/adaptor/cpp17/carray_byte.hpp
|
||||
include/msgpack/adaptor/cpp17/optional.hpp
|
||||
include/msgpack/adaptor/cpp17/string_view.hpp
|
||||
include/msgpack/adaptor/cpp17/variant.hpp
|
||||
include/msgpack/adaptor/cpp17/vector_byte.hpp
|
||||
include/msgpack/adaptor/cpp20/span.hpp
|
||||
include/msgpack/adaptor/define.hpp
|
||||
@@ -542,6 +543,7 @@ SET (msgpack-cxx_HEADERS
|
||||
include/msgpack/v1/adaptor/cpp17/carray_byte.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/optional.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/string_view.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/variant.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/vector_byte.hpp
|
||||
include/msgpack/v1/adaptor/cpp20/span.hpp
|
||||
include/msgpack/v1/adaptor/define.hpp
|
||||
|
@@ -1,7 +1,7 @@
|
||||
`msgpack` for C++
|
||||
===================
|
||||
|
||||
Version 6.0.0 [](https://github.com/msgpack/msgpack-c/actions) [](https://ci.appveyor.com/project/redboltz/msgpack-c/branch/cpp_master)
|
||||
Version 6.1.0 [](https://github.com/msgpack/msgpack-c/actions) [](https://ci.appveyor.com/project/redboltz/msgpack-c/branch/cpp_master)
|
||||
[](https://codecov.io/gh/msgpack/msgpack-c/branch/cpp_master)
|
||||
|
||||
It's like JSON but smaller and faster.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
version: 6.0.0.{build}
|
||||
version: 6.1.0.{build}
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
@@ -21,6 +21,7 @@ cmake \
|
||||
-D MSGPACK_CHAR_SIGN=${CHAR_SIGN} \
|
||||
-D MSGPACK_DEFAULT_API_VERSION=${API_VERSION} \
|
||||
-D MSGPACK_USE_X3_PARSE=${X3_PARSE} \
|
||||
-D MSGPACK_USE_STD_VARIANT_ADAPTOR=${STD_VARIANT_ADAPTOR} \
|
||||
-D CMAKE_CXX_FLAGS="${CXXFLAGS} ${ARCH_FLAG}" \
|
||||
-D CMAKE_INSTALL_PREFIX=$prefix_dir \
|
||||
-B $build_dir \
|
||||
|
16
include/msgpack/adaptor/cpp17/variant.hpp
Normal file
16
include/msgpack/adaptor/cpp17/variant.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2023 Uy Ha
|
||||
//
|
||||
// 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_CPP17_VARIANT_HPP
|
||||
#define MSGPACK_TYPE_CPP17_VARIANT_HPP
|
||||
|
||||
#include "msgpack/v1/adaptor/cpp17/variant.hpp"
|
||||
|
||||
#endif // MSGPACK_TYPE_CPP17_VARIANT_HPP
|
@@ -37,9 +37,7 @@
|
||||
#include "adaptor/cpp11/array_char.hpp"
|
||||
#include "adaptor/cpp11/array_unsigned_char.hpp"
|
||||
|
||||
#if !defined(MSGPACK_NO_BOOST)
|
||||
#include "adaptor/cpp11/chrono.hpp"
|
||||
#endif // !defined(MSGPACK_NO_BOOST)
|
||||
|
||||
#include "adaptor/cpp11/forward_list.hpp"
|
||||
#include "adaptor/cpp11/reference_wrapper.hpp"
|
||||
@@ -63,6 +61,10 @@
|
||||
#include "adaptor/cpp17/carray_byte.hpp"
|
||||
#include "adaptor/cpp17/vector_byte.hpp"
|
||||
|
||||
#if MSGPACK_HAS_INCLUDE(<variant>)
|
||||
#include "adaptor/cpp17/variant.hpp"
|
||||
#endif // MSGPACK_HAS_INCLUDE(<variant>)
|
||||
|
||||
#if MSGPACK_HAS_INCLUDE(<span>)
|
||||
#include "adaptor/cpp20/span.hpp"
|
||||
#endif // MSGPACK_HAS_INCLUDE(<span>)
|
||||
|
@@ -122,6 +122,12 @@ struct basic_variant :
|
||||
int_init(v);
|
||||
}
|
||||
basic_variant(unsigned long long v):base(uint64_t(v)) {}
|
||||
basic_variant(float v) {
|
||||
double_init(v);
|
||||
}
|
||||
basic_variant(double v) {
|
||||
double_init(v);
|
||||
}
|
||||
|
||||
bool is_nil() const {
|
||||
return boost::get<msgpack::type::nil_t>(this) != MSGPACK_NULLPTR;
|
||||
@@ -177,71 +183,50 @@ struct basic_variant :
|
||||
int64_t as_int64_t() const {
|
||||
return boost::get<int64_t>(*this);
|
||||
}
|
||||
int64_t& as_int64_t() {
|
||||
return boost::get<int64_t>(*this);
|
||||
}
|
||||
uint64_t as_uint64_t() const {
|
||||
return boost::get<uint64_t>(*this);
|
||||
}
|
||||
uint64_t& as_uint64_t() {
|
||||
return boost::get<uint64_t>(*this);
|
||||
}
|
||||
double as_double() const {
|
||||
return boost::get<double>(*this);
|
||||
}
|
||||
double& as_double() {
|
||||
return boost::get<double>(*this);
|
||||
if (is_double()) {
|
||||
return boost::get<double>(*this);
|
||||
}
|
||||
if (is_int64_t()) {
|
||||
return static_cast<double>(boost::get<int64_t>(*this));
|
||||
}
|
||||
if (is_uint64_t()) {
|
||||
return static_cast<double>(boost::get<uint64_t>(*this));
|
||||
}
|
||||
throw msgpack::type_error();
|
||||
}
|
||||
std::string const& as_string() const {
|
||||
return boost::get<std::string>(*this);
|
||||
}
|
||||
std::string& as_string() {
|
||||
return boost::get<std::string>(*this);
|
||||
}
|
||||
#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
|
||||
boost::string_ref const& as_boost_string_ref() const {
|
||||
return boost::get<boost::string_ref>(*this);
|
||||
}
|
||||
boost::string_ref& as_boost_string_ref() {
|
||||
return boost::get<boost::string_ref>(*this);
|
||||
}
|
||||
#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
|
||||
std::vector<char> const& as_vector_char() const {
|
||||
return boost::get<std::vector<char> >(*this);
|
||||
}
|
||||
std::vector<char>& as_vector_char() {
|
||||
return boost::get<std::vector<char> >(*this);
|
||||
}
|
||||
raw_ref const& as_raw_ref() const {
|
||||
return boost::get<raw_ref>(*this);
|
||||
}
|
||||
ext const& as_ext() const {
|
||||
return boost::get<ext>(*this);
|
||||
}
|
||||
ext& as_ext() {
|
||||
return boost::get<ext>(*this);
|
||||
}
|
||||
ext_ref const& as_ext_ref() const {
|
||||
return boost::get<ext_ref>(*this);
|
||||
}
|
||||
std::vector<basic_variant<STR, BIN, EXT> > const& as_vector() const {
|
||||
return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
std::vector<basic_variant<STR, BIN, EXT> >& as_vector() {
|
||||
return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > const& as_map() const {
|
||||
return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> >& as_map() {
|
||||
return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > const& as_multimap() const {
|
||||
return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> >& as_multimap() {
|
||||
return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
|
||||
}
|
||||
private:
|
||||
template <typename T>
|
||||
void int_init(T v) {
|
||||
@@ -252,6 +237,19 @@ private:
|
||||
static_cast<base&>(*this) = uint64_t(v);
|
||||
}
|
||||
}
|
||||
void double_init(double v) {
|
||||
if (v == v) { // check for nan
|
||||
if (v >= 0 && v <= double(std::numeric_limits<uint64_t>::max()) && v == double(uint64_t(v))) {
|
||||
static_cast<base&>(*this) = uint64_t(v);
|
||||
return;
|
||||
}
|
||||
else if (v < 0 && v >= double(std::numeric_limits<int64_t>::min()) && v == double(int64_t(v))) {
|
||||
static_cast<base&>(*this) = int64_t(v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
static_cast<base&>(*this) = v;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename STR, typename BIN, typename EXT>
|
||||
|
@@ -11,17 +11,14 @@
|
||||
#ifndef MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
|
||||
#define MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
|
||||
|
||||
#if !defined(MSGPACK_NO_BOOST)
|
||||
|
||||
#include "msgpack/versioning.hpp"
|
||||
#include "msgpack/adaptor/adaptor_base.hpp"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/adaptor/check_container_size.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
/// @cond
|
||||
@@ -30,6 +27,113 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||
|
||||
namespace adaptor {
|
||||
|
||||
namespace detail {
|
||||
template <
|
||||
typename Target,
|
||||
typename Source,
|
||||
bool target_is_signed = std::is_signed<Target>::value,
|
||||
bool source_is_signed = std::is_signed<Source>::value,
|
||||
typename = typename std::enable_if<
|
||||
std::is_integral<Target>::value &&
|
||||
std::is_integral<Source>::value
|
||||
>::type
|
||||
>
|
||||
struct would_underflow {
|
||||
// The default case includes the cases that Source being unsigned, and since Source
|
||||
// is unsigned, no underflow can happen
|
||||
would_underflow(Source) : value{false} {}
|
||||
bool value;
|
||||
};
|
||||
|
||||
template <typename Target, typename Source>
|
||||
struct would_underflow<Target, Source, false, true> {
|
||||
// When Source is signed and Target is unsigned, we only need to compare with 0 to
|
||||
// detect underflow, this works correctly and also avoids warnings from the compiler
|
||||
would_underflow(Source source) : value{source < 0} {}
|
||||
bool value;
|
||||
};
|
||||
template <typename Target, typename Source>
|
||||
struct would_underflow<Target, Source, true, true> {
|
||||
// When Source and Target are signed, the promotion rules apply sensibly so we do
|
||||
// not need to do anything
|
||||
would_underflow(Source source)
|
||||
: value{source < std::numeric_limits<Target>::min()} {}
|
||||
bool value;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Target,
|
||||
typename Source,
|
||||
bool target_is_signed = std::is_signed<Target>::value,
|
||||
bool source_is_signed = std::is_signed<Source>::value,
|
||||
typename = typename std::enable_if<
|
||||
std::is_integral<Target>::value &&
|
||||
std::is_integral<Source>::value
|
||||
>::type
|
||||
>
|
||||
struct would_overflow {
|
||||
// The default case is Source and Target having the same signedness, the promotion
|
||||
// rule also apply sensibly here so nothing special needs to be done
|
||||
would_overflow(Source source)
|
||||
: value{source > std::numeric_limits<Target>::max()} {}
|
||||
bool value;
|
||||
};
|
||||
template <typename Target, typename Source>
|
||||
struct would_overflow <Target, Source, false, true> {
|
||||
// When Target is unsigned and Source is signed, we cannot rely on the promotion
|
||||
// rule.
|
||||
would_overflow(Source source)
|
||||
: value{
|
||||
sizeof(Target) >= sizeof(Source)
|
||||
// Given Source is signed, Target being unsigned and having at least the
|
||||
// same size makes impossible to overflow
|
||||
? false
|
||||
// Source being larger than Target makes it safe to cast the maximum value
|
||||
// of Target to Source
|
||||
: source > static_cast<Source>(std::numeric_limits<Target>::max())
|
||||
} {}
|
||||
bool value;
|
||||
};
|
||||
template <typename Target, typename Source>
|
||||
struct would_overflow <Target, Source, true, false> {
|
||||
// When Target is signed and Source is unsigned, we cannot rely on the promotion
|
||||
// rule.
|
||||
would_overflow(Source source)
|
||||
: value{
|
||||
sizeof(Target) > sizeof(Source)
|
||||
// Target being larger than Source makes it impossible to overflow
|
||||
? false
|
||||
// Source being unsigned and having at least the size of Target makes it
|
||||
// safe to cast the maximum value of Target to Source
|
||||
: source > static_cast<Source>(std::numeric_limits<Target>::max())
|
||||
} {}
|
||||
bool value;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Target,
|
||||
typename Source,
|
||||
typename = typename std::enable_if<
|
||||
std::is_integral<Target>::value &&
|
||||
std::is_integral<Source>::value
|
||||
>::type
|
||||
>
|
||||
Target integral_cast(Source source) {
|
||||
if (would_underflow<Target, Source>(source).value) {
|
||||
throw std::underflow_error{
|
||||
"casting from Source to Target causes an underflow error"
|
||||
};
|
||||
}
|
||||
if(would_overflow<Target, Source>(source).value) {
|
||||
throw std::overflow_error{
|
||||
"casting from Source to Target causes an overflow error"
|
||||
};
|
||||
}
|
||||
|
||||
return static_cast<Target>(source);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Clock, typename Duration>
|
||||
struct as<std::chrono::time_point<Clock, Duration>> {
|
||||
typename std::chrono::time_point<Clock, Duration> operator()(msgpack::object const& o) const {
|
||||
@@ -45,7 +149,7 @@ struct as<std::chrono::time_point<Clock, Duration>> {
|
||||
case 8: {
|
||||
uint64_t value;
|
||||
_msgpack_load64(uint64_t, o.via.ext.data(), &value);
|
||||
uint32_t nanosec = boost::numeric_cast<uint32_t>(value >> 34);
|
||||
uint32_t nanosec = detail::integral_cast<uint32_t>(value >> 34);
|
||||
uint64_t sec = value & 0x00000003ffffffffLL;
|
||||
tp += std::chrono::duration_cast<Duration>(
|
||||
std::chrono::nanoseconds(nanosec));
|
||||
@@ -69,7 +173,7 @@ struct as<std::chrono::time_point<Clock, Duration>> {
|
||||
else {
|
||||
++sec;
|
||||
tp += std::chrono::seconds(sec);
|
||||
int64_t ns = boost::numeric_cast<int64_t>(nanosec) - 1000000000L;
|
||||
int64_t ns = detail::integral_cast<int64_t>(nanosec) - 1000000000L;
|
||||
tp += std::chrono::duration_cast<Duration>(
|
||||
std::chrono::nanoseconds(ns));
|
||||
}
|
||||
@@ -98,7 +202,7 @@ struct convert<std::chrono::time_point<Clock, Duration>> {
|
||||
case 8: {
|
||||
uint64_t value;
|
||||
_msgpack_load64(uint64_t, o.via.ext.data(), &value);
|
||||
uint32_t nanosec = boost::numeric_cast<uint32_t>(value >> 34);
|
||||
uint32_t nanosec = detail::integral_cast<uint32_t>(value >> 34);
|
||||
uint64_t sec = value & 0x00000003ffffffffLL;
|
||||
tp += std::chrono::duration_cast<Duration>(
|
||||
std::chrono::nanoseconds(nanosec));
|
||||
@@ -123,7 +227,7 @@ struct convert<std::chrono::time_point<Clock, Duration>> {
|
||||
else {
|
||||
++sec;
|
||||
tp += std::chrono::seconds(sec);
|
||||
int64_t ns = boost::numeric_cast<int64_t>(nanosec) - 1000000000L;
|
||||
int64_t ns = detail::integral_cast<int64_t>(nanosec) - 1000000000L;
|
||||
tp += std::chrono::duration_cast<Duration>(
|
||||
std::chrono::nanoseconds(ns));
|
||||
}
|
||||
@@ -142,7 +246,7 @@ template <typename Clock, typename Duration>
|
||||
struct pack<std::chrono::time_point<Clock, Duration>> {
|
||||
template <typename Stream>
|
||||
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, std::chrono::time_point<Clock, Duration> const& v) const {
|
||||
int64_t count = boost::numeric_cast<int64_t>(v.time_since_epoch().count());
|
||||
int64_t count = detail::integral_cast<int64_t>(v.time_since_epoch().count());
|
||||
int64_t nano_num =
|
||||
Duration::period::ratio::num *
|
||||
(1000000000L / Duration::period::ratio::den);
|
||||
@@ -158,11 +262,11 @@ struct pack<std::chrono::time_point<Clock, Duration>> {
|
||||
/ Duration::period::ratio::den;
|
||||
|
||||
if ((sec >> 34) == 0) {
|
||||
uint64_t data64 = (boost::numeric_cast<uint64_t>(nanosec) << 34) | boost::numeric_cast<uint64_t>(sec);
|
||||
uint64_t data64 = (detail::integral_cast<uint64_t>(nanosec) << 34) | detail::integral_cast<uint64_t>(sec);
|
||||
if ((data64 & 0xffffffff00000000L) == 0) {
|
||||
// timestamp 32
|
||||
o.pack_ext(4, -1);
|
||||
uint32_t data32 = boost::numeric_cast<uint32_t>(data64);
|
||||
uint32_t data32 = detail::integral_cast<uint32_t>(data64);
|
||||
char buf[4];
|
||||
_msgpack_store32(buf, data32);
|
||||
o.pack_ext_body(buf, 4);
|
||||
@@ -181,7 +285,7 @@ struct pack<std::chrono::time_point<Clock, Duration>> {
|
||||
char buf[12];
|
||||
|
||||
|
||||
_msgpack_store32(&buf[0], boost::numeric_cast<uint32_t>(nanosec));
|
||||
_msgpack_store32(&buf[0], detail::integral_cast<uint32_t>(nanosec));
|
||||
_msgpack_store64(&buf[4], sec);
|
||||
o.pack_ext_body(buf, 12);
|
||||
}
|
||||
@@ -192,7 +296,7 @@ struct pack<std::chrono::time_point<Clock, Duration>> {
|
||||
template <typename Clock, typename Duration>
|
||||
struct object_with_zone<std::chrono::time_point<Clock, Duration>> {
|
||||
void operator()(msgpack::object::with_zone& o, const std::chrono::time_point<Clock, Duration>& v) const {
|
||||
int64_t count = boost::numeric_cast<int64_t>(v.time_since_epoch().count());
|
||||
int64_t count = detail::integral_cast<int64_t>(v.time_since_epoch().count());
|
||||
|
||||
int64_t nano_num =
|
||||
Duration::period::ratio::num *
|
||||
@@ -208,14 +312,14 @@ struct object_with_zone<std::chrono::time_point<Clock, Duration>> {
|
||||
* Duration::period::ratio::num
|
||||
/ Duration::period::ratio::den;
|
||||
if ((sec >> 34) == 0) {
|
||||
uint64_t data64 = (boost::numeric_cast<uint64_t>(nanosec) << 34) | boost::numeric_cast<uint64_t>(sec);
|
||||
uint64_t data64 = (detail::integral_cast<uint64_t>(nanosec) << 34) | detail::integral_cast<uint64_t>(sec);
|
||||
if ((data64 & 0xffffffff00000000L) == 0) {
|
||||
// timestamp 32
|
||||
o.type = msgpack::type::EXT;
|
||||
o.via.ext.size = 4;
|
||||
char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
|
||||
p[0] = static_cast<char>(-1);
|
||||
uint32_t data32 = boost::numeric_cast<uint32_t>(data64);
|
||||
uint32_t data32 = detail::integral_cast<uint32_t>(data64);
|
||||
_msgpack_store32(&p[1], data32);
|
||||
o.via.ext.ptr = p;
|
||||
}
|
||||
@@ -235,7 +339,7 @@ struct object_with_zone<std::chrono::time_point<Clock, Duration>> {
|
||||
o.via.ext.size = 12;
|
||||
char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
|
||||
p[0] = static_cast<char>(-1);
|
||||
_msgpack_store32(&p[1], boost::numeric_cast<uint32_t>(nanosec));
|
||||
_msgpack_store32(&p[1], detail::integral_cast<uint32_t>(nanosec));
|
||||
_msgpack_store64(&p[1 + 4], sec);
|
||||
o.via.ext.ptr = p;
|
||||
}
|
||||
@@ -250,6 +354,4 @@ struct object_with_zone<std::chrono::time_point<Clock, Duration>> {
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif // !defined(MSGPACK_NO_BOOST)
|
||||
|
||||
#endif // MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
|
||||
|
151
include/msgpack/v1/adaptor/cpp17/variant.hpp
Normal file
151
include/msgpack/v1/adaptor/cpp17/variant.hpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2023 Uy Ha
|
||||
//
|
||||
// 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_VARIANT_HPP
|
||||
#define MSGPACK_V1_TYPE_VARIANT_HPP
|
||||
|
||||
#if defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
#include "msgpack/cpp_version.hpp"
|
||||
|
||||
#if MSGPACK_CPP_VERSION >= 201703
|
||||
|
||||
#include "msgpack/adaptor/adaptor_base.hpp"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/versioning.hpp"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace msgpack {
|
||||
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||
namespace adaptor {
|
||||
namespace detail {
|
||||
template <
|
||||
typename Variant,
|
||||
typename T,
|
||||
typename... Ts,
|
||||
std::size_t current_index,
|
||||
std::size_t... indices
|
||||
>
|
||||
Variant construct_variant(
|
||||
std::size_t index,
|
||||
msgpack::object& object,
|
||||
std::index_sequence<current_index, indices...>
|
||||
) {
|
||||
if constexpr(sizeof...(Ts) == 0) {
|
||||
return object.as<T>();
|
||||
}
|
||||
else {
|
||||
if (index == current_index) {
|
||||
return object.as<T>();
|
||||
}
|
||||
return construct_variant<Variant, Ts...>(
|
||||
index,
|
||||
object,
|
||||
std::index_sequence<indices...>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct object_variant_overload {
|
||||
object_variant_overload(msgpack::object& obj, msgpack::zone& zone)
|
||||
: obj{obj}
|
||||
, zone{zone} {}
|
||||
|
||||
template<typename T>
|
||||
void operator()(T const& value) {
|
||||
obj = msgpack::object(value, zone);
|
||||
}
|
||||
|
||||
msgpack::object& obj;
|
||||
msgpack::zone& zone;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Ts>
|
||||
struct as<std::variant<Ts...>, typename std::enable_if<(msgpack::has_as<Ts>::value && ...)>::type> {
|
||||
std::variant<Ts...> operator()(msgpack::object const& o) const {
|
||||
if ( o.type != msgpack::type::ARRAY
|
||||
|| o.via.array.size != 2
|
||||
|| o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER
|
||||
|| o.via.array.ptr[0].via.u64 >= sizeof...(Ts)) {
|
||||
throw msgpack::type_error{};
|
||||
}
|
||||
|
||||
return detail::construct_variant<std::variant<Ts...>, Ts...>(
|
||||
o.via.array.ptr[0].as<std::size_t>(),
|
||||
o.via.array.ptr[1],
|
||||
std::make_index_sequence<sizeof...(Ts)>()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct convert<std::variant<Ts...>> {
|
||||
msgpack::object const& operator()(msgpack::object const& o, std::variant<Ts...>& v) const {
|
||||
if ( o.type != msgpack::type::ARRAY
|
||||
|| o.via.array.size != 2
|
||||
|| o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER
|
||||
|| o.via.array.ptr[0].via.u64 >= sizeof...(Ts)) {
|
||||
throw msgpack::type_error{};
|
||||
}
|
||||
|
||||
v = detail::construct_variant<std::variant<Ts...>, Ts...>(
|
||||
o.via.array.ptr[0].as<std::size_t>(),
|
||||
o.via.array.ptr[1],
|
||||
std::make_index_sequence<sizeof...(Ts)>()
|
||||
);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
struct pack<std::variant<Ts...>>{
|
||||
template<typename Stream>
|
||||
msgpack::packer<Stream>& operator()(
|
||||
msgpack::packer<Stream>& o,
|
||||
std::variant<Ts...> const& v
|
||||
) const {
|
||||
o.pack_array(2);
|
||||
o.pack_uint64(v.index());
|
||||
std::visit([&o](auto const& value){o.pack(value);}, v);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename... Ts>
|
||||
struct object_with_zone<std::variant<Ts...>> {
|
||||
void operator()(
|
||||
msgpack::object::with_zone& o,
|
||||
std::variant<Ts...> const& v
|
||||
) const {
|
||||
msgpack::object *p =
|
||||
static_cast<msgpack::object *>(
|
||||
o.zone.allocate_align(
|
||||
sizeof(msgpack::object) * 2,
|
||||
MSGPACK_ZONE_ALIGNOF(msgpack::object)
|
||||
)
|
||||
);
|
||||
|
||||
o.type = msgpack::type::ARRAY;
|
||||
o.via.array.size = 2;
|
||||
o.via.array.ptr = p;
|
||||
o.via.array.ptr[0]= msgpack::object(v.index(), o.zone);
|
||||
std::visit(detail::object_variant_overload(o.via.array.ptr[1], o.zone), v);
|
||||
}
|
||||
};
|
||||
} // namespace adaptor
|
||||
}
|
||||
} // namespace msgpack
|
||||
|
||||
#endif // MSGPACK_CPP_VERSION >= 201703
|
||||
#endif // defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
#endif // MSGPACK_V1_TYPE_VARIANT_HPP
|
@@ -1,3 +1,3 @@
|
||||
#define MSGPACK_VERSION_MAJOR 6
|
||||
#define MSGPACK_VERSION_MINOR 0
|
||||
#define MSGPACK_VERSION_MINOR 1
|
||||
#define MSGPACK_VERSION_REVISION 0
|
||||
|
@@ -264,7 +264,7 @@ BOOST_AUTO_TEST_CASE(pack_convert_variant_float)
|
||||
BOOST_CHECK(val2.is_double());
|
||||
BOOST_CHECK(fabs(12.34 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_NO_THROW(boost::get<double>(val2));
|
||||
BOOST_CHECK(fabs(val2.as_double() - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(fabs(val1.as_double() - val2.as_double()) <= kEPS);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_variant_float)
|
||||
@@ -277,7 +277,8 @@ BOOST_AUTO_TEST_CASE(object_variant_float)
|
||||
BOOST_CHECK(val2.is_double());
|
||||
BOOST_CHECK(fabs(12.34 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_NO_THROW(boost::get<double>(val2));
|
||||
BOOST_CHECK(fabs(val2.as_double() - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(fabs(val1.as_double() - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_with_zone_variant_float)
|
||||
@@ -291,7 +292,116 @@ BOOST_AUTO_TEST_CASE(object_with_zone_variant_float)
|
||||
BOOST_CHECK(val2.is_double());
|
||||
BOOST_CHECK(fabs(12.34 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_NO_THROW(boost::get<double>(val2));
|
||||
BOOST_CHECK(fabs(val2.as_double() - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(fabs(val1.as_double() - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(pack_convert_variant_float_zero_atdp_positive)
|
||||
{
|
||||
std::stringstream ss;
|
||||
msgpack::type::variant val1 = 12.0;
|
||||
BOOST_CHECK(val1.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), 12);
|
||||
BOOST_CHECK(fabs(12.0 - val1.as_double()) <= kEPS);
|
||||
|
||||
msgpack::pack(ss, val1);
|
||||
|
||||
std::string const& str = ss.str();
|
||||
msgpack::object_handle oh =
|
||||
msgpack::unpack(str.data(), str.size());
|
||||
msgpack::type::variant val2 = oh.get().as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_uint64_t(), 12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<uint64_t>(val2));
|
||||
BOOST_CHECK(fabs(12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), val2.as_uint64_t());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_variant_float_zero_atdp_positive)
|
||||
{
|
||||
msgpack::type::variant val1 = 12.0;
|
||||
BOOST_CHECK(val1.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), 12);
|
||||
BOOST_CHECK(fabs(12.0 - val1.as_double()) <= kEPS);
|
||||
msgpack::object obj(val1);
|
||||
msgpack::type::variant val2 = obj.as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_uint64_t(), 12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<uint64_t>(val2));
|
||||
BOOST_CHECK(fabs(12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), val2.as_uint64_t());
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_with_zone_variant_float_zero_atdp_positive)
|
||||
{
|
||||
msgpack::zone z;
|
||||
msgpack::type::variant val1 = 12.0;
|
||||
BOOST_CHECK(val1.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), 12);
|
||||
BOOST_CHECK(fabs(12.0 - val1.as_double()) <= kEPS);
|
||||
msgpack::object obj(val1, z);
|
||||
msgpack::type::variant val2 = obj.as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_uint64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_uint64_t(), 12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<uint64_t>(val2));
|
||||
BOOST_CHECK_EQUAL(val1.as_uint64_t(), val2.as_uint64_t());
|
||||
BOOST_CHECK(fabs(12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(pack_convert_variant_float_zero_atdp_negative)
|
||||
{
|
||||
std::stringstream ss;
|
||||
msgpack::type::variant val1 = -12.0;
|
||||
BOOST_CHECK(val1.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), -12);
|
||||
BOOST_CHECK(fabs(-12.0 - val1.as_double()) <= kEPS);
|
||||
|
||||
msgpack::pack(ss, val1);
|
||||
|
||||
std::string const& str = ss.str();
|
||||
msgpack::object_handle oh =
|
||||
msgpack::unpack(str.data(), str.size());
|
||||
msgpack::type::variant val2 = oh.get().as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_int64_t(), -12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<int64_t>(val2));
|
||||
BOOST_CHECK(fabs(-12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), val2.as_int64_t());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_variant_float_zero_atdp_negative)
|
||||
{
|
||||
msgpack::type::variant val1 = -12.0;
|
||||
BOOST_CHECK(val1.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), -12);
|
||||
BOOST_CHECK(fabs(-12.0 - val1.as_double()) <= kEPS);
|
||||
msgpack::object obj(val1);
|
||||
msgpack::type::variant val2 = obj.as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_int64_t(), -12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<int64_t>(val2));
|
||||
BOOST_CHECK(fabs(-12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), val2.as_int64_t());
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(object_with_zone_variant_float_zero_atdp_negative)
|
||||
{
|
||||
msgpack::zone z;
|
||||
msgpack::type::variant val1 = -12.0;
|
||||
BOOST_CHECK(val1.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), -12);
|
||||
BOOST_CHECK(fabs(-12.0 - val1.as_double()) <= kEPS);
|
||||
msgpack::object obj(val1, z);
|
||||
msgpack::type::variant val2 = obj.as<msgpack::type::variant>();
|
||||
BOOST_CHECK(val2.is_int64_t());
|
||||
BOOST_CHECK_EQUAL(val2.as_int64_t(), -12);
|
||||
BOOST_CHECK_NO_THROW(boost::get<int64_t>(val2));
|
||||
BOOST_CHECK(fabs(-12.0 - val2.as_double()) <= kEPS);
|
||||
BOOST_CHECK_EQUAL(val1.as_int64_t(), val2.as_int64_t());
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
// str
|
||||
|
@@ -252,6 +252,9 @@ struct equal_to : std::equal_to<Key> {
|
||||
template <class Key>
|
||||
struct set_allocator : std::allocator<Key> {
|
||||
using std::allocator<Key>::allocator;
|
||||
|
||||
template<class U>
|
||||
struct rebind { using other = set_allocator<U>; };
|
||||
};
|
||||
|
||||
// C++ named requirement Allocator implies that the first template type
|
||||
@@ -262,6 +265,9 @@ struct set_allocator : std::allocator<Key> {
|
||||
template <typename KeyValuePair>
|
||||
struct map_allocator_impl : std::allocator<KeyValuePair> {
|
||||
using std::allocator<KeyValuePair>::allocator;
|
||||
|
||||
template<class U>
|
||||
struct rebind { using other = map_allocator_impl<U>; };
|
||||
};
|
||||
|
||||
template <class Key, class T>
|
||||
@@ -270,6 +276,9 @@ using map_allocator = map_allocator_impl<std::pair<const Key, T>>;
|
||||
template <class T>
|
||||
struct allocator : std::allocator<T> {
|
||||
using std::allocator<T>::allocator;
|
||||
|
||||
template<class U>
|
||||
struct rebind { using other = allocator<U>; };
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -861,8 +870,6 @@ BOOST_AUTO_TEST_CASE(no_def_con_array_simple_buffer)
|
||||
BOOST_CHECK(val1 == val2);
|
||||
}
|
||||
|
||||
#if !defined(MSGPACK_NO_BOOST)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(system_clock)
|
||||
{
|
||||
std::chrono::system_clock::time_point val1;
|
||||
@@ -1428,8 +1435,6 @@ BOOST_AUTO_TEST_CASE(high_resolution_clock_impl_now)
|
||||
BOOST_CHECK(val1 == val3);
|
||||
}
|
||||
|
||||
#endif // !defined(MSGPACK_NO_BOOST)
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(timespec_pack_convert_zero)
|
||||
{
|
||||
|
@@ -461,4 +461,30 @@ BOOST_AUTO_TEST_CASE(carray_byte_object_with_zone)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(variant_pack_unpack_as) {
|
||||
std::stringstream ss;
|
||||
std::variant<bool, int, float, double> val1{1.0};
|
||||
msgpack::pack(ss, val1);
|
||||
std::string const& str = ss.str();
|
||||
msgpack::object_handle oh =
|
||||
msgpack::unpack(str.data(), str.size());
|
||||
std::variant<bool, int, float, double> val2 =
|
||||
oh.get().as<std::variant<bool, int, float, double> >();
|
||||
BOOST_CHECK(val1 == val2);
|
||||
BOOST_CHECK_THROW((oh.get().as<std::variant<bool>>()), msgpack::type_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(variant_with_zone) {
|
||||
msgpack::zone z;
|
||||
std::variant<bool, int, float, double> val1{1.0};
|
||||
msgpack::object obj(val1, z);
|
||||
std::variant<bool, int, float, double> val2 = obj.as<std::variant<bool, int, float, double>>();
|
||||
BOOST_CHECK(val1 == val2);
|
||||
BOOST_CHECK_THROW((obj.as<std::variant<bool>>()), msgpack::type_error);
|
||||
}
|
||||
|
||||
#endif // defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
#endif // MSGPACK_CPP_VERSION >= 201703
|
||||
|
Reference in New Issue
Block a user