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 namespace msgpack {
21 
25 
26 namespace adaptor {
27 
28 template <>
29 struct as<std::chrono::system_clock::time_point> {
30  typename std::chrono::system_clock::time_point operator()(msgpack::object const& o) const {
31  if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
32  if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
33  std::chrono::system_clock::time_point tp;
34  switch(o.via.ext.size) {
35  case 4: {
36  uint32_t sec;
37  _msgpack_load32(uint32_t, o.via.ext.data(), &sec);
38  tp += std::chrono::seconds(sec);
39  } break;
40  case 8: {
41  uint64_t value;
42  _msgpack_load64(uint64_t, o.via.ext.data(), &value);
43  uint32_t nanosec = static_cast<uint32_t>(value >> 34);
44  uint64_t sec = value & 0x00000003ffffffffLL;
45  tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(
46  std::chrono::nanoseconds(nanosec));
47  tp += std::chrono::seconds(sec);
48  } break;
49  case 12: {
50  uint32_t nanosec;
51  _msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
52  int64_t sec;
53  _msgpack_load64(int64_t, o.via.ext.data() + 4, &sec);
54  tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(
55  std::chrono::nanoseconds(nanosec));
56  tp += std::chrono::seconds(sec);
57  } break;
58  default:
59  throw msgpack::type_error();
60  }
61  return tp;
62  }
63 };
64 
65 template <>
66 struct convert<std::chrono::system_clock::time_point> {
67  msgpack::object const& operator()(msgpack::object const& o, std::chrono::system_clock::time_point& v) const {
68  if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
69  if(o.via.ext.type() != -1) { throw msgpack::type_error(); }
70  std::chrono::system_clock::time_point tp;
71  switch(o.via.ext.size) {
72  case 4: {
73  uint32_t sec;
74  _msgpack_load32(uint32_t, o.via.ext.data(), &sec);
75  tp += std::chrono::seconds(sec);
76  v = tp;
77  } break;
78  case 8: {
79  uint64_t value;
80  _msgpack_load64(uint64_t, o.via.ext.data(), &value);
81  uint32_t nanosec = static_cast<uint32_t>(value >> 34);
82  uint64_t sec = value & 0x00000003ffffffffLL;
83  tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(
84  std::chrono::nanoseconds(nanosec));
85  tp += std::chrono::seconds(sec);
86  v = tp;
87  } break;
88  case 12: {
89  uint32_t nanosec;
90  _msgpack_load32(uint32_t, o.via.ext.data(), &nanosec);
91  int64_t sec;
92  _msgpack_load64(int64_t, o.via.ext.data() + 4, &sec);
93  tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(
94  std::chrono::nanoseconds(nanosec));
95  tp += std::chrono::seconds(sec);
96  v = tp;
97  } break;
98  default:
99  throw msgpack::type_error();
100  }
101  return o;
102  }
103 };
104 
105 template <>
106 struct pack<std::chrono::system_clock::time_point> {
107  template <typename Stream>
108  msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::chrono::system_clock::time_point& v) const {
109  int64_t count = static_cast<int64_t>(v.time_since_epoch().count());
110 
111  int64_t nano_num =
112  std::chrono::system_clock::duration::period::ratio::num *
113  (1000000000 / std::chrono::system_clock::duration::period::ratio::den);
114 
115  int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
116  int64_t sec = 0;
117  if (nanosec < 0) {
118  nanosec = 1000000000 + nanosec;
119  --sec;
120  }
121  sec += count
122  * std::chrono::system_clock::duration::period::ratio::num
123  / std::chrono::system_clock::duration::period::ratio::den;
124  if ((sec >> 34) == 0) {
125  uint64_t data64 = (static_cast<uint64_t>(nanosec) << 34) | static_cast<uint64_t>(sec);
126  if ((data64 & 0xffffffff00000000L) == 0) {
127  // timestamp 32
128  o.pack_ext(4, -1);
129  uint32_t data32 = static_cast<uint32_t>(data64);
130  char buf[4];
131  _msgpack_store32(buf, data32);
132  o.pack_ext_body(buf, 4);
133  }
134  else {
135  // timestamp 64
136  o.pack_ext(8, -1);
137  char buf[8];
138  _msgpack_store64(buf, data64);
139  o.pack_ext_body(buf, 8);
140  }
141  }
142  else {
143  // timestamp 96
144  o.pack_ext(12, -1);
145  char buf[12];
146  _msgpack_store32(&buf[0], static_cast<uint32_t>(nanosec));
147  _msgpack_store64(&buf[4], sec);
148  o.pack_ext_body(buf, 12);
149  }
150  return o;
151  }
152 };
153 
154 template <>
155 struct object_with_zone<std::chrono::system_clock::time_point> {
156  void operator()(msgpack::object::with_zone& o, const std::chrono::system_clock::time_point& v) const {
157  int64_t count = static_cast<int64_t>(v.time_since_epoch().count());
158 
159  int64_t nano_num =
160  std::chrono::system_clock::duration::period::ratio::num *
161  (1000000000 / std::chrono::system_clock::duration::period::ratio::den);
162 
163  int64_t nanosec = count % (1000000000 / nano_num) * nano_num;
164  int64_t sec = 0;
165  if (nanosec < 0) {
166  nanosec = 1000000000 + nanosec;
167  --sec;
168  }
169  sec += count
170  * std::chrono::system_clock::duration::period::ratio::num
171  / std::chrono::system_clock::duration::period::ratio::den;
172  if ((sec >> 34) == 0) {
173  uint64_t data64 = (static_cast<uint64_t>(nanosec) << 34) | static_cast<uint64_t>(sec);
174  if ((data64 & 0xffffffff00000000L) == 0) {
175  // timestamp 32
177  o.via.ext.size = 4;
178  char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
179  p[0] = static_cast<char>(-1);
180  uint32_t data32 = static_cast<uint32_t>(data64);
181  _msgpack_store32(&p[1], data32);
182  o.via.ext.ptr = p;
183  }
184  else {
185  // timestamp 64
187  o.via.ext.size = 8;
188  char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
189  p[0] = static_cast<char>(-1);
190  _msgpack_store64(&p[1], data64);
191  o.via.ext.ptr = p;
192  }
193  }
194  else {
195  // timestamp 96
197  o.via.ext.size = 12;
198  char* p = static_cast<char*>(o.zone.allocate_no_align(o.via.ext.size + 1));
199  p[0] = static_cast<char>(-1);
200  _msgpack_store32(&p[1], static_cast<uint32_t>(nanosec));
201  _msgpack_store64(&p[1 + 4], sec);
202  o.via.ext.ptr = p;
203  }
204  }
205 };
206 
207 } // namespace adaptor
208 
210 } // MSGPACK_API_VERSION_NAMESPACE(v1)
212 
213 } // namespace msgpack
214 
215 #endif // MSGPACK_V1_TYPE_CPP11_CHRONO_HPP
msgpack::adaptor::object_with_zone< std::chrono::system_clock::time_point >::operator()
void operator()(msgpack::object::with_zone &o, const std::chrono::system_clock::time_point &v) const
Definition: chrono.hpp:156
msgpack::adaptor::as< std::chrono::system_clock::time_point >::operator()
std::chrono::system_clock::time_point operator()(msgpack::object const &o) const
Definition: chrono.hpp:30
msgpack::packer::pack_ext
packer< Stream > & pack_ext(size_t l, int8_t type)
Packing ext header, type, and length.
Definition: pack.hpp:1316
msgpack::object_ext::data
const char * data() const
Definition: object_fwd.hpp:44
msgpack::packer
The class template that supports continuous packing.
Definition: adaptor_base_decl.hpp:24
msgpack::object_ext::ptr
const char * ptr
Definition: object_fwd.hpp:46
msgpack::adaptor::object_with_zone
Definition: adaptor_base.hpp:43
msgpack
Definition: adaptor_base.hpp:15
msgpack::adaptor::convert
Definition: adaptor_base.hpp:27
msgpack::object_ext::size
uint32_t size
Definition: object_fwd.hpp:45
MSGPACK_API_VERSION_NAMESPACE
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:58
msgpack::object::via
union_type via
Definition: object_fwd.hpp:93
adaptor_base.hpp
msgpack::adaptor::as
Definition: object_fwd_decl.hpp:62
versioning.hpp
msgpack::adaptor::pack< std::chrono::system_clock::time_point >::operator()
msgpack::packer< Stream > & operator()(msgpack::packer< Stream > &o, const std::chrono::system_clock::time_point &v) const
Definition: chrono.hpp:108
msgpack::object::union_type::ext
msgpack::object_ext ext
Definition: object_fwd.hpp:89
msgpack::type::EXT
@ EXT
Definition: object_fwd_decl.hpp:43
check_container_size.hpp
msgpack::type_error
Definition: object_fwd.hpp:236
msgpack::adaptor::pack
Definition: adaptor_base.hpp:32
msgpack::packer::pack_ext_body
packer< Stream > & pack_ext_body(const char *b, uint32_t l)
Packing ext body.
Definition: pack.hpp:1375
msgpack::zone::allocate_no_align
void * allocate_no_align(size_t size)
Definition: cpp03_zone.hpp:261
msgpack::object
Object class that corresponding to MessagePack format object.
Definition: object_fwd.hpp:75
v2::object::with_zone::zone
msgpack::zone & zone
Definition: object.hpp:37
v2::object::with_zone
Definition: object.hpp:35
msgpack::object_ext::type
int8_t type() const
Definition: object_fwd.hpp:43
msgpack::object::type
msgpack::type::object_type type
Definition: object_fwd.hpp:92
msgpack::adaptor::convert< std::chrono::system_clock::time_point >::operator()
msgpack::object const & operator()(msgpack::object const &o, std::chrono::system_clock::time_point &v) const
Definition: chrono.hpp:67