Improved clock adaptor.

This commit is contained in:
Takatoshi Kondo 2020-06-14 18:46:44 +09:00
parent c7b7e745b3
commit 4629583662

View File

@ -25,13 +25,13 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor {
namespace detail {
template <typename T>
typename T::time_point chrono_as(msgpack::object const& o) {
template <typename Clock>
struct as<std::chrono::time_point<Clock>> {
typename std::chrono::time_point<Clock> operator()(msgpack::object const& o) const {
using duration_t = typename std::chrono::time_point<Clock>::duration;
if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
typename T::time_point tp;
std::chrono::time_point<Clock> tp;
switch(o.via.ext.size) {
case 4: {
uint32_t sec;
@ -43,7 +43,7 @@ typename T::time_point chrono_as(msgpack::object const& o) {
_msgpack_load64(uint64_t, o.via.ext.data(), &value);
uint32_t nanosec = static_cast<uint32_t>(value >> 34);
uint64_t sec = value & 0x00000003ffffffffLL;
tp += std::chrono::duration_cast<typename T::duration>(
tp += std::chrono::duration_cast<duration_t>(
std::chrono::nanoseconds(nanosec));
tp += std::chrono::seconds(sec);
} break;
@ -52,7 +52,7 @@ typename T::time_point chrono_as(msgpack::object const& o) {
_msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
int64_t sec;
_msgpack_load64(int64_t, o.via.ext.data() + 4, &sec);
tp += std::chrono::duration_cast<typename T::duration>(
tp += std::chrono::duration_cast<duration_t>(
std::chrono::nanoseconds(nanosec));
tp += std::chrono::seconds(sec);
} break;
@ -60,13 +60,16 @@ typename T::time_point chrono_as(msgpack::object const& o) {
throw msgpack::type_error();
}
return tp;
}
}
};
template <typename T>
msgpack::object const& chrono_convert(msgpack::object const& o, typename T::time_point& v) {
template <typename Clock>
struct convert<std::chrono::time_point<Clock>> {
msgpack::object const& operator()(msgpack::object const& o, std::chrono::time_point<Clock>& v) const {
using duration_t = typename std::chrono::time_point<Clock>::duration;
if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
typename T::time_point tp;
std::chrono::time_point<Clock> tp;
switch(o.via.ext.size) {
case 4: {
uint32_t sec;
@ -79,7 +82,7 @@ msgpack::object const& chrono_convert(msgpack::object const& o, typename T::time
_msgpack_load64(uint64_t, o.via.ext.data(), &value);
uint32_t nanosec = static_cast<uint32_t>(value >> 34);
uint64_t sec = value & 0x00000003ffffffffLL;
tp += std::chrono::duration_cast<typename T::duration>(
tp += std::chrono::duration_cast<duration_t>(
std::chrono::nanoseconds(nanosec));
tp += std::chrono::seconds(sec);
v = tp;
@ -89,7 +92,7 @@ msgpack::object const& chrono_convert(msgpack::object const& o, typename T::time
_msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
int64_t sec;
_msgpack_load64(int64_t, o.via.ext.data() + 4, &sec);
tp += std::chrono::duration_cast<typename T::duration>(
tp += std::chrono::duration_cast<duration_t>(
std::chrono::nanoseconds(nanosec));
tp += std::chrono::seconds(sec);
v = tp;
@ -98,15 +101,19 @@ msgpack::object const& chrono_convert(msgpack::object const& o, typename T::time
throw msgpack::type_error();
}
return o;
}
}
};
template <typename T, typename Stream>
msgpack::packer<Stream>& chrono_pack(msgpack::packer<Stream>& o, const typename T::time_point& v) {
template <typename Clock>
struct pack<std::chrono::time_point<Clock>> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, std::chrono::time_point<Clock> const& v) const {
using duration_t = typename std::chrono::time_point<Clock>::duration;
int64_t count = static_cast<int64_t>(v.time_since_epoch().count());
int64_t nano_num =
T::duration::period::ratio::num *
(1000000000 / T::duration::period::ratio::den);
duration_t::period::ratio::num *
(1000000000 / duration_t::period::ratio::den);
int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
int64_t sec = 0;
@ -115,8 +122,8 @@ msgpack::packer<Stream>& chrono_pack(msgpack::packer<Stream>& o, const typename
--sec;
}
sec += count
* T::duration::period::ratio::num
/ T::duration::period::ratio::den;
* duration_t::period::ratio::num
/ duration_t::period::ratio::den;
if ((sec >> 34) == 0) {
uint64_t data64 = (static_cast<uint64_t>(nanosec) << 34) | static_cast<uint64_t>(sec);
if ((data64 & 0xffffffff00000000L) == 0) {
@ -144,15 +151,18 @@ msgpack::packer<Stream>& chrono_pack(msgpack::packer<Stream>& o, const typename
o.pack_ext_body(buf, 12);
}
return o;
}
}
};
template <typename T>
void chrono_object_with_zone(msgpack::object::with_zone& o, const typename T::time_point& v) {
template <typename Clock>
struct object_with_zone<std::chrono::time_point<Clock>> {
void operator()(msgpack::object::with_zone& o, const std::chrono::time_point<Clock>& v) const {
using duration_t = typename std::chrono::time_point<Clock>::duration;
int64_t count = static_cast<int64_t>(v.time_since_epoch().count());
int64_t nano_num =
T::duration::period::ratio::num *
(1000000000 / T::duration::period::ratio::den);
duration_t::period::ratio::num *
(1000000000 / duration_t::period::ratio::den);
int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
int64_t sec = 0;
@ -161,8 +171,8 @@ void chrono_object_with_zone(msgpack::object::with_zone& o, const typename T::ti
--sec;
}
sec += count
* T::duration::period::ratio::num
/ T::duration::period::ratio::den;
* duration_t::period::ratio::num
/ duration_t::period::ratio::den;
if ((sec >> 34) == 0) {
uint64_t data64 = (static_cast<uint64_t>(nanosec) << 34) | static_cast<uint64_t>(sec);
if ((data64 & 0xffffffff00000000L) == 0) {
@ -195,128 +205,6 @@ void chrono_object_with_zone(msgpack::object::with_zone& o, const typename T::ti
_msgpack_store64(&p[1 + 4], sec);
o.via.ext.ptr = p;
}
}
} // namespace detail
template <>
struct as<std::chrono::system_clock::time_point> {
typename std::chrono::system_clock::time_point operator()(msgpack::object const& o) const {
return detail::chrono_as<std::chrono::system_clock>(o);
}
};
template <>
struct convert<std::chrono::system_clock::time_point> {
msgpack::object const& operator()(msgpack::object const& o, std::chrono::system_clock::time_point& v) const {
return detail::chrono_convert<std::chrono::system_clock>(o, v);
}
};
template <>
struct pack<std::chrono::system_clock::time_point> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::chrono::system_clock::time_point& v) const {
return detail::chrono_pack<std::chrono::system_clock>(o, v);
}
};
template <>
struct object_with_zone<std::chrono::system_clock::time_point> {
void operator()(msgpack::object::with_zone& o, const std::chrono::system_clock::time_point& v) const {
detail::chrono_object_with_zone<std::chrono::system_clock>(o, v);
}
};
template <>
struct as<std::chrono::steady_clock::time_point> {
typename std::chrono::steady_clock::time_point operator()(msgpack::object const& o) const {
return detail::chrono_as<std::chrono::steady_clock>(o);
}
};
template <>
struct convert<std::chrono::steady_clock::time_point> {
msgpack::object const& operator()(msgpack::object const& o, std::chrono::steady_clock::time_point& v) const {
return detail::chrono_convert<std::chrono::steady_clock>(o, v);
}
};
template <>
struct pack<std::chrono::steady_clock::time_point> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::chrono::steady_clock::time_point& v) const {
return detail::chrono_pack<std::chrono::steady_clock>(o, v);
}
};
template <>
struct object_with_zone<std::chrono::steady_clock::time_point> {
void operator()(msgpack::object::with_zone& o, const std::chrono::steady_clock::time_point& v) const {
detail::chrono_object_with_zone<std::chrono::steady_clock>(o, v);
}
};
template <>
struct as<
std::chrono::high_resolution_clock::time_point,
typename std::conditional<
!std::is_same<std::chrono::high_resolution_clock, std::chrono::system_clock>::value &&
!std::is_same<std::chrono::high_resolution_clock, std::chrono::steady_clock>::value,
void,
std::nullptr_t
>::type
> {
typename std::chrono::high_resolution_clock::time_point operator()(msgpack::object const& o) const {
return detail::chrono_as<std::chrono::high_resolution_clock>(o);
}
};
template <>
struct convert<
std::chrono::high_resolution_clock::time_point,
typename std::conditional<
!std::is_same<std::chrono::high_resolution_clock, std::chrono::system_clock>::value &&
!std::is_same<std::chrono::high_resolution_clock, std::chrono::steady_clock>::value,
void,
std::nullptr_t
>::type
> {
msgpack::object const& operator()(msgpack::object const& o, std::chrono::high_resolution_clock::time_point& v) const {
return detail::chrono_convert<std::chrono::high_resolution_clock>(o, v);
}
};
template <>
struct pack<
std::chrono::high_resolution_clock::time_point,
typename std::conditional<
!std::is_same<std::chrono::high_resolution_clock, std::chrono::system_clock>::value &&
!std::is_same<std::chrono::high_resolution_clock, std::chrono::steady_clock>::value,
void,
std::nullptr_t
>::type
> {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::chrono::high_resolution_clock::time_point& v) const {
return detail::chrono_pack<std::chrono::high_resolution_clock>(o, v);
}
};
template <>
struct object_with_zone<
std::chrono::high_resolution_clock::time_point,
typename std::conditional<
!std::is_same<std::chrono::high_resolution_clock, std::chrono::system_clock>::value &&
!std::is_same<std::chrono::high_resolution_clock, std::chrono::steady_clock>::value,
void,
std::nullptr_t
>::type
> {
void operator()(msgpack::object::with_zone& o, const std::chrono::high_resolution_clock::time_point& v) const {
detail::chrono_object_with_zone<std::chrono::high_resolution_clock>(o, v);
}
};