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