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 
14 #include "msgpack/versioning.hpp"
17 
18 #include <chrono>
19 
20 #include <boost/numeric/conversion/cast.hpp>
21 
22 namespace msgpack {
23 
27 
28 namespace adaptor {
29 
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 {
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 
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 {
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 
138 template <typename Clock, typename Duration>
139 struct 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 
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());
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:271
@ 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
const char * data() const
Definition: object_fwd.hpp:44
int8_t type() const
Definition: object_fwd.hpp:43
const char * ptr
Definition: object_fwd.hpp:46
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:172
#define _msgpack_store32(to, num)
Definition: sysdep.hpp:179
#define _msgpack_store64(to, num)
Definition: sysdep.hpp:181
#define _msgpack_load32(cast, from, to)
Definition: sysdep.hpp:168
msgpack::object_ext ext
Definition: object_fwd.hpp:89
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:66