diff --git a/include/msgpack/v1/adaptor/cpp11/chrono.hpp b/include/msgpack/v1/adaptor/cpp11/chrono.hpp index c6324fdcd..333194ed5 100644 --- a/include/msgpack/v1/adaptor/cpp11/chrono.hpp +++ b/include/msgpack/v1/adaptor/cpp11/chrono.hpp @@ -17,6 +17,8 @@ #include +#include + namespace msgpack { /// @cond @@ -25,13 +27,12 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { namespace adaptor { -template -struct as> { - typename std::chrono::time_point operator()(msgpack::object const& o) const { - using duration_t = typename std::chrono::time_point::duration; +template +struct as> { + typename std::chrono::time_point operator()(msgpack::object const& o) const { 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; + std::chrono::time_point tp; switch(o.via.ext.size) { case 4: { uint32_t sec; @@ -41,9 +42,9 @@ struct as> { case 8: { uint64_t value; _msgpack_load64(uint64_t, o.via.ext.data(), &value); - uint32_t nanosec = static_cast(value >> 34); + uint32_t nanosec = boost::numeric_cast(value >> 34); uint64_t sec = value & 0x00000003ffffffffLL; - tp += std::chrono::duration_cast( + tp += std::chrono::duration_cast( std::chrono::nanoseconds(nanosec)); tp += std::chrono::seconds(sec); } break; @@ -52,9 +53,24 @@ struct as> { _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); + + if (sec > 0) { + tp += std::chrono::seconds(sec); + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + } + else { + if (nanosec == 0) { + tp += std::chrono::seconds(sec); + } + else { + ++sec; + tp += std::chrono::seconds(sec); + int64_t ns = boost::numeric_cast(nanosec) - 1000000000L; + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(ns)); + } + } } break; default: throw msgpack::type_error(); @@ -63,13 +79,12 @@ struct as> { } }; -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; +template +struct convert> { + msgpack::object const& operator()(msgpack::object const& o, std::chrono::time_point& v) const { 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; + std::chrono::time_point tp; switch(o.via.ext.size) { case 4: { uint32_t sec; @@ -80,9 +95,9 @@ struct convert> { case 8: { uint64_t value; _msgpack_load64(uint64_t, o.via.ext.data(), &value); - uint32_t nanosec = static_cast(value >> 34); + uint32_t nanosec = boost::numeric_cast(value >> 34); uint64_t sec = value & 0x00000003ffffffffLL; - tp += std::chrono::duration_cast( + tp += std::chrono::duration_cast( std::chrono::nanoseconds(nanosec)); tp += std::chrono::seconds(sec); v = tp; @@ -92,9 +107,25 @@ struct convert> { _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); + + if (sec > 0) { + tp += std::chrono::seconds(sec); + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(nanosec)); + } + else { + if (nanosec == 0) { + tp += std::chrono::seconds(sec); + } + else { + ++sec; + tp += std::chrono::seconds(sec); + int64_t ns = boost::numeric_cast(nanosec) - 1000000000L; + tp += std::chrono::duration_cast( + std::chrono::nanoseconds(ns)); + } + } + v = tp; } break; default: @@ -104,32 +135,31 @@ struct convert> { } }; -template -struct pack> { +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()); - + msgpack::packer& operator()(msgpack::packer& o, std::chrono::time_point const& v) const { + int64_t count = boost::numeric_cast(v.time_since_epoch().count()); int64_t nano_num = - duration_t::period::ratio::num * - (1000000000 / duration_t::period::ratio::den); + Duration::period::ratio::num * + (1000000000L / Duration::period::ratio::den); - int64_t nanosec = count % (1000000000 / nano_num) * nano_num; + int64_t nanosec = count % (1000000000L / nano_num) * nano_num; int64_t sec = 0; if (nanosec < 0) { - nanosec = 1000000000 + nanosec; + nanosec = 1000000000L + nanosec; --sec; } sec += count - * duration_t::period::ratio::num - / duration_t::period::ratio::den; + * Duration::period::ratio::num + / Duration::period::ratio::den; + if ((sec >> 34) == 0) { - uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); + uint64_t data64 = (boost::numeric_cast(nanosec) << 34) | boost::numeric_cast(sec); if ((data64 & 0xffffffff00000000L) == 0) { // timestamp 32 o.pack_ext(4, -1); - uint32_t data32 = static_cast(data64); + uint32_t data32 = boost::numeric_cast(data64); char buf[4]; _msgpack_store32(buf, data32); o.pack_ext_body(buf, 4); @@ -146,7 +176,9 @@ struct pack> { // timestamp 96 o.pack_ext(12, -1); char buf[12]; - _msgpack_store32(&buf[0], static_cast(nanosec)); + + + _msgpack_store32(&buf[0], boost::numeric_cast(nanosec)); _msgpack_store64(&buf[4], sec); o.pack_ext_body(buf, 12); } @@ -154,34 +186,33 @@ struct pack> { } }; -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()); +template +struct object_with_zone> { + void operator()(msgpack::object::with_zone& o, const std::chrono::time_point& v) const { + int64_t count = boost::numeric_cast(v.time_since_epoch().count()); int64_t nano_num = - duration_t::period::ratio::num * - (1000000000 / duration_t::period::ratio::den); + Duration::period::ratio::num * + (1000000000L / Duration::period::ratio::den); - int64_t nanosec = count % (1000000000 / nano_num) * nano_num; + int64_t nanosec = count % (1000000000L / nano_num) * nano_num; int64_t sec = 0; if (nanosec < 0) { - nanosec = 1000000000 + nanosec; + nanosec = 1000000000L + nanosec; --sec; } sec += count - * duration_t::period::ratio::num - / duration_t::period::ratio::den; + * Duration::period::ratio::num + / Duration::period::ratio::den; if ((sec >> 34) == 0) { - uint64_t data64 = (static_cast(nanosec) << 34) | static_cast(sec); + uint64_t data64 = (boost::numeric_cast(nanosec) << 34) | boost::numeric_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); + uint32_t data32 = boost::numeric_cast(data64); _msgpack_store32(&p[1], data32); o.via.ext.ptr = p; } @@ -201,7 +232,7 @@ struct object_with_zone> { 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_store32(&p[1], boost::numeric_cast(nanosec)); _msgpack_store64(&p[1 + 4], sec); o.via.ext.ptr = p; }