Coverage Report

Created: 2026-02-26 07:06

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