MessagePack for C++
chrono.hpp
Go to the documentation of this file.
1//
2// MessagePack for C++ static resolution routine
3//
4// Copyright (C) 2017 KONDO Takatoshi
5//
6// Distributed under the Boost Software License, Version 1.0.
7// (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
12#define MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
13
17
18#include <chrono>
19
20#include <boost/numeric/conversion/cast.hpp>
21
22namespace msgpack {
23
27
28namespace adaptor {
29
30template <typename Clock, typename Duration>
31struct as<std::chrono::time_point<Clock, Duration>> {
32 typename std::chrono::time_point<Clock, Duration> operator()(msgpack::object const& o) const {
33 if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
34 if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
35 std::chrono::time_point<Clock, Duration> tp;
36 switch(o.via.ext.size) {
37 case 4: {
38 uint32_t sec;
39 _msgpack_load32(uint32_t, o.via.ext.data(), &sec);
40 tp += std::chrono::seconds(sec);
41 } break;
42 case 8: {
43 uint64_t value;
44 _msgpack_load64(uint64_t, o.via.ext.data(), &value);
45 uint32_t nanosec = boost::numeric_cast<uint32_t>(value >> 34);
46 uint64_t sec = value & 0x00000003ffffffffLL;
47 tp += std::chrono::duration_cast<Duration>(
48 std::chrono::nanoseconds(nanosec));
49 tp += std::chrono::seconds(sec);
50 } break;
51 case 12: {
52 uint32_t nanosec;
53 _msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
54 int64_t sec;
55 _msgpack_load64(int64_t, o.via.ext.data() + 4, &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 }
74 } break;
75 default:
76 throw msgpack::type_error();
77 }
78 return tp;
79 }
80};
81
82template <typename Clock, typename Duration>
83struct convert<std::chrono::time_point<Clock, Duration>> {
84 msgpack::object const& operator()(msgpack::object const& o, std::chrono::time_point<Clock, Duration>& v) const {
85 if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
86 if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
87 std::chrono::time_point<Clock, Duration> tp;
88 switch(o.via.ext.size) {
89 case 4: {
90 uint32_t sec;
91 _msgpack_load32(uint32_t, o.via.ext.data(), &sec);
92 tp += std::chrono::seconds(sec);
93 v = tp;
94 } break;
95 case 8: {
96 uint64_t value;
97 _msgpack_load64(uint64_t, o.via.ext.data(), &value);
98 uint32_t nanosec = boost::numeric_cast<uint32_t>(value >> 34);
99 uint64_t sec = value & 0x00000003ffffffffLL;
100 tp += std::chrono::duration_cast<Duration>(
101 std::chrono::nanoseconds(nanosec));
102 tp += std::chrono::seconds(sec);
103 v = tp;
104 } break;
105 case 12: {
106 uint32_t nanosec;
107 _msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
108 int64_t sec;
109 _msgpack_load64(int64_t, o.via.ext.data() + 4, &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
129 v = tp;
130 } break;
131 default:
132 throw msgpack::type_error();
133 }
134 return o;
135 }
136};
137
138template <typename Clock, typename Duration>
139struct pack<std::chrono::time_point<Clock, Duration>> {
140 template <typename Stream>
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());
143 int64_t nano_num =
144 Duration::period::ratio::num *
145 (1000000000L / Duration::period::ratio::den);
146
147 int64_t nanosec = count % (1000000000L / nano_num) * nano_num;
148 int64_t sec = 0;
149 if (nanosec < 0) {
150 nanosec = 1000000000L + nanosec;
151 --sec;
152 }
153 sec += count
154 * Duration::period::ratio::num
155 / Duration::period::ratio::den;
156
157 if ((sec >> 34) == 0) {
158 uint64_t data64 = (boost::numeric_cast<uint64_t>(nanosec) << 34) | boost::numeric_cast<uint64_t>(sec);
159 if ((data64 & 0xffffffff00000000L) == 0) {
160 // timestamp 32
161 o.pack_ext(4, -1);
162 uint32_t data32 = boost::numeric_cast<uint32_t>(data64);
163 char buf[4];
164 _msgpack_store32(buf, data32);
165 o.pack_ext_body(buf, 4);
166 }
167 else {
168 // timestamp 64
169 o.pack_ext(8, -1);
170 char buf[8];
171 _msgpack_store64(buf, data64);
172 o.pack_ext_body(buf, 8);
173 }
174 }
175 else {
176 // timestamp 96
177 o.pack_ext(12, -1);
178 char buf[12];
179
180
181 _msgpack_store32(&buf[0], boost::numeric_cast<uint32_t>(nanosec));
182 _msgpack_store64(&buf[4], sec);
183 o.pack_ext_body(buf, 12);
184 }
185 return o;
186 }
187};
188
189template <typename Clock, typename Duration>
190struct 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());
193
194 int64_t nano_num =
195 Duration::period::ratio::num *
196 (1000000000L / Duration::period::ratio::den);
197
198 int64_t nanosec = count % (1000000000L / nano_num) * nano_num;
199 int64_t sec = 0;
200 if (nanosec < 0) {
201 nanosec = 1000000000L + nanosec;
202 --sec;
203 }
204 sec += count
205 * Duration::period::ratio::num
206 / Duration::period::ratio::den;
207 if ((sec >> 34) == 0) {
208 uint64_t data64 = (boost::numeric_cast<uint64_t>(nanosec) << 34) | boost::numeric_cast<uint64_t>(sec);
209 if ((data64 & 0xffffffff00000000L) == 0) {
210 // timestamp 32
212 o.via.ext.size = 4;
213 char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
214 p[0] = static_cast<char>(-1);
215 uint32_t data32 = boost::numeric_cast<uint32_t>(data64);
216 _msgpack_store32(&p[1], data32);
217 o.via.ext.ptr = p;
218 }
219 else {
220 // timestamp 64
222 o.via.ext.size = 8;
223 char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
224 p[0] = static_cast<char>(-1);
225 _msgpack_store64(&p[1], data64);
226 o.via.ext.ptr = p;
227 }
228 }
229 else {
230 // timestamp 96
232 o.via.ext.size = 12;
233 char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
234 p[0] = static_cast<char>(-1);
235 _msgpack_store32(&p[1], boost::numeric_cast<uint32_t>(nanosec));
236 _msgpack_store64(&p[1 + 4], sec);
237 o.via.ext.ptr = p;
238 }
239 }
240};
241
242} // namespace adaptor
243
245} // MSGPACK_API_VERSION_NAMESPACE(v1)
247
248} // namespace msgpack
249
250#endif // MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
The class template that supports continuous packing.
Definition: pack.hpp:33
packer< Stream > & pack_ext(size_t l, int8_t type)
Packing ext header, type, and length.
Definition: pack.hpp:1316
packer< Stream > & pack_ext_body(const char *b, uint32_t l)
Packing ext body.
Definition: pack.hpp:1375
Definition: object_fwd.hpp:231
void * allocate_no_align(size_t size)
Definition: cpp03_zone.hpp:270
@ EXT
Definition: object_fwd_decl.hpp:42
Definition: adaptor_base.hpp:15
std::chrono::time_point< Clock, Duration > operator()(msgpack::object const &o) const
Definition: chrono.hpp:32
Definition: object_fwd_decl.hpp:61
msgpack::object const & operator()(msgpack::object const &o, std::chrono::time_point< Clock, Duration > &v) const
Definition: chrono.hpp:84
Definition: adaptor_base.hpp:27
void operator()(msgpack::object::with_zone &o, const std::chrono::time_point< Clock, Duration > &v) const
Definition: chrono.hpp:191
Definition: adaptor_base.hpp:43
msgpack::packer< Stream > & operator()(msgpack::packer< Stream > &o, std::chrono::time_point< Clock, Duration > const &v) const
Definition: chrono.hpp:141
Definition: adaptor_base.hpp:32
Definition: object.hpp:35
msgpack::zone & zone
Definition: object.hpp:37
int8_t type() const
Definition: object_fwd.hpp:43
const char * ptr
Definition: object_fwd.hpp:46
const char * data() const
Definition: object_fwd.hpp:44
uint32_t size
Definition: object_fwd.hpp:45
Object class that corresponding to MessagePack format object.
Definition: object_fwd.hpp:75
union_type via
Definition: object_fwd.hpp:93
msgpack::type::object_type type
Definition: object_fwd.hpp:92
#define _msgpack_load64(cast, from, to)
Definition: sysdep.hpp:180
#define _msgpack_store32(to, num)
Definition: sysdep.hpp:187
#define _msgpack_store64(to, num)
Definition: sysdep.hpp:189
#define _msgpack_load32(cast, from, to)
Definition: sysdep.hpp:176
msgpack::object_ext ext
Definition: object_fwd.hpp:89
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:66