Skip to content

Commit 3aae588

Browse files
authored
Merge pull request #706 from redboltz/fix_638_3
Implemented #638.
2 parents c58a565 + cb2dcb1 commit 3aae588

File tree

6 files changed

+486
-0
lines changed

6 files changed

+486
-0
lines changed

Files.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ IF (MSGPACK_ENABLE_CXX)
173173
include/msgpack/adaptor/cpp11/array.hpp
174174
include/msgpack/adaptor/cpp11/array_char.hpp
175175
include/msgpack/adaptor/cpp11/array_unsigned_char.hpp
176+
include/msgpack/adaptor/cpp11/chrono.hpp
176177
include/msgpack/adaptor/cpp11/forward_list.hpp
177178
include/msgpack/adaptor/cpp11/reference_wrapper.hpp
178179
include/msgpack/adaptor/cpp11/shared_ptr.hpp
@@ -529,6 +530,7 @@ IF (MSGPACK_ENABLE_CXX)
529530
include/msgpack/v1/adaptor/cpp11/array.hpp
530531
include/msgpack/v1/adaptor/cpp11/array_char.hpp
531532
include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp
533+
include/msgpack/v1/adaptor/cpp11/chrono.hpp
532534
include/msgpack/v1/adaptor/cpp11/forward_list.hpp
533535
include/msgpack/v1/adaptor/cpp11/reference_wrapper.hpp
534536
include/msgpack/v1/adaptor/cpp11/shared_ptr.hpp
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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_TYPE_CPP11_CHRONO_HPP
12+
#define MSGPACK_TYPE_CPP11_CHRONO_HPP
13+
14+
#include "msgpack/v1/adaptor/cpp11/chrono.hpp"
15+
16+
#endif // MSGPACK_TYPE_CPP11_CHRONO_HPP

include/msgpack/type.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "adaptor/cpp11/array.hpp"
3535
#include "adaptor/cpp11/array_char.hpp"
3636
#include "adaptor/cpp11/array_unsigned_char.hpp"
37+
#include "adaptor/cpp11/chrono.hpp"
3738
#include "adaptor/cpp11/forward_list.hpp"
3839
#include "adaptor/cpp11/reference_wrapper.hpp"
3940
#include "adaptor/cpp11/shared_ptr.hpp"
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
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"
15+
#include "msgpack/adaptor/adaptor_base.hpp"
16+
#include "msgpack/adaptor/check_container_size.hpp"
17+
18+
#include <chrono>
19+
20+
namespace msgpack {
21+
22+
/// @cond
23+
MSGPACK_API_VERSION_NAMESPACE(v1) {
24+
/// @endcond
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 & 0x00000003ffffffffL;
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 & 0x00000003ffffffffL;
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 = (nanosec << 34) | 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 = (nanosec << 34) | sec;
174+
if ((data64 & 0xffffffff00000000L) == 0) {
175+
// timestamp 32
176+
o.type = msgpack::type::EXT;
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] = -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
186+
o.type = msgpack::type::EXT;
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] = -1;
190+
_msgpack_store64(&p[1], data64);
191+
o.via.ext.ptr = p;
192+
}
193+
}
194+
else {
195+
// timestamp 96
196+
o.type = msgpack::type::EXT;
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] = -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+
209+
/// @cond
210+
} // MSGPACK_API_VERSION_NAMESPACE(v1)
211+
/// @endcond
212+
213+
} // namespace msgpack
214+
215+
#endif // MSGPACK_V1_TYPE_CPP11_CHRONO_HPP

0 commit comments

Comments
 (0)