17
17
18
18
#include < chrono>
19
19
20
+ #include < boost/numeric/conversion/cast.hpp>
21
+
20
22
namespace msgpack {
21
23
22
24
// / @cond
@@ -25,13 +27,12 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
25
27
26
28
namespace adaptor {
27
29
28
- template <typename Clock>
29
- struct as <std::chrono::time_point<Clock>> {
30
- typename std::chrono::time_point<Clock> operator ()(msgpack::object const & o) const {
31
- using duration_t = typename std::chrono::time_point<Clock>::duration;
30
+ template <typename Clock, typename Duration>
31
+ struct as <std::chrono::time_point<Clock, Duration>> {
32
+ typename std::chrono::time_point<Clock, Duration> operator ()(msgpack::object const & o) const {
32
33
if (o.type != msgpack::type::EXT) { throw msgpack::type_error (); }
33
34
if (o.via .ext .type () != -1 ) { throw msgpack::type_error (); }
34
- std::chrono::time_point<Clock> tp;
35
+ std::chrono::time_point<Clock, Duration > tp;
35
36
switch (o.via .ext .size ) {
36
37
case 4 : {
37
38
uint32_t sec;
@@ -41,9 +42,9 @@ struct as<std::chrono::time_point<Clock>> {
41
42
case 8 : {
42
43
uint64_t value;
43
44
_msgpack_load64 (uint64_t , o.via .ext .data (), &value);
44
- uint32_t nanosec = static_cast <uint32_t >(value >> 34 );
45
+ uint32_t nanosec = boost::numeric_cast <uint32_t >(value >> 34 );
45
46
uint64_t sec = value & 0x00000003ffffffffLL ;
46
- tp += std::chrono::duration_cast<duration_t >(
47
+ tp += std::chrono::duration_cast<Duration >(
47
48
std::chrono::nanoseconds (nanosec));
48
49
tp += std::chrono::seconds (sec);
49
50
} break ;
@@ -52,9 +53,24 @@ struct as<std::chrono::time_point<Clock>> {
52
53
_msgpack_load32 (uint32_t , o.via .ext .data (), &nanosec);
53
54
int64_t sec;
54
55
_msgpack_load64 (int64_t , o.via .ext .data () + 4 , &sec);
55
- tp += std::chrono::duration_cast<duration_t >(
56
- std::chrono::nanoseconds (nanosec));
57
- tp += std::chrono::seconds (sec);
56
+
57
+ if (sec > 0 ) {
58
+ tp += std::chrono::seconds (sec);
59
+ tp += std::chrono::duration_cast<Duration>(
60
+ std::chrono::nanoseconds (nanosec));
61
+ }
62
+ else {
63
+ if (nanosec == 0 ) {
64
+ tp += std::chrono::seconds (sec);
65
+ }
66
+ else {
67
+ ++sec;
68
+ tp += std::chrono::seconds (sec);
69
+ int64_t ns = boost::numeric_cast<int64_t >(nanosec) - 1000000000L ;
70
+ tp += std::chrono::duration_cast<Duration>(
71
+ std::chrono::nanoseconds (ns));
72
+ }
73
+ }
58
74
} break ;
59
75
default :
60
76
throw msgpack::type_error ();
@@ -63,13 +79,12 @@ struct as<std::chrono::time_point<Clock>> {
63
79
}
64
80
};
65
81
66
- template <typename Clock>
67
- struct convert <std::chrono::time_point<Clock>> {
68
- msgpack::object const & operator ()(msgpack::object const & o, std::chrono::time_point<Clock>& v) const {
69
- using duration_t = typename std::chrono::time_point<Clock>::duration;
82
+ template <typename Clock, typename Duration>
83
+ struct convert <std::chrono::time_point<Clock, Duration>> {
84
+ msgpack::object const & operator ()(msgpack::object const & o, std::chrono::time_point<Clock, Duration>& v) const {
70
85
if (o.type != msgpack::type::EXT) { throw msgpack::type_error (); }
71
86
if (o.via .ext .type () != -1 ) { throw msgpack::type_error (); }
72
- std::chrono::time_point<Clock> tp;
87
+ std::chrono::time_point<Clock, Duration > tp;
73
88
switch (o.via .ext .size ) {
74
89
case 4 : {
75
90
uint32_t sec;
@@ -80,9 +95,9 @@ struct convert<std::chrono::time_point<Clock>> {
80
95
case 8 : {
81
96
uint64_t value;
82
97
_msgpack_load64 (uint64_t , o.via .ext .data (), &value);
83
- uint32_t nanosec = static_cast <uint32_t >(value >> 34 );
98
+ uint32_t nanosec = boost::numeric_cast <uint32_t >(value >> 34 );
84
99
uint64_t sec = value & 0x00000003ffffffffLL ;
85
- tp += std::chrono::duration_cast<duration_t >(
100
+ tp += std::chrono::duration_cast<Duration >(
86
101
std::chrono::nanoseconds (nanosec));
87
102
tp += std::chrono::seconds (sec);
88
103
v = tp;
@@ -92,9 +107,25 @@ struct convert<std::chrono::time_point<Clock>> {
92
107
_msgpack_load32 (uint32_t , o.via .ext .data (), &nanosec);
93
108
int64_t sec;
94
109
_msgpack_load64 (int64_t , o.via .ext .data () + 4 , &sec);
95
- tp += std::chrono::duration_cast<duration_t >(
96
- std::chrono::nanoseconds (nanosec));
97
- tp += std::chrono::seconds (sec);
110
+
111
+ if (sec > 0 ) {
112
+ tp += std::chrono::seconds (sec);
113
+ tp += std::chrono::duration_cast<Duration>(
114
+ std::chrono::nanoseconds (nanosec));
115
+ }
116
+ else {
117
+ if (nanosec == 0 ) {
118
+ tp += std::chrono::seconds (sec);
119
+ }
120
+ else {
121
+ ++sec;
122
+ tp += std::chrono::seconds (sec);
123
+ int64_t ns = boost::numeric_cast<int64_t >(nanosec) - 1000000000L ;
124
+ tp += std::chrono::duration_cast<Duration>(
125
+ std::chrono::nanoseconds (ns));
126
+ }
127
+ }
128
+
98
129
v = tp;
99
130
} break ;
100
131
default :
@@ -104,32 +135,31 @@ struct convert<std::chrono::time_point<Clock>> {
104
135
}
105
136
};
106
137
107
- template <typename Clock>
108
- struct pack <std::chrono::time_point<Clock>> {
138
+ template <typename Clock, typename Duration >
139
+ struct pack <std::chrono::time_point<Clock, Duration >> {
109
140
template <typename Stream>
110
- msgpack::packer<Stream>& operator ()(msgpack::packer<Stream>& o, std::chrono::time_point<Clock> const & v) const {
111
- using duration_t = typename std::chrono::time_point<Clock>::duration;
112
- int64_t count = static_cast <int64_t >(v.time_since_epoch ().count ());
113
-
141
+ msgpack::packer<Stream>& operator ()(msgpack::packer<Stream>& o, std::chrono::time_point<Clock, Duration> const & v) const {
142
+ int64_t count = boost::numeric_cast<int64_t >(v.time_since_epoch ().count ());
114
143
int64_t nano_num =
115
- duration_t ::period::ratio::num *
116
- (1000000000 / duration_t ::period::ratio::den);
144
+ Duration ::period::ratio::num *
145
+ (1000000000L / Duration ::period::ratio::den);
117
146
118
- int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
147
+ int64_t nanosec = count % (1000000000L / nano_num) * nano_num;
119
148
int64_t sec = 0 ;
120
149
if (nanosec < 0 ) {
121
- nanosec = 1000000000 + nanosec;
150
+ nanosec = 1000000000L + nanosec;
122
151
--sec;
123
152
}
124
153
sec += count
125
- * duration_t ::period::ratio::num
126
- / duration_t ::period::ratio::den;
154
+ * Duration::period::ratio::num
155
+ / Duration::period::ratio::den;
156
+
127
157
if ((sec >> 34 ) == 0 ) {
128
- uint64_t data64 = (static_cast <uint64_t >(nanosec) << 34 ) | static_cast <uint64_t >(sec);
158
+ uint64_t data64 = (boost::numeric_cast <uint64_t >(nanosec) << 34 ) | boost::numeric_cast <uint64_t >(sec);
129
159
if ((data64 & 0xffffffff00000000L ) == 0 ) {
130
160
// timestamp 32
131
161
o.pack_ext (4 , -1 );
132
- uint32_t data32 = static_cast <uint32_t >(data64);
162
+ uint32_t data32 = boost::numeric_cast <uint32_t >(data64);
133
163
char buf[4 ];
134
164
_msgpack_store32 (buf, data32);
135
165
o.pack_ext_body (buf, 4 );
@@ -146,42 +176,43 @@ struct pack<std::chrono::time_point<Clock>> {
146
176
// timestamp 96
147
177
o.pack_ext (12 , -1 );
148
178
char buf[12 ];
149
- _msgpack_store32 (&buf[0 ], static_cast <uint32_t >(nanosec));
179
+
180
+
181
+ _msgpack_store32 (&buf[0 ], boost::numeric_cast<uint32_t >(nanosec));
150
182
_msgpack_store64 (&buf[4 ], sec);
151
183
o.pack_ext_body (buf, 12 );
152
184
}
153
185
return o;
154
186
}
155
187
};
156
188
157
- template <typename Clock>
158
- struct object_with_zone <std::chrono::time_point<Clock>> {
159
- void operator ()(msgpack::object::with_zone& o, const std::chrono::time_point<Clock>& v) const {
160
- using duration_t = typename std::chrono::time_point<Clock>::duration;
161
- int64_t count = static_cast <int64_t >(v.time_since_epoch ().count ());
189
+ template <typename Clock, typename Duration>
190
+ struct object_with_zone <std::chrono::time_point<Clock, Duration>> {
191
+ void operator ()(msgpack::object::with_zone& o, const std::chrono::time_point<Clock, Duration>& v) const {
192
+ int64_t count = boost::numeric_cast<int64_t >(v.time_since_epoch ().count ());
162
193
163
194
int64_t nano_num =
164
- duration_t ::period::ratio::num *
165
- (1000000000 / duration_t ::period::ratio::den);
195
+ Duration ::period::ratio::num *
196
+ (1000000000L / Duration ::period::ratio::den);
166
197
167
- int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
198
+ int64_t nanosec = count % (1000000000L / nano_num) * nano_num;
168
199
int64_t sec = 0 ;
169
200
if (nanosec < 0 ) {
170
- nanosec = 1000000000 + nanosec;
201
+ nanosec = 1000000000L + nanosec;
171
202
--sec;
172
203
}
173
204
sec += count
174
- * duration_t ::period::ratio::num
175
- / duration_t ::period::ratio::den;
205
+ * Duration ::period::ratio::num
206
+ / Duration ::period::ratio::den;
176
207
if ((sec >> 34 ) == 0 ) {
177
- uint64_t data64 = (static_cast <uint64_t >(nanosec) << 34 ) | static_cast <uint64_t >(sec);
208
+ uint64_t data64 = (boost::numeric_cast <uint64_t >(nanosec) << 34 ) | boost::numeric_cast <uint64_t >(sec);
178
209
if ((data64 & 0xffffffff00000000L ) == 0 ) {
179
210
// timestamp 32
180
211
o.type = msgpack::type::EXT;
181
212
o.via .ext .size = 4 ;
182
213
char * p = static_cast <char *>(o.zone .allocate_no_align (o.via .ext .size + 1 ));
183
214
p[0 ] = static_cast <char >(-1 );
184
- uint32_t data32 = static_cast <uint32_t >(data64);
215
+ uint32_t data32 = boost::numeric_cast <uint32_t >(data64);
185
216
_msgpack_store32 (&p[1 ], data32);
186
217
o.via .ext .ptr = p;
187
218
}
@@ -201,7 +232,7 @@ struct object_with_zone<std::chrono::time_point<Clock>> {
201
232
o.via .ext .size = 12 ;
202
233
char * p = static_cast <char *>(o.zone .allocate_no_align (o.via .ext .size + 1 ));
203
234
p[0 ] = static_cast <char >(-1 );
204
- _msgpack_store32 (&p[1 ], static_cast <uint32_t >(nanosec));
235
+ _msgpack_store32 (&p[1 ], boost::numeric_cast <uint32_t >(nanosec));
205
236
_msgpack_store64 (&p[1 + 4 ], sec);
206
237
o.via .ext .ptr = p;
207
238
}
0 commit comments