diff --git a/include/msgpack/v1/adaptor/cpp11/chrono.hpp b/include/msgpack/v1/adaptor/cpp11/chrono.hpp index 88f84bb4..c6324fdc 100644 --- a/include/msgpack/v1/adaptor/cpp11/chrono.hpp +++ b/include/msgpack/v1/adaptor/cpp11/chrono.hpp @@ -25,299 +25,187 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { namespace adaptor { -namespace detail { - -template -typename T::time_point chrono_as(msgpack::object const& o) { - 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; - switch(o.via.ext.size) { - case 4: { - uint32_t sec; - _msgpack_load32(uint32_t, o.via.ext.data(), &sec); - tp += std::chrono::seconds(sec); - } break; - case 8: { - uint64_t value; - _msgpack_load64(uint64_t, o.via.ext.data(), &value); - uint32_t nanosec = static_cast(value >> 34); - uint64_t sec = value & 0x00000003ffffffffLL; - tp += std::chrono::duration_cast( - std::chrono::nanoseconds(nanosec)); - tp += std::chrono::seconds(sec); - } 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); - tp += std::chrono::duration_cast( - std::chrono::nanoseconds(nanosec)); - tp += std::chrono::seconds(sec); - } break; - default: - throw msgpack::type_error(); +template +struct as> { + typename std::chrono::time_point operator()(msgpack::object const& o) const { + using duration_t = typename std::chrono::time_point::duration; + if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); } + if(o.via.ext.type() != -1) { throw msgpack::type_error(); } + std::chrono::time_point tp; + switch(o.via.ext.size) { + case 4: { + uint32_t sec; + _msgpack_load32(uint32_t, o.via.ext.data(), &sec); + tp += std::chrono::seconds(sec); + } break; + case 8: { + uint64_t value; + _msgpack_load64(uint64_t, o.via.ext.data(), &value); + uint32_t nanosec = static_cast(value >> 34); + uint64_t sec = value & 0x00000003ffffffffLL; + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + tp += std::chrono::seconds(sec); + } 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); + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + tp += std::chrono::seconds(sec); + } break; + default: + throw msgpack::type_error(); + } + return tp; } - return tp; -} +}; -template -msgpack::object const& chrono_convert(msgpack::object const& o, typename T::time_point& v) { - 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; - switch(o.via.ext.size) { - case 4: { - uint32_t sec; - _msgpack_load32(uint32_t, o.via.ext.data(), &sec); - tp += std::chrono::seconds(sec); - v = tp; - } break; - case 8: { - uint64_t value; - _msgpack_load64(uint64_t, o.via.ext.data(), &value); - uint32_t nanosec = static_cast(value >> 34); - uint64_t sec = value & 0x00000003ffffffffLL; - tp += std::chrono::duration_cast( - std::chrono::nanoseconds(nanosec)); - tp += std::chrono::seconds(sec); - v = tp; - } 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); - tp += std::chrono::duration_cast( - std::chrono::nanoseconds(nanosec)); - tp += std::chrono::seconds(sec); - v = tp; - } break; - default: - throw msgpack::type_error(); +template +struct convert> { + msgpack::object const& operator()(msgpack::object const& o, std::chrono::time_point& v) const { + using duration_t = typename std::chrono::time_point::duration; + if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); } + if(o.via.ext.type() != -1) { throw msgpack::type_error(); } + std::chrono::time_point tp; + switch(o.via.ext.size) { + case 4: { + uint32_t sec; + _msgpack_load32(uint32_t, o.via.ext.data(), &sec); + tp += std::chrono::seconds(sec); + v = tp; + } break; + case 8: { + uint64_t value; + _msgpack_load64(uint64_t, o.via.ext.data(), &value); + uint32_t nanosec = static_cast(value >> 34); + uint64_t sec = value & 0x00000003ffffffffLL; + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + tp += std::chrono::seconds(sec); + v = tp; + } 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); + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + tp += std::chrono::seconds(sec); + v = tp; + } break; + default: + throw msgpack::type_error(); + } + return o; } - return o; -} +}; -template -msgpack::packer& chrono_pack(msgpack::packer& o, const typename T::time_point& v) { - int64_t count = static_cast(v.time_since_epoch().count()); +template +struct pack> { + template + msgpack::packer& operator()(msgpack::packer& o, std::chrono::time_point const& v) const { + using duration_t = typename std::chrono::time_point::duration; + int64_t count = static_cast(v.time_since_epoch().count()); - int64_t nano_num = - T::duration::period::ratio::num * - (1000000000 / T::duration::period::ratio::den); + int64_t nano_num = + duration_t::period::ratio::num * + (1000000000 / duration_t::period::ratio::den); - int64_t nanosec = count % (1000000000 / nano_num) * nano_num; - int64_t sec = 0; - if (nanosec < 0) { - nanosec = 1000000000 + nanosec; - --sec; - } - sec += count - * T::duration::period::ratio::num - / T::duration::period::ratio::den; - if ((sec >> 34) == 0) { - uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); - if ((data64 & 0xffffffff00000000L) == 0) { - // timestamp 32 - o.pack_ext(4, -1); - uint32_t data32 = static_cast(data64); - char buf[4]; - _msgpack_store32(buf, data32); - o.pack_ext_body(buf, 4); + int64_t nanosec = count % (1000000000 / nano_num) * nano_num; + int64_t sec = 0; + if (nanosec < 0) { + nanosec = 1000000000 + nanosec; + --sec; + } + sec += count + * duration_t::period::ratio::num + / duration_t::period::ratio::den; + if ((sec >> 34) == 0) { + uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); + if ((data64 & 0xffffffff00000000L) == 0) { + // timestamp 32 + o.pack_ext(4, -1); + uint32_t data32 = static_cast(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 64 - o.pack_ext(8, -1); - char buf[8]; - _msgpack_store64(buf, data64); - o.pack_ext_body(buf, 8); + // timestamp 96 + o.pack_ext(12, -1); + char buf[12]; + _msgpack_store32(&buf[0], static_cast(nanosec)); + _msgpack_store64(&buf[4], sec); + o.pack_ext_body(buf, 12); } + return o; } - else { - // timestamp 96 - o.pack_ext(12, -1); - char buf[12]; - _msgpack_store32(&buf[0], static_cast(nanosec)); - _msgpack_store64(&buf[4], sec); - o.pack_ext_body(buf, 12); - } - return o; -} +}; -template -void chrono_object_with_zone(msgpack::object::with_zone& o, const typename T::time_point& v) { - int64_t count = static_cast(v.time_since_epoch().count()); +template +struct object_with_zone> { + void operator()(msgpack::object::with_zone& o, const std::chrono::time_point& v) const { + using duration_t = typename std::chrono::time_point::duration; + int64_t count = static_cast(v.time_since_epoch().count()); - int64_t nano_num = - T::duration::period::ratio::num * - (1000000000 / T::duration::period::ratio::den); + int64_t nano_num = + duration_t::period::ratio::num * + (1000000000 / duration_t::period::ratio::den); - int64_t nanosec = count % (1000000000 / nano_num) * nano_num; - int64_t sec = 0; - if (nanosec < 0) { - nanosec = 1000000000 + nanosec; - --sec; - } - sec += count - * T::duration::period::ratio::num - / T::duration::period::ratio::den; - if ((sec >> 34) == 0) { - uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); - if ((data64 & 0xffffffff00000000L) == 0) { - // timestamp 32 - o.type = msgpack::type::EXT; - o.via.ext.size = 4; - char* p = static_cast(o.zone.allocate_no_align(o.via.ext.size + 1)); - p[0] = static_cast(-1); - uint32_t data32 = static_cast(data64); - _msgpack_store32(&p[1], data32); - o.via.ext.ptr = p; + int64_t nanosec = count % (1000000000 / nano_num) * nano_num; + int64_t sec = 0; + if (nanosec < 0) { + nanosec = 1000000000 + nanosec; + --sec; + } + sec += count + * duration_t::period::ratio::num + / duration_t::period::ratio::den; + if ((sec >> 34) == 0) { + uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); + if ((data64 & 0xffffffff00000000L) == 0) { + // timestamp 32 + o.type = msgpack::type::EXT; + o.via.ext.size = 4; + char* p = static_cast(o.zone.allocate_no_align(o.via.ext.size + 1)); + p[0] = static_cast(-1); + uint32_t data32 = static_cast(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(o.zone.allocate_no_align(o.via.ext.size + 1)); + p[0] = static_cast(-1); + _msgpack_store64(&p[1], data64); + o.via.ext.ptr = p; + } } else { - // timestamp 64 + // timestamp 96 o.type = msgpack::type::EXT; - o.via.ext.size = 8; + o.via.ext.size = 12; char* p = static_cast(o.zone.allocate_no_align(o.via.ext.size + 1)); p[0] = static_cast(-1); - _msgpack_store64(&p[1], data64); + _msgpack_store32(&p[1], static_cast(nanosec)); + _msgpack_store64(&p[1 + 4], sec); o.via.ext.ptr = p; } } - else { - // timestamp 96 - o.type = msgpack::type::EXT; - o.via.ext.size = 12; - char* p = static_cast(o.zone.allocate_no_align(o.via.ext.size + 1)); - p[0] = static_cast(-1); - _msgpack_store32(&p[1], static_cast(nanosec)); - _msgpack_store64(&p[1 + 4], sec); - o.via.ext.ptr = p; - } -} - -} // namespace detail - -template <> -struct as { - typename std::chrono::system_clock::time_point operator()(msgpack::object const& o) const { - return detail::chrono_as(o); - } -}; - -template <> -struct convert { - msgpack::object const& operator()(msgpack::object const& o, std::chrono::system_clock::time_point& v) const { - return detail::chrono_convert(o, v); - } -}; - -template <> -struct pack { - template - msgpack::packer& operator()(msgpack::packer& o, const std::chrono::system_clock::time_point& v) const { - return detail::chrono_pack(o, v); - } -}; - -template <> -struct object_with_zone { - void operator()(msgpack::object::with_zone& o, const std::chrono::system_clock::time_point& v) const { - detail::chrono_object_with_zone(o, v); - } -}; - - -template <> -struct as { - typename std::chrono::steady_clock::time_point operator()(msgpack::object const& o) const { - return detail::chrono_as(o); - } -}; - -template <> -struct convert { - msgpack::object const& operator()(msgpack::object const& o, std::chrono::steady_clock::time_point& v) const { - return detail::chrono_convert(o, v); - } -}; - -template <> -struct pack { - template - msgpack::packer& operator()(msgpack::packer& o, const std::chrono::steady_clock::time_point& v) const { - return detail::chrono_pack(o, v); - } -}; - -template <> -struct object_with_zone { - void operator()(msgpack::object::with_zone& o, const std::chrono::steady_clock::time_point& v) const { - detail::chrono_object_with_zone(o, v); - } -}; - - -template <> -struct as< - std::chrono::high_resolution_clock::time_point, - typename std::conditional< - !std::is_same::value && - !std::is_same::value, - void, - std::nullptr_t - >::type -> { - typename std::chrono::high_resolution_clock::time_point operator()(msgpack::object const& o) const { - return detail::chrono_as(o); - } -}; - -template <> -struct convert< - std::chrono::high_resolution_clock::time_point, - typename std::conditional< - !std::is_same::value && - !std::is_same::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(o, v); - } -}; - -template <> -struct pack< - std::chrono::high_resolution_clock::time_point, - typename std::conditional< - !std::is_same::value && - !std::is_same::value, - void, - std::nullptr_t - >::type -> { - template - msgpack::packer& operator()(msgpack::packer& o, const std::chrono::high_resolution_clock::time_point& v) const { - return detail::chrono_pack(o, v); - } -}; - -template <> -struct object_with_zone< - std::chrono::high_resolution_clock::time_point, - typename std::conditional< - !std::is_same::value && - !std::is_same::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(o, v); - } }; } // namespace adaptor