mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-15 15:16:51 +02:00
Added timespec support for C++11 or later.
This commit is contained in:
@@ -190,6 +190,7 @@ IF (MSGPACK_ENABLE_CXX)
|
|||||||
include/msgpack/adaptor/cpp11/forward_list.hpp
|
include/msgpack/adaptor/cpp11/forward_list.hpp
|
||||||
include/msgpack/adaptor/cpp11/reference_wrapper.hpp
|
include/msgpack/adaptor/cpp11/reference_wrapper.hpp
|
||||||
include/msgpack/adaptor/cpp11/shared_ptr.hpp
|
include/msgpack/adaptor/cpp11/shared_ptr.hpp
|
||||||
|
include/msgpack/adaptor/cpp11/timespec.hpp
|
||||||
include/msgpack/adaptor/cpp11/tuple.hpp
|
include/msgpack/adaptor/cpp11/tuple.hpp
|
||||||
include/msgpack/adaptor/cpp11/unique_ptr.hpp
|
include/msgpack/adaptor/cpp11/unique_ptr.hpp
|
||||||
include/msgpack/adaptor/cpp11/unordered_map.hpp
|
include/msgpack/adaptor/cpp11/unordered_map.hpp
|
||||||
@@ -552,6 +553,7 @@ IF (MSGPACK_ENABLE_CXX)
|
|||||||
include/msgpack/v1/adaptor/cpp11/forward_list.hpp
|
include/msgpack/v1/adaptor/cpp11/forward_list.hpp
|
||||||
include/msgpack/v1/adaptor/cpp11/reference_wrapper.hpp
|
include/msgpack/v1/adaptor/cpp11/reference_wrapper.hpp
|
||||||
include/msgpack/v1/adaptor/cpp11/shared_ptr.hpp
|
include/msgpack/v1/adaptor/cpp11/shared_ptr.hpp
|
||||||
|
include/msgpack/v1/adaptor/cpp11/timespec.hpp
|
||||||
include/msgpack/v1/adaptor/cpp11/tuple.hpp
|
include/msgpack/v1/adaptor/cpp11/tuple.hpp
|
||||||
include/msgpack/v1/adaptor/cpp11/unique_ptr.hpp
|
include/msgpack/v1/adaptor/cpp11/unique_ptr.hpp
|
||||||
include/msgpack/v1/adaptor/cpp11/unordered_map.hpp
|
include/msgpack/v1/adaptor/cpp11/unordered_map.hpp
|
||||||
|
16
include/msgpack/adaptor/cpp11/timespec.hpp
Normal file
16
include/msgpack/adaptor/cpp11/timespec.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// MessagePack for C++ static resolution routine
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019 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_CPP11_TIMESPEC_HPP
|
||||||
|
#define MSGPACK_TYPE_CPP11_TIMESPEC_HPP
|
||||||
|
|
||||||
|
#include "msgpack/v1/adaptor/cpp11/timespec.hpp"
|
||||||
|
|
||||||
|
#endif // MSGPACK_TYPE_CPP11_TIMESPEC_HPP
|
@@ -39,6 +39,7 @@
|
|||||||
#include "adaptor/cpp11/forward_list.hpp"
|
#include "adaptor/cpp11/forward_list.hpp"
|
||||||
#include "adaptor/cpp11/reference_wrapper.hpp"
|
#include "adaptor/cpp11/reference_wrapper.hpp"
|
||||||
#include "adaptor/cpp11/shared_ptr.hpp"
|
#include "adaptor/cpp11/shared_ptr.hpp"
|
||||||
|
#include "adaptor/cpp11/timespec.hpp"
|
||||||
#include "adaptor/cpp11/tuple.hpp"
|
#include "adaptor/cpp11/tuple.hpp"
|
||||||
#include "adaptor/cpp11/unique_ptr.hpp"
|
#include "adaptor/cpp11/unique_ptr.hpp"
|
||||||
#include "adaptor/cpp11/unordered_map.hpp"
|
#include "adaptor/cpp11/unordered_map.hpp"
|
||||||
|
140
include/msgpack/v1/adaptor/cpp11/timespec.hpp
Normal file
140
include/msgpack/v1/adaptor/cpp11/timespec.hpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// MessagePack for C++ static resolution routine
|
||||||
|
//
|
||||||
|
// Copyright (C) 2018 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_CPP11_TIMESPEC_HPP
|
||||||
|
#define MSGPACK_V1_TYPE_CPP11_TIMESPEC_HPP
|
||||||
|
|
||||||
|
#include "msgpack/versioning.hpp"
|
||||||
|
#include "msgpack/adaptor/adaptor_base.hpp"
|
||||||
|
#include "msgpack/object.hpp"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
namespace msgpack {
|
||||||
|
|
||||||
|
/// @cond
|
||||||
|
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
|
namespace adaptor {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct convert<timespec> {
|
||||||
|
msgpack::object const& operator()(msgpack::object const& o, timespec& v) const {
|
||||||
|
if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
|
||||||
|
if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
|
||||||
|
switch(o.via.ext.size) {
|
||||||
|
case 4: {
|
||||||
|
uint32_t sec;
|
||||||
|
_msgpack_load32(uint32_t, o.via.ext.data(), &sec);
|
||||||
|
v.tv_sec = static_cast<decltype(v.tv_sec)>(sec);
|
||||||
|
v.tv_nsec = 0;
|
||||||
|
} break;
|
||||||
|
case 8: {
|
||||||
|
uint64_t value;
|
||||||
|
_msgpack_load64(uint64_t, o.via.ext.data(), &value);
|
||||||
|
v.tv_sec = static_cast<decltype(v.tv_sec)>(value & 0x00000003ffffffffLL);
|
||||||
|
v.tv_nsec= static_cast<decltype(v.tv_nsec)>(value >> 34);
|
||||||
|
} break;
|
||||||
|
case 12: {
|
||||||
|
uint32_t nanosec;
|
||||||
|
_msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
|
||||||
|
int64_t sec;
|
||||||
|
_msgpack_load64(int64_t, o.via.ext.data() + 4, &sec);
|
||||||
|
v.tv_sec = static_cast<decltype(v.tv_sec)>(sec);
|
||||||
|
v.tv_nsec = static_cast<decltype(v.tv_nsec)>(nanosec);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
throw msgpack::type_error();
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pack<timespec> {
|
||||||
|
template <typename Stream>
|
||||||
|
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const timespec& v) const {
|
||||||
|
if ((static_cast<uint64_t>(v.tv_sec) >> 34) == 0) {
|
||||||
|
uint64_t data64 = (static_cast<uint64_t>(v.tv_nsec) << 34) | static_cast<uint64_t>(v.tv_sec);
|
||||||
|
if ((data64 & 0xffffffff00000000L) == 0) {
|
||||||
|
// timestamp 32
|
||||||
|
o.pack_ext(4, -1);
|
||||||
|
uint32_t data32 = static_cast<uint32_t>(data64);
|
||||||
|
char buf[4];
|
||||||
|
_msgpack_store32(buf, data32);
|
||||||
|
o.pack_ext_body(buf, 4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// timestamp 64
|
||||||
|
o.pack_ext(8, -1);
|
||||||
|
char buf[8];
|
||||||
|
_msgpack_store64(buf, data64);
|
||||||
|
o.pack_ext_body(buf, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// timestamp 96
|
||||||
|
o.pack_ext(12, -1);
|
||||||
|
char buf[12];
|
||||||
|
_msgpack_store32(&buf[0], static_cast<uint32_t>(v.tv_nsec));
|
||||||
|
_msgpack_store64(&buf[4], v.tv_sec);
|
||||||
|
o.pack_ext_body(buf, 12);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct object_with_zone<timespec> {
|
||||||
|
void operator()(msgpack::object::with_zone& o, const timespec& v) const {
|
||||||
|
if ((static_cast<uint64_t>(v.tv_sec) >> 34) == 0) {
|
||||||
|
uint64_t data64 = (static_cast<uint64_t>(v.tv_nsec) << 34) | static_cast<uint64_t>(v.tv_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 = static_cast<uint32_t>(data64);
|
||||||
|
_msgpack_store32(&p[1], data32);
|
||||||
|
o.via.ext.ptr = p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// timestamp 64
|
||||||
|
o.type = msgpack::type::EXT;
|
||||||
|
o.via.ext.size = 8;
|
||||||
|
char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
|
||||||
|
p[0] = static_cast<char>(-1);
|
||||||
|
_msgpack_store64(&p[1], data64);
|
||||||
|
o.via.ext.ptr = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// timestamp 96
|
||||||
|
o.type = msgpack::type::EXT;
|
||||||
|
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], static_cast<uint32_t>(v.tv_nsec));
|
||||||
|
_msgpack_store64(&p[1 + 4], v.tv_sec);
|
||||||
|
o.via.ext.ptr = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace adaptor
|
||||||
|
|
||||||
|
/// @cond
|
||||||
|
} // MSGPACK_API_VERSION_NAMESPACE(v1)
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
|
} // namespace msgpack
|
||||||
|
|
||||||
|
#endif // MSGPACK_V1_TYPE_CPP11_TIMESPEC_HPP
|
@@ -1049,4 +1049,158 @@ TEST(MSGPACK_CHRONO, system_clock_impl_now)
|
|||||||
EXPECT_EQ(val1, val3);
|
EXPECT_EQ(val1, val3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_zero)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ 0, 0 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xd6));
|
||||||
|
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_zero)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ 0, 0 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_32bit_sec)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ 0xffffffffUL, 0 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xd6));
|
||||||
|
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_32bit_sec)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ 0xffffffffUL, 0 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_max_nano)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ 0, 999999999 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xd7));
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_max_nano)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ 0, 999999999 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_34bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
if (sizeof(decltype(std::declval<timespec>().tv_sec)) <= 4) return;
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ static_cast<decltype(std::declval<timespec>().tv_sec)>(0x3ffffffffULL), 999999999 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xd7));
|
||||||
|
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_34bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
if (sizeof(decltype(std::declval<timespec>().tv_sec)) <= 4) return;
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ static_cast<decltype(std::declval<timespec>().tv_sec)>(0x3ffffffffULL), 999999999 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_35bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
if (sizeof(decltype(std::declval<timespec>().tv_sec)) <= 4) return;
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ static_cast<decltype(std::declval<timespec>().tv_sec)>(0x7ffffffffULL), 999999999 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xc7));
|
||||||
|
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_35bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
if (sizeof(decltype(std::declval<timespec>().tv_sec)) <= 4) return;
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ static_cast<decltype(std::declval<timespec>().tv_sec)>(0x7ffffffffULL), 999999999 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_pack_convert_64bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
timespec val1{ std::numeric_limits<decltype(std::declval<timespec>().tv_sec)>::max(), 999999999 };
|
||||||
|
|
||||||
|
msgpack::pack(ss, val1);
|
||||||
|
EXPECT_EQ(ss.str().data()[0], static_cast<char>(0xc7));
|
||||||
|
|
||||||
|
msgpack::object_handle oh;
|
||||||
|
msgpack::unpack(oh, ss.str().data(), ss.str().size());
|
||||||
|
timespec val2 = oh.get().as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MSGPACK_TIMESPEC, timespec_object_with_zone_64bit_sec_max_nano)
|
||||||
|
{
|
||||||
|
msgpack::zone z;
|
||||||
|
timespec val1{ std::numeric_limits<decltype(std::declval<timespec>().tv_sec)>::max(), 999999999 };
|
||||||
|
msgpack::object obj(val1, z);
|
||||||
|
timespec val2 = obj.as<timespec>();
|
||||||
|
EXPECT_EQ(val1.tv_sec, val2.tv_sec);
|
||||||
|
EXPECT_EQ(val1.tv_nsec, val2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // !defined(MSGPACK_USE_CPP03)
|
#endif // !defined(MSGPACK_USE_CPP03)
|
||||||
|
Reference in New Issue
Block a user