/src/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2013-2023 Daniel Parker |
2 | | // Distributed under the Boost license, Version 1.0. |
3 | | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
4 | | |
5 | | // See https://github.com/danielaparker/jsoncons for latest version |
6 | | |
7 | | #ifndef JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP |
8 | | #define JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP |
9 | | |
10 | | #include <string> |
11 | | #include <vector> |
12 | | #include <limits> // std::numeric_limits |
13 | | #include <memory> |
14 | | #include <utility> // std::move |
15 | | #include <jsoncons/json_exception.hpp> |
16 | | #include <jsoncons/json_visitor.hpp> |
17 | | #include <jsoncons/config/jsoncons_config.hpp> |
18 | | #include <jsoncons/sink.hpp> |
19 | | #include <jsoncons/detail/parse_number.hpp> |
20 | | #include <jsoncons_ext/msgpack/msgpack_type.hpp> |
21 | | #include <jsoncons_ext/msgpack/msgpack_error.hpp> |
22 | | #include <jsoncons_ext/msgpack/msgpack_options.hpp> |
23 | | |
24 | | namespace jsoncons { |
25 | | namespace msgpack { |
26 | | |
27 | | enum class msgpack_container_type {object, array}; |
28 | | |
29 | | template<class Sink=jsoncons::binary_stream_sink,class Allocator=std::allocator<char>> |
30 | | class basic_msgpack_encoder final : public basic_json_visitor<char> |
31 | | { |
32 | | enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 }; |
33 | | |
34 | | static constexpr int64_t nanos_in_milli = 1000000; |
35 | | static constexpr int64_t nanos_in_second = 1000000000; |
36 | | static constexpr int64_t millis_in_second = 1000; |
37 | | public: |
38 | | using allocator_type = Allocator; |
39 | | using char_type = char; |
40 | | using typename basic_json_visitor<char>::string_view_type; |
41 | | using sink_type = Sink; |
42 | | |
43 | | private: |
44 | | struct stack_item |
45 | | { |
46 | | msgpack_container_type type_; |
47 | | std::size_t length_; |
48 | | std::size_t count_; |
49 | | |
50 | | stack_item(msgpack_container_type type, std::size_t length = 0) noexcept |
51 | | : type_(type), length_(length), count_(0) |
52 | 136k | { |
53 | 136k | } |
54 | | |
55 | | std::size_t length() const |
56 | 225k | { |
57 | 225k | return length_; |
58 | 225k | } |
59 | | |
60 | | std::size_t count() const |
61 | 225k | { |
62 | 225k | return count_; |
63 | 225k | } |
64 | | |
65 | | bool is_object() const |
66 | | { |
67 | | return type_ == msgpack_container_type::object; |
68 | | } |
69 | | }; |
70 | | |
71 | | Sink sink_; |
72 | | const msgpack_encode_options options_; |
73 | | allocator_type alloc_; |
74 | | |
75 | | std::vector<stack_item> stack_; |
76 | | int nesting_depth_; |
77 | | |
78 | | // Noncopyable and nonmoveable |
79 | | basic_msgpack_encoder(const basic_msgpack_encoder&) = delete; |
80 | | basic_msgpack_encoder& operator=(const basic_msgpack_encoder&) = delete; |
81 | | public: |
82 | | explicit basic_msgpack_encoder(Sink&& sink, |
83 | | const Allocator& alloc = Allocator()) |
84 | | : basic_msgpack_encoder(std::forward<Sink>(sink), msgpack_encode_options(), alloc) |
85 | 6.04k | { |
86 | 6.04k | } |
87 | | |
88 | | explicit basic_msgpack_encoder(Sink&& sink, |
89 | | const msgpack_encode_options& options, |
90 | | const Allocator& alloc = Allocator()) |
91 | | : sink_(std::forward<Sink>(sink)), |
92 | | options_(options), |
93 | | alloc_(alloc), |
94 | | nesting_depth_(0) |
95 | 6.04k | { |
96 | 6.04k | } |
97 | | |
98 | | ~basic_msgpack_encoder() noexcept |
99 | 6.04k | { |
100 | 6.04k | sink_.flush(); |
101 | 6.04k | } |
102 | | |
103 | | void reset() |
104 | | { |
105 | | stack_.clear(); |
106 | | nesting_depth_ = 0; |
107 | | } |
108 | | |
109 | | void reset(Sink&& sink) |
110 | | { |
111 | | sink_ = std::move(sink); |
112 | | reset(); |
113 | | } |
114 | | |
115 | | private: |
116 | | // Implementing methods |
117 | | |
118 | | void visit_flush() override |
119 | 1.41k | { |
120 | 1.41k | sink_.flush(); |
121 | 1.41k | } |
122 | | |
123 | | bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override |
124 | 0 | { |
125 | 0 | ec = msgpack_errc::object_length_required; |
126 | 0 | return false; |
127 | 0 | } |
128 | | |
129 | | bool visit_begin_object(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override |
130 | 54.9k | { |
131 | 54.9k | if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) |
132 | 0 | { |
133 | 0 | ec = msgpack_errc::max_nesting_depth_exceeded; |
134 | 0 | return false; |
135 | 0 | } |
136 | 54.9k | stack_.emplace_back(msgpack_container_type::object, length); |
137 | | |
138 | 54.9k | if (length <= 15) |
139 | 53.3k | { |
140 | | // fixmap |
141 | 53.3k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf)); |
142 | 53.3k | } |
143 | 1.55k | else if (length <= 65535) |
144 | 672 | { |
145 | | // map 16 |
146 | 672 | sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type); |
147 | 672 | binary::native_to_big(static_cast<uint16_t>(length), |
148 | 672 | std::back_inserter(sink_)); |
149 | 672 | } |
150 | 882 | else if (length <= 4294967295) |
151 | 882 | { |
152 | | // map 32 |
153 | 882 | sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type); |
154 | 882 | binary::native_to_big(static_cast<uint32_t>(length), |
155 | 882 | std::back_inserter(sink_)); |
156 | 882 | } |
157 | | |
158 | 54.9k | return true; |
159 | 54.9k | } |
160 | | |
161 | | bool visit_end_object(const ser_context&, std::error_code& ec) override |
162 | 48.1k | { |
163 | 48.1k | JSONCONS_ASSERT(!stack_.empty()); |
164 | 48.1k | --nesting_depth_; |
165 | | |
166 | 48.1k | if (stack_.back().count() < stack_.back().length()) |
167 | 20 | { |
168 | 20 | ec = msgpack_errc::too_few_items; |
169 | 20 | return false; |
170 | 20 | } |
171 | 48.1k | else if (stack_.back().count() > stack_.back().length()) |
172 | 0 | { |
173 | 0 | ec = msgpack_errc::too_many_items; |
174 | 0 | return false; |
175 | 0 | } |
176 | | |
177 | 48.1k | stack_.pop_back(); |
178 | 48.1k | end_value(); |
179 | 48.1k | return true; |
180 | 48.1k | } |
181 | | |
182 | | bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override |
183 | 0 | { |
184 | 0 | ec = msgpack_errc::array_length_required; |
185 | 0 | return false; |
186 | 0 | } |
187 | | |
188 | | bool visit_begin_array(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override |
189 | 81.3k | { |
190 | 81.3k | if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) |
191 | 0 | { |
192 | 0 | ec = msgpack_errc::max_nesting_depth_exceeded; |
193 | 0 | return false; |
194 | 0 | } |
195 | 81.3k | stack_.emplace_back(msgpack_container_type::array, length); |
196 | 81.3k | if (length <= 15) |
197 | 78.1k | { |
198 | | // fixarray |
199 | 78.1k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf)); |
200 | 78.1k | } |
201 | 3.17k | else if (length <= (std::numeric_limits<uint16_t>::max)()) |
202 | 1.61k | { |
203 | | // array 16 |
204 | 1.61k | sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type); |
205 | 1.61k | binary::native_to_big(static_cast<uint16_t>(length),std::back_inserter(sink_)); |
206 | 1.61k | } |
207 | 1.56k | else if (length <= (std::numeric_limits<uint32_t>::max)()) |
208 | 1.56k | { |
209 | | // array 32 |
210 | 1.56k | sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type); |
211 | 1.56k | binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_)); |
212 | 1.56k | } |
213 | 81.3k | return true; |
214 | 81.3k | } |
215 | | |
216 | | bool visit_end_array(const ser_context&, std::error_code& ec) override |
217 | 64.8k | { |
218 | 64.8k | JSONCONS_ASSERT(!stack_.empty()); |
219 | | |
220 | 64.8k | --nesting_depth_; |
221 | | |
222 | 64.8k | if (stack_.back().count() < stack_.back().length()) |
223 | 19 | { |
224 | 19 | ec = msgpack_errc::too_few_items; |
225 | 19 | return false; |
226 | 19 | } |
227 | 64.7k | else if (stack_.back().count() > stack_.back().length()) |
228 | 0 | { |
229 | 0 | ec = msgpack_errc::too_many_items; |
230 | 0 | return false; |
231 | 0 | } |
232 | | |
233 | 64.7k | stack_.pop_back(); |
234 | 64.7k | end_value(); |
235 | 64.7k | return true; |
236 | 64.8k | } |
237 | | |
238 | | bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override |
239 | 393k | { |
240 | 393k | write_string_value(name); |
241 | 393k | return true; |
242 | 393k | } |
243 | | |
244 | | bool visit_null(semantic_tag, const ser_context&, std::error_code&) override |
245 | 5.51k | { |
246 | | // nil |
247 | 5.51k | sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type); |
248 | 5.51k | end_value(); |
249 | 5.51k | return true; |
250 | 5.51k | } |
251 | | |
252 | | void write_timestamp(int64_t seconds, int64_t nanoseconds) |
253 | 35.2k | { |
254 | 35.2k | if ((seconds >> 34) == 0) |
255 | 25.8k | { |
256 | 25.8k | uint64_t data64 = (nanoseconds << 34) | seconds; |
257 | 25.8k | if ((data64 & 0xffffffff00000000L) == 0) |
258 | 2.09k | { |
259 | | // timestamp 32 |
260 | 2.09k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type); |
261 | 2.09k | sink_.push_back(0xff); |
262 | 2.09k | binary::native_to_big(static_cast<uint32_t>(data64), std::back_inserter(sink_)); |
263 | 2.09k | } |
264 | 23.7k | else |
265 | 23.7k | { |
266 | | // timestamp 64 |
267 | 23.7k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type); |
268 | 23.7k | sink_.push_back(0xff); |
269 | 23.7k | binary::native_to_big(static_cast<uint64_t>(data64), std::back_inserter(sink_)); |
270 | 23.7k | } |
271 | 25.8k | } |
272 | 9.33k | else |
273 | 9.33k | { |
274 | | // timestamp 96 |
275 | 9.33k | sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type); |
276 | 9.33k | sink_.push_back(0x0c); // 12 |
277 | 9.33k | sink_.push_back(0xff); |
278 | 9.33k | binary::native_to_big(static_cast<uint32_t>(nanoseconds), std::back_inserter(sink_)); |
279 | 9.33k | binary::native_to_big(static_cast<uint64_t>(seconds), std::back_inserter(sink_)); |
280 | 9.33k | } |
281 | 35.2k | } |
282 | | |
283 | | bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) override |
284 | 38.4k | { |
285 | 38.4k | switch (tag) |
286 | 38.4k | { |
287 | 0 | case semantic_tag::epoch_second: |
288 | 0 | { |
289 | 0 | int64_t seconds; |
290 | 0 | auto result = jsoncons::detail::to_integer(sv.data(), sv.length(), seconds); |
291 | 0 | if (!result) |
292 | 0 | { |
293 | 0 | ec = msgpack_errc::invalid_timestamp; |
294 | 0 | return false; |
295 | 0 | } |
296 | 0 | write_timestamp(seconds, 0); |
297 | 0 | break; |
298 | 0 | } |
299 | 0 | case semantic_tag::epoch_milli: |
300 | 0 | { |
301 | 0 | bigint n = bigint::from_string(sv.data(), sv.length()); |
302 | 0 | if (n != 0) |
303 | 0 | { |
304 | 0 | bigint q; |
305 | 0 | bigint rem; |
306 | 0 | n.divide(millis_in_second, q, rem, true); |
307 | 0 | int64_t seconds = static_cast<int64_t>(q); |
308 | 0 | int64_t nanoseconds = static_cast<int64_t>(rem) * nanos_in_milli; |
309 | 0 | if (nanoseconds < 0) |
310 | 0 | { |
311 | 0 | nanoseconds = -nanoseconds; |
312 | 0 | } |
313 | 0 | write_timestamp(seconds, nanoseconds); |
314 | 0 | } |
315 | 0 | else |
316 | 0 | { |
317 | 0 | write_timestamp(0, 0); |
318 | 0 | } |
319 | 0 | break; |
320 | 0 | } |
321 | 33.8k | case semantic_tag::epoch_nano: |
322 | 33.8k | { |
323 | 33.8k | bigint n = bigint::from_string(sv.data(), sv.length()); |
324 | 33.8k | if (n != 0) |
325 | 33.2k | { |
326 | 33.2k | bigint q; |
327 | 33.2k | bigint rem; |
328 | 33.2k | n.divide(nanos_in_second, q, rem, true); |
329 | 33.2k | int64_t seconds = static_cast<int64_t>(q); |
330 | 33.2k | int64_t nanoseconds = static_cast<int64_t>(rem); |
331 | 33.2k | if (nanoseconds < 0) |
332 | 6.01k | { |
333 | 6.01k | nanoseconds = -nanoseconds; |
334 | 6.01k | } |
335 | 33.2k | write_timestamp(seconds, nanoseconds); |
336 | 33.2k | } |
337 | 569 | else |
338 | 569 | { |
339 | 569 | write_timestamp(0, 0); |
340 | 569 | } |
341 | 33.8k | break; |
342 | 0 | } |
343 | 4.59k | default: |
344 | 4.59k | { |
345 | 4.59k | write_string_value(sv); |
346 | 4.59k | end_value(); |
347 | 4.59k | break; |
348 | 0 | } |
349 | 38.4k | } |
350 | 38.4k | return true; |
351 | 38.4k | } |
352 | | |
353 | | void write_string_value(const string_view_type& sv) |
354 | 397k | { |
355 | 397k | auto sink = unicode_traits::validate(sv.data(), sv.size()); |
356 | 397k | if (sink.ec != unicode_traits::conv_errc()) |
357 | 0 | { |
358 | 0 | JSONCONS_THROW(ser_error(msgpack_errc::invalid_utf8_text_string)); |
359 | 0 | } |
360 | | |
361 | 397k | const size_t length = sv.length(); |
362 | 397k | if (length <= 31) |
363 | 395k | { |
364 | | // fixstr stores a byte array whose length is upto 31 bytes |
365 | 395k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast<uint8_t>(length)); |
366 | 395k | } |
367 | 2.15k | else if (length <= (std::numeric_limits<uint8_t>::max)()) |
368 | 787 | { |
369 | | // str 8 stores a byte array whose length is upto (2^8)-1 bytes |
370 | 787 | sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type); |
371 | 787 | sink_.push_back(static_cast<uint8_t>(length)); |
372 | 787 | } |
373 | 1.36k | else if (length <= (std::numeric_limits<uint16_t>::max)()) |
374 | 1.07k | { |
375 | | // str 16 stores a byte array whose length is upto (2^16)-1 bytes |
376 | 1.07k | sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type); |
377 | 1.07k | binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_)); |
378 | 1.07k | } |
379 | 288 | else if (length <= (std::numeric_limits<uint32_t>::max)()) |
380 | 288 | { |
381 | | // str 32 stores a byte array whose length is upto (2^32)-1 bytes |
382 | 288 | sink_.push_back(jsoncons::msgpack::msgpack_type::str32_type); |
383 | 288 | binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_)); |
384 | 288 | } |
385 | | |
386 | 397k | for (auto c : sv) |
387 | 83.4M | { |
388 | 83.4M | sink_.push_back(c); |
389 | 83.4M | } |
390 | 397k | } |
391 | | |
392 | | bool visit_byte_string(const byte_string_view& b, |
393 | | semantic_tag, |
394 | | const ser_context&, |
395 | | std::error_code&) override |
396 | 2.12k | { |
397 | | |
398 | 2.12k | const std::size_t length = b.size(); |
399 | 2.12k | if (length <= (std::numeric_limits<uint8_t>::max)()) |
400 | 1.74k | { |
401 | | // bin 8 stores a byte array whose length is upto (2^8)-1 bytes |
402 | 1.74k | sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type); |
403 | 1.74k | sink_.push_back(static_cast<uint8_t>(length)); |
404 | 1.74k | } |
405 | 374 | else if (length <= (std::numeric_limits<uint16_t>::max)()) |
406 | 324 | { |
407 | | // bin 16 stores a byte array whose length is upto (2^16)-1 bytes |
408 | 324 | sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type); |
409 | 324 | binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_)); |
410 | 324 | } |
411 | 50 | else if (length <= (std::numeric_limits<uint32_t>::max)()) |
412 | 50 | { |
413 | | // bin 32 stores a byte array whose length is upto (2^32)-1 bytes |
414 | 50 | sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type); |
415 | 50 | binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_)); |
416 | 50 | } |
417 | | |
418 | 2.12k | for (auto c : b) |
419 | 7.03M | { |
420 | 7.03M | sink_.push_back(c); |
421 | 7.03M | } |
422 | | |
423 | 2.12k | end_value(); |
424 | 2.12k | return true; |
425 | 2.12k | } |
426 | | |
427 | | bool visit_byte_string(const byte_string_view& b, |
428 | | uint64_t ext_tag, |
429 | | const ser_context&, |
430 | | std::error_code&) override |
431 | 44.3k | { |
432 | 44.3k | const std::size_t length = b.size(); |
433 | 44.3k | switch (length) |
434 | 44.3k | { |
435 | 1.25k | case 1: |
436 | 1.25k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type); |
437 | 1.25k | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
438 | 1.25k | break; |
439 | 36.5k | case 2: |
440 | 36.5k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type); |
441 | 36.5k | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
442 | 36.5k | break; |
443 | 935 | case 4: |
444 | 935 | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type); |
445 | 935 | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
446 | 935 | break; |
447 | 1.57k | case 8: |
448 | 1.57k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type); |
449 | 1.57k | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
450 | 1.57k | break; |
451 | 2.02k | case 16: |
452 | 2.02k | sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type); |
453 | 2.02k | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
454 | 2.02k | break; |
455 | 2.05k | default: |
456 | 2.05k | if (length <= (std::numeric_limits<uint8_t>::max)()) |
457 | 1.59k | { |
458 | 1.59k | sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type); |
459 | 1.59k | sink_.push_back(static_cast<uint8_t>(length)); |
460 | 1.59k | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
461 | 1.59k | } |
462 | 461 | else if (length <= (std::numeric_limits<uint16_t>::max)()) |
463 | 401 | { |
464 | 401 | sink_.push_back(jsoncons::msgpack::msgpack_type::ext16_type); |
465 | 401 | binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_)); |
466 | 401 | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
467 | 401 | } |
468 | 60 | else if (length <= (std::numeric_limits<uint32_t>::max)()) |
469 | 60 | { |
470 | 60 | sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type); |
471 | 60 | binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_)); |
472 | 60 | sink_.push_back(static_cast<uint8_t>(ext_tag)); |
473 | 60 | } |
474 | 2.05k | break; |
475 | 44.3k | } |
476 | | |
477 | 44.3k | for (auto c : b) |
478 | 8.13M | { |
479 | 8.13M | sink_.push_back(c); |
480 | 8.13M | } |
481 | | |
482 | 44.3k | end_value(); |
483 | 44.3k | return true; |
484 | 44.3k | } |
485 | | |
486 | | bool visit_double(double val, |
487 | | semantic_tag, |
488 | | const ser_context&, |
489 | | std::error_code&) override |
490 | 81.6k | { |
491 | 81.6k | float valf = (float)val; |
492 | 81.6k | if ((double)valf == val) |
493 | 53.9k | { |
494 | | // float 32 |
495 | 53.9k | sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type); |
496 | 53.9k | binary::native_to_big(valf,std::back_inserter(sink_)); |
497 | 53.9k | } |
498 | 27.6k | else |
499 | 27.6k | { |
500 | | // float 64 |
501 | 27.6k | sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type); |
502 | 27.6k | binary::native_to_big(val,std::back_inserter(sink_)); |
503 | 27.6k | } |
504 | | |
505 | | // write double |
506 | | |
507 | 81.6k | end_value(); |
508 | 81.6k | return true; |
509 | 81.6k | } |
510 | | |
511 | | bool visit_int64(int64_t val, |
512 | | semantic_tag tag, |
513 | | const ser_context&, |
514 | | std::error_code&) override |
515 | 196k | { |
516 | 196k | switch (tag) |
517 | 196k | { |
518 | 0 | case semantic_tag::epoch_second: |
519 | 0 | write_timestamp(val, 0); |
520 | 0 | break; |
521 | 0 | case semantic_tag::epoch_milli: |
522 | 0 | { |
523 | 0 | if (val != 0) |
524 | 0 | { |
525 | 0 | auto dv = std::div(val,millis_in_second); |
526 | 0 | int64_t seconds = dv.quot; |
527 | 0 | int64_t nanoseconds = dv.rem*nanos_in_milli; |
528 | 0 | if (nanoseconds < 0) |
529 | 0 | { |
530 | 0 | nanoseconds = -nanoseconds; |
531 | 0 | } |
532 | 0 | write_timestamp(seconds, nanoseconds); |
533 | 0 | } |
534 | 0 | else |
535 | 0 | { |
536 | 0 | write_timestamp(0, 0); |
537 | 0 | } |
538 | 0 | break; |
539 | 0 | } |
540 | 0 | case semantic_tag::epoch_nano: |
541 | 0 | { |
542 | 0 | if (val != 0) |
543 | 0 | { |
544 | 0 | auto dv = std::div(val,static_cast<int64_t>(nanos_in_second)); |
545 | 0 | int64_t seconds = dv.quot; |
546 | 0 | int64_t nanoseconds = dv.rem; |
547 | 0 | if (nanoseconds < 0) |
548 | 0 | { |
549 | 0 | nanoseconds = -nanoseconds; |
550 | 0 | } |
551 | 0 | write_timestamp(seconds, nanoseconds); |
552 | 0 | } |
553 | 0 | else |
554 | 0 | { |
555 | 0 | write_timestamp(0, 0); |
556 | 0 | } |
557 | 0 | break; |
558 | 0 | } |
559 | 196k | default: |
560 | 196k | { |
561 | 196k | if (val >= 0) |
562 | 2.70k | { |
563 | 2.70k | if (val <= 0x7f) |
564 | 339 | { |
565 | | // positive fixnum stores 7-bit positive integer |
566 | 339 | sink_.push_back(static_cast<uint8_t>(val)); |
567 | 339 | } |
568 | 2.36k | else if (val <= (std::numeric_limits<uint8_t>::max)()) |
569 | 507 | { |
570 | | // uint 8 stores a 8-bit unsigned integer |
571 | 507 | sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type); |
572 | 507 | sink_.push_back(static_cast<uint8_t>(val)); |
573 | 507 | } |
574 | 1.85k | else if (val <= (std::numeric_limits<uint16_t>::max)()) |
575 | 498 | { |
576 | | // uint 16 stores a 16-bit big-endian unsigned integer |
577 | 498 | sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type); |
578 | 498 | binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_)); |
579 | 498 | } |
580 | 1.36k | else if (val <= (std::numeric_limits<uint32_t>::max)()) |
581 | 967 | { |
582 | | // uint 32 stores a 32-bit big-endian unsigned integer |
583 | 967 | sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type); |
584 | 967 | binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_)); |
585 | 967 | } |
586 | 393 | else if (val <= (std::numeric_limits<int64_t>::max)()) |
587 | 393 | { |
588 | | // int 64 stores a 64-bit big-endian signed integer |
589 | 393 | sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type); |
590 | 393 | binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_)); |
591 | 393 | } |
592 | 2.70k | } |
593 | 193k | else |
594 | 193k | { |
595 | 193k | if (val >= -32) |
596 | 109k | { |
597 | | // negative fixnum stores 5-bit negative integer |
598 | 109k | binary::native_to_big(static_cast<int8_t>(val), std::back_inserter(sink_)); |
599 | 109k | } |
600 | 83.6k | else if (val >= (std::numeric_limits<int8_t>::lowest)()) |
601 | 44.7k | { |
602 | | // int 8 stores a 8-bit signed integer |
603 | 44.7k | sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type); |
604 | 44.7k | binary::native_to_big(static_cast<int8_t>(val),std::back_inserter(sink_)); |
605 | 44.7k | } |
606 | 38.9k | else if (val >= (std::numeric_limits<int16_t>::lowest)()) |
607 | 22.9k | { |
608 | | // int 16 stores a 16-bit big-endian signed integer |
609 | 22.9k | sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type); |
610 | 22.9k | binary::native_to_big(static_cast<int16_t>(val),std::back_inserter(sink_)); |
611 | 22.9k | } |
612 | 15.9k | else if (val >= (std::numeric_limits<int32_t>::lowest)()) |
613 | 12.9k | { |
614 | | // int 32 stores a 32-bit big-endian signed integer |
615 | 12.9k | sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type); |
616 | 12.9k | binary::native_to_big(static_cast<int32_t>(val),std::back_inserter(sink_)); |
617 | 12.9k | } |
618 | 3.06k | else if (val >= (std::numeric_limits<int64_t>::lowest)()) |
619 | 3.06k | { |
620 | | // int 64 stores a 64-bit big-endian signed integer |
621 | 3.06k | sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type); |
622 | 3.06k | binary::native_to_big(static_cast<int64_t>(val),std::back_inserter(sink_)); |
623 | 3.06k | } |
624 | 193k | } |
625 | 196k | } |
626 | 196k | break; |
627 | 196k | } |
628 | 196k | end_value(); |
629 | 196k | return true; |
630 | 196k | } |
631 | | |
632 | | bool visit_uint64(uint64_t val, |
633 | | semantic_tag tag, |
634 | | const ser_context&, |
635 | | std::error_code&) override |
636 | 651k | { |
637 | 651k | switch (tag) |
638 | 651k | { |
639 | 1.38k | case semantic_tag::epoch_second: |
640 | 1.38k | write_timestamp(static_cast<int64_t>(val), 0); |
641 | 1.38k | break; |
642 | 0 | case semantic_tag::epoch_milli: |
643 | 0 | { |
644 | 0 | if (val != 0) |
645 | 0 | { |
646 | 0 | auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(millis_in_second)); |
647 | 0 | int64_t seconds = dv.quot; |
648 | 0 | int64_t nanoseconds = dv.rem*nanos_in_milli; |
649 | 0 | if (nanoseconds < 0) |
650 | 0 | { |
651 | 0 | nanoseconds = -nanoseconds; |
652 | 0 | } |
653 | 0 | write_timestamp(seconds, nanoseconds); |
654 | 0 | } |
655 | 0 | else |
656 | 0 | { |
657 | 0 | write_timestamp(0, 0); |
658 | 0 | } |
659 | 0 | break; |
660 | 0 | } |
661 | 0 | case semantic_tag::epoch_nano: |
662 | 0 | { |
663 | 0 | if (val != 0) |
664 | 0 | { |
665 | 0 | auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(nanos_in_second)); |
666 | 0 | int64_t seconds = dv.quot; |
667 | 0 | int64_t nanoseconds = dv.rem; |
668 | 0 | if (nanoseconds < 0) |
669 | 0 | { |
670 | 0 | nanoseconds = -nanoseconds; |
671 | 0 | } |
672 | 0 | write_timestamp(seconds, nanoseconds); |
673 | 0 | } |
674 | 0 | else |
675 | 0 | { |
676 | 0 | write_timestamp(0, 0); |
677 | 0 | } |
678 | 0 | break; |
679 | 0 | } |
680 | 649k | default: |
681 | 649k | { |
682 | 649k | if (val <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)())) |
683 | 563k | { |
684 | | // positive fixnum stores 7-bit positive integer |
685 | 563k | sink_.push_back(static_cast<uint8_t>(val)); |
686 | 563k | } |
687 | 86.0k | else if (val <= (std::numeric_limits<uint8_t>::max)()) |
688 | 59.4k | { |
689 | | // uint 8 stores a 8-bit unsigned integer |
690 | 59.4k | sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type); |
691 | 59.4k | sink_.push_back(static_cast<uint8_t>(val)); |
692 | 59.4k | } |
693 | 26.6k | else if (val <= (std::numeric_limits<uint16_t>::max)()) |
694 | 543 | { |
695 | | // uint 16 stores a 16-bit big-endian unsigned integer |
696 | 543 | sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type); |
697 | 543 | binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_)); |
698 | 543 | } |
699 | 26.1k | else if (val <= (std::numeric_limits<uint32_t>::max)()) |
700 | 24.8k | { |
701 | | // uint 32 stores a 32-bit big-endian unsigned integer |
702 | 24.8k | sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type); |
703 | 24.8k | binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_)); |
704 | 24.8k | } |
705 | 1.23k | else if (val <= (std::numeric_limits<uint64_t>::max)()) |
706 | 1.23k | { |
707 | | // uint 64 stores a 64-bit big-endian unsigned integer |
708 | 1.23k | sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type); |
709 | 1.23k | binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_)); |
710 | 1.23k | } |
711 | 649k | break; |
712 | 0 | } |
713 | 651k | } |
714 | 651k | end_value(); |
715 | 651k | return true; |
716 | 651k | } |
717 | | |
718 | | bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override |
719 | 53.6k | { |
720 | | // true and false |
721 | 53.6k | sink_.push_back(static_cast<uint8_t>(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type)); |
722 | | |
723 | 53.6k | end_value(); |
724 | 53.6k | return true; |
725 | 53.6k | } |
726 | | |
727 | | void end_value() |
728 | 1.15M | { |
729 | 1.15M | if (!stack_.empty()) |
730 | 1.15M | { |
731 | 1.15M | ++stack_.back().count_; |
732 | 1.15M | } |
733 | 1.15M | } |
734 | | }; |
735 | | |
736 | | using msgpack_stream_encoder = basic_msgpack_encoder<jsoncons::binary_stream_sink>; |
737 | | using msgpack_bytes_encoder = basic_msgpack_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>; |
738 | | |
739 | | #if !defined(JSONCONS_NO_DEPRECATED) |
740 | | JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_bytes_serializer; |
741 | | |
742 | | template<class Sink=jsoncons::binary_stream_sink> |
743 | | using basic_msgpack_serializer = basic_msgpack_encoder<Sink>; |
744 | | |
745 | | JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_encoder; |
746 | | JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_serializer; |
747 | | JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_buffer_serializer; |
748 | | #endif |
749 | | |
750 | | } // namespace msgpack |
751 | | } // namespace jsoncons |
752 | | |
753 | | #endif |