Coverage Report

Created: 2026-10-14 06:51

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/nonstd/compiler_support.hpp>
20
#include <jsoncons/config/jsoncons_config.hpp>
21
#include <jsoncons/utility/number_readers.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_common.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 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
            container_type type_;
60
            std::size_t length_;
61
            std::size_t index_{0};
62
63
            stack_item(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
209k
            {
70
209k
                return length_;
71
209k
            }
72
73
            std::size_t count() const
74
209k
            {
75
209k
                return is_object() ? index_/2 : index_;
76
209k
            }
77
78
            bool is_object() const
79
222k
            {
80
222k
                return type_ == container_type::object;
81
222k
            }
82
83
            bool is_array() const
84
93.5k
            {
85
93.5k
                return type_ == container_type::array;
86
93.5k
            }
87
        };
88
89
        Sink sink_;
90
        std::size_t max_nesting_depth_;
91
        allocator_type alloc_;
92
93
        std::vector<stack_item> stack_;
94
    public:
95
96
        // Noncopyable and nonmoveable
97
        basic_msgpack_encoder(const basic_msgpack_encoder&) = delete;
98
        basic_msgpack_encoder(basic_msgpack_encoder&&) = delete;
99
100
        explicit basic_msgpack_encoder(Sink&& sink, const Allocator& alloc = Allocator())
101
6.52k
           : basic_msgpack_encoder(std::forward<Sink>(sink), msgpack_encode_options(), alloc)
102
6.52k
        {
103
6.52k
        }
104
105
        explicit basic_msgpack_encoder(Sink&& sink, 
106
            const msgpack_encode_options& options, 
107
            const Allocator& alloc = Allocator())
108
6.52k
           : sink_(std::forward<Sink>(sink)),
109
6.52k
             max_nesting_depth_(static_cast<std::size_t>(options.max_nesting_depth())),
110
6.52k
             alloc_(alloc)
111
6.52k
        {
112
6.52k
        }
113
114
        ~basic_msgpack_encoder() noexcept
115
6.52k
        {
116
6.52k
            sink_.flush();
117
6.52k
        }
118
119
        basic_msgpack_encoder& operator=(const basic_msgpack_encoder&) = delete;
120
        basic_msgpack_encoder& operator=(basic_msgpack_encoder&&) = delete;
121
122
        void reset()
123
        {
124
            stack_.clear();
125
        }
126
127
        void reset(Sink&& sink)
128
        {
129
            sink_ = std::move(sink);
130
            reset();
131
        }
132
133
    private:
134
        // Implementing methods
135
136
        void visit_flush() final
137
1.71k
        {
138
1.71k
            sink_.flush();
139
1.71k
        }
140
141
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) final
142
0
        {
143
0
            ec = msgpack_errc::object_length_required;
144
0
            JSONCONS_VISITOR_RETURN;
145
0
        }
146
147
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) final
148
20.4k
        {
149
20.4k
            if (JSONCONS_UNLIKELY(stack_.size() >= max_nesting_depth_))
150
1
            {
151
1
                ec = msgpack_errc::max_nesting_depth_exceeded;
152
1
                JSONCONS_VISITOR_RETURN;
153
1
            } 
154
20.4k
            stack_.emplace_back(container_type::object, length);
155
156
20.4k
            if (length <= 15)
157
18.2k
            {
158
                // fixmap
159
18.2k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf));
160
18.2k
            }
161
2.17k
            else if (length <= 65535)
162
747
            {
163
                // map 16
164
747
                sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type);
165
747
                binary::native_to_big(static_cast<uint16_t>(length), 
166
747
                                      std::back_inserter(sink_));
167
747
            }
168
1.43k
            else if (length <= (std::numeric_limits<uint32_t>::max)())
169
1.43k
            {
170
                // map 32
171
1.43k
                sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type);
172
1.43k
                binary::native_to_big(static_cast<uint32_t>(length),
173
1.43k
                                      std::back_inserter(sink_));
174
1.43k
            }
175
176
20.4k
            JSONCONS_VISITOR_RETURN;
177
20.4k
        }
178
179
        JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context&, std::error_code& ec) final
180
12.0k
        {
181
12.0k
            if (JSONCONS_UNLIKELY(stack_.empty() || !stack_.back().is_object()))
182
196
            {
183
196
                ec = msgpack_errc::unmatched_end_object;
184
196
                JSONCONS_VISITOR_RETURN;
185
196
            }
186
187
11.8k
            if (stack_.back().count() < stack_.back().length())
188
216
            {
189
216
                ec = msgpack_errc::too_few_items;
190
216
                JSONCONS_VISITOR_RETURN;
191
216
            }
192
11.6k
            else if (stack_.back().count() > stack_.back().length())
193
0
            {
194
0
                ec = msgpack_errc::too_many_items;
195
0
                JSONCONS_VISITOR_RETURN;
196
0
            }
197
198
11.6k
            stack_.pop_back();
199
11.6k
            end_value();
200
11.6k
            JSONCONS_VISITOR_RETURN;
201
11.8k
        }
202
203
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) final
204
0
        {
205
0
            ec = msgpack_errc::array_length_required;
206
0
            JSONCONS_VISITOR_RETURN;
207
0
        }
208
209
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) final
210
113k
        {
211
113k
            if (JSONCONS_UNLIKELY(stack_.size() >= max_nesting_depth_))
212
1
            {
213
1
                ec = msgpack_errc::max_nesting_depth_exceeded;
214
1
                JSONCONS_VISITOR_RETURN;
215
1
            } 
216
113k
            stack_.emplace_back(container_type::array, length);
217
113k
            if (length <= 15)
218
107k
            {
219
                // fixarray
220
107k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf));
221
107k
            }
222
5.96k
            else if (length <= (std::numeric_limits<uint16_t>::max)())
223
2.96k
            {
224
                // array 16
225
2.96k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type);
226
2.96k
                binary::native_to_big(static_cast<uint16_t>(length),std::back_inserter(sink_));
227
2.96k
            }
228
3.00k
            else if (length <= (std::numeric_limits<uint32_t>::max)())
229
3.00k
            {
230
                // array 32
231
3.00k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type);
232
3.00k
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
233
3.00k
            }
234
113k
            JSONCONS_VISITOR_RETURN;
235
113k
        }
236
237
        JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context&, std::error_code& ec) final
238
93.5k
        {
239
93.5k
            if (JSONCONS_UNLIKELY(stack_.empty() || !stack_.back().is_array()))
240
196
            {
241
196
                ec = msgpack_errc::unmatched_end_array;
242
196
                JSONCONS_VISITOR_RETURN;
243
196
            }
244
245
93.3k
            if (stack_.back().count() < stack_.back().length())
246
366
            {
247
366
                ec = msgpack_errc::too_few_items;
248
366
                JSONCONS_VISITOR_RETURN;
249
366
            }
250
93.0k
            else if (stack_.back().count() > stack_.back().length())
251
0
            {
252
0
                ec = msgpack_errc::too_many_items;
253
0
                JSONCONS_VISITOR_RETURN;
254
0
            }
255
256
93.0k
            stack_.pop_back();
257
93.0k
            end_value();
258
93.0k
            JSONCONS_VISITOR_RETURN;
259
93.3k
        }
260
261
        JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context& context, std::error_code& ec) final
262
911k
        {
263
911k
            visit_string(name, semantic_tag::none, context, ec);
264
911k
            JSONCONS_VISITOR_RETURN;
265
911k
        }
266
267
        JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag, const ser_context&, std::error_code&) final
268
20.7k
        {
269
            // nil
270
20.7k
            sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type);
271
20.7k
            end_value();
272
20.7k
            JSONCONS_VISITOR_RETURN;
273
20.7k
        }
274
275
        void write_timestamp(int64_t seconds, int64_t nanoseconds)
276
23.2k
        {
277
23.2k
            if ((seconds >> 34) == 0) 
278
16.4k
            {
279
16.4k
                uint64_t data64 = (nanoseconds << 34) | seconds;
280
16.4k
                if ((data64 & 0xffffffff00000000L) == 0) 
281
2.67k
                {
282
                    // timestamp 32
283
2.67k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
284
2.67k
                    sink_.push_back(0xff);
285
2.67k
                    binary::native_to_big(static_cast<uint32_t>(data64), std::back_inserter(sink_));
286
2.67k
                }
287
13.7k
                else 
288
13.7k
                {
289
                    // timestamp 64
290
13.7k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
291
13.7k
                    sink_.push_back(0xff);
292
13.7k
                    binary::native_to_big(static_cast<uint64_t>(data64), std::back_inserter(sink_));
293
13.7k
                }
294
16.4k
            }
295
6.80k
            else 
296
6.80k
            {
297
                // timestamp 96
298
6.80k
                sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
299
6.80k
                sink_.push_back(0x0c); // 12
300
6.80k
                sink_.push_back(0xff);
301
6.80k
                binary::native_to_big(static_cast<uint32_t>(nanoseconds), std::back_inserter(sink_));
302
6.80k
                binary::native_to_big(static_cast<uint64_t>(seconds), std::back_inserter(sink_));
303
6.80k
            }
304
23.2k
        }
305
306
        JSONCONS_VISITOR_RETURN_TYPE visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) final
307
943k
        {
308
943k
            switch (tag)
309
943k
            {
310
0
                case semantic_tag::epoch_second:
311
0
                {
312
0
                    int64_t seconds;
313
0
                    auto result = jsoncons::to_integer(sv.data(), sv.length(), seconds);
314
0
                    if (!result)
315
0
                    {
316
0
                        ec = msgpack_errc::invalid_timestamp;
317
0
                        JSONCONS_VISITOR_RETURN;
318
0
                    }
319
0
                    write_timestamp(seconds, 0);
320
0
                    break;
321
0
                }
322
0
                case semantic_tag::epoch_milli:
323
0
                {
324
0
                    bigint n;
325
0
                    auto result = to_bigint(sv.data(), sv.length(), n);
326
0
                    if (!result)
327
0
                    {
328
0
                        ec = msgpack_errc::invalid_timestamp;
329
0
                        JSONCONS_VISITOR_RETURN;
330
0
                    }
331
0
                    if (n != 0)
332
0
                    {
333
0
                        bigint q;
334
0
                        bigint rem;
335
0
                        n.divide(millis_in_second, q, rem, true);
336
0
                        auto seconds = static_cast<int64_t>(q);
337
0
                        auto nanoseconds = static_cast<int64_t>(rem) * nanos_in_milli;
338
0
                        if (nanoseconds < 0)
339
0
                        {
340
0
                            nanoseconds = -nanoseconds; 
341
0
                        }
342
0
                        write_timestamp(seconds, nanoseconds);
343
0
                    }
344
0
                    else
345
0
                    {
346
0
                        write_timestamp(0, 0);
347
0
                    }
348
0
                    break;
349
0
                }
350
21.7k
                case semantic_tag::epoch_nano:
351
21.7k
                {
352
21.7k
                    bigint n;
353
21.7k
                    auto result = to_bigint(sv.data(), sv.length(), n);
354
21.7k
                    if (!result)
355
0
                    {
356
0
                        ec = msgpack_errc::invalid_timestamp;
357
0
                        JSONCONS_VISITOR_RETURN;
358
0
                    }
359
21.7k
                    if (n != 0)
360
20.6k
                    {
361
20.6k
                        bigint q;
362
20.6k
                        bigint rem;
363
20.6k
                        n.divide(nanos_in_second, q, rem, true);
364
20.6k
                        auto seconds = static_cast<int64_t>(q);
365
20.6k
                        auto nanoseconds = static_cast<int64_t>(rem);
366
20.6k
                        if (nanoseconds < 0)
367
3.22k
                        {
368
3.22k
                            nanoseconds = -nanoseconds; 
369
3.22k
                        }
370
20.6k
                        write_timestamp(seconds, nanoseconds);
371
20.6k
                    }
372
1.10k
                    else
373
1.10k
                    {
374
1.10k
                        write_timestamp(0, 0);
375
1.10k
                    }
376
21.7k
                    break;
377
21.7k
                }
378
921k
                default:
379
921k
                {
380
921k
                    write_string_value(sv);
381
921k
                    end_value();
382
921k
                    break;
383
21.7k
                }
384
943k
            }
385
943k
            JSONCONS_VISITOR_RETURN;
386
943k
        }
387
388
        void write_string_value(const string_view_type& sv) 
389
921k
        {
390
921k
            auto sink = unicode_traits::validate(sv.data(), sv.size());
391
921k
            if (sink.ec != unicode_traits::unicode_errc())
392
0
            {
393
0
                JSONCONS_THROW(ser_error(msgpack_errc::invalid_utf8_text_string));
394
0
            }
395
396
921k
            const size_t length = sv.length();
397
921k
            if (length <= 31)
398
918k
            {
399
                // fixstr stores a byte array whose length is upto 31 bytes
400
918k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast<uint8_t>(length));
401
918k
            }
402
2.57k
            else if (length <= (std::numeric_limits<uint8_t>::max)())
403
1.47k
            {
404
                // str 8 stores a byte array whose length is upto (2^8)-1 bytes
405
1.47k
                sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type);
406
1.47k
                sink_.push_back(static_cast<uint8_t>(length));
407
1.47k
            }
408
1.10k
            else if (length <= (std::numeric_limits<uint16_t>::max)())
409
727
            {
410
                // str 16 stores a byte array whose length is upto (2^16)-1 bytes
411
727
                sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type);
412
727
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
413
727
            }
414
373
            else if (length <= (std::numeric_limits<uint32_t>::max)())
415
373
            {
416
                // str 32 stores a byte array whose length is upto (2^32)-1 bytes
417
373
                sink_.push_back(jsoncons::msgpack::msgpack_type::str32_type);
418
373
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
419
373
            }
420
421
921k
            for (auto c : sv)
422
96.5M
            {
423
96.5M
                sink_.push_back(c);
424
96.5M
            }
425
921k
        }
426
427
        JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& b, 
428
            semantic_tag, 
429
            const ser_context&,
430
            std::error_code&) final
431
3.05k
        {
432
433
3.05k
            const std::size_t length = b.size();
434
3.05k
            if (length <= (std::numeric_limits<uint8_t>::max)())
435
2.34k
            {
436
                // bin 8 stores a byte array whose length is upto (2^8)-1 bytes
437
2.34k
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type);
438
2.34k
                sink_.push_back(static_cast<uint8_t>(length));
439
2.34k
            }
440
716
            else if (length <= (std::numeric_limits<uint16_t>::max)())
441
648
            {
442
                // bin 16 stores a byte array whose length is upto (2^16)-1 bytes
443
648
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type);
444
648
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
445
648
            }
446
68
            else if (length <= (std::numeric_limits<uint32_t>::max)())
447
68
            {
448
                // bin 32 stores a byte array whose length is upto (2^32)-1 bytes
449
68
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type);
450
68
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
451
68
            }
452
453
3.05k
            for (auto c : b)
454
8.47M
            {
455
8.47M
                sink_.push_back(c);
456
8.47M
            }
457
458
3.05k
            end_value();
459
3.05k
            JSONCONS_VISITOR_RETURN;
460
3.05k
        }
461
462
        JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& b, 
463
            uint64_t raw_tag, 
464
            const ser_context&,
465
            std::error_code&) final
466
522k
        {
467
522k
            const std::size_t length = b.size();
468
522k
            switch (length)
469
522k
            {
470
1.31k
                case 1:
471
1.31k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type);
472
1.31k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
473
1.31k
                    break;
474
491k
                case 2:
475
491k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type);
476
491k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
477
491k
                    break;
478
1.11k
                case 4:
479
1.11k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
480
1.11k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
481
1.11k
                    break;
482
3.59k
                case 8:
483
3.59k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
484
3.59k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
485
3.59k
                    break;
486
22.7k
                case 16:
487
22.7k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type);
488
22.7k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
489
22.7k
                    break;
490
2.43k
                default:
491
2.43k
                    if (length <= (std::numeric_limits<uint8_t>::max)())
492
1.48k
                    {
493
1.48k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
494
1.48k
                        sink_.push_back(static_cast<uint8_t>(length));
495
1.48k
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
496
1.48k
                    }
497
945
                    else if (length <= (std::numeric_limits<uint16_t>::max)())
498
862
                    {
499
862
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext16_type);
500
862
                        binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
501
862
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
502
862
                    }
503
83
                    else if (length <= (std::numeric_limits<uint32_t>::max)())
504
83
                    {
505
83
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type);
506
83
                        binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
507
83
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
508
83
                    }
509
2.43k
                    break;
510
522k
            }
511
512
522k
            for (auto c : b)
513
10.2M
            {
514
10.2M
                sink_.push_back(c);
515
10.2M
            }
516
517
522k
            end_value();
518
522k
            JSONCONS_VISITOR_RETURN;
519
522k
        }
520
521
        JSONCONS_VISITOR_RETURN_TYPE visit_double(double val, 
522
            semantic_tag,
523
            const ser_context&,
524
            std::error_code&) final
525
69.8k
        {
526
69.8k
            float valf = (float)val;
527
69.8k
            if ((double)valf == val)
528
44.2k
            {
529
                // float 32
530
44.2k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type);
531
44.2k
                binary::native_to_big(valf,std::back_inserter(sink_));
532
44.2k
            }
533
25.6k
            else
534
25.6k
            {
535
                // float 64
536
25.6k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type);
537
25.6k
                binary::native_to_big(val,std::back_inserter(sink_));
538
25.6k
            }
539
540
            // write double
541
542
69.8k
            end_value();
543
69.8k
            JSONCONS_VISITOR_RETURN;
544
69.8k
        }
545
546
        JSONCONS_VISITOR_RETURN_TYPE visit_int64(int64_t val, 
547
            semantic_tag tag, 
548
            const ser_context&,
549
            std::error_code&) final
550
191k
        {
551
191k
            switch (tag)
552
191k
            {
553
0
                case semantic_tag::epoch_second:
554
0
                    write_timestamp(val, 0);
555
0
                    break;
556
0
                case semantic_tag::epoch_milli:
557
0
                {
558
0
                    if (val != 0)
559
0
                    {
560
0
                        auto dv = std::div(val,millis_in_second);
561
0
                        int64_t seconds = dv.quot;
562
0
                        int64_t nanoseconds = dv.rem*nanos_in_milli;
563
0
                        if (nanoseconds < 0)
564
0
                        {
565
0
                            nanoseconds = -nanoseconds; 
566
0
                        }
567
0
                        write_timestamp(seconds, nanoseconds);
568
0
                    }
569
0
                    else
570
0
                    {
571
0
                        write_timestamp(0, 0);
572
0
                    }
573
0
                    break;
574
0
                }
575
0
                case semantic_tag::epoch_nano:
576
0
                {
577
0
                    if (val != 0)
578
0
                    {
579
0
                        auto dv = std::div(val,static_cast<int64_t>(nanos_in_second));
580
0
                        int64_t seconds = dv.quot;
581
0
                        int64_t nanoseconds = dv.rem;
582
0
                        if (nanoseconds < 0)
583
0
                        {
584
0
                            nanoseconds = -nanoseconds; 
585
0
                        }
586
0
                        write_timestamp(seconds, nanoseconds);
587
0
                    }
588
0
                    else
589
0
                    {
590
0
                        write_timestamp(0, 0);
591
0
                    }
592
0
                    break;
593
0
                }
594
191k
                default:
595
191k
                {
596
191k
                    if (val >= 0)
597
15.9k
                    {
598
15.9k
                        if (val <= 0x7f)
599
1.00k
                        {
600
                            // positive fixnum stores 7-bit positive integer
601
1.00k
                            sink_.push_back(static_cast<uint8_t>(val));
602
1.00k
                        }
603
14.9k
                        else if (val <= (std::numeric_limits<uint8_t>::max)())
604
556
                        {
605
                            // uint 8 stores a 8-bit unsigned integer
606
556
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
607
556
                            sink_.push_back(static_cast<uint8_t>(val));
608
556
                        }
609
14.4k
                        else if (val <= (std::numeric_limits<uint16_t>::max)())
610
594
                        {
611
                            // uint 16 stores a 16-bit big-endian unsigned integer
612
594
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
613
594
                            binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
614
594
                        }
615
13.8k
                        else if (val <= (std::numeric_limits<uint32_t>::max)())
616
342
                        {
617
                            // uint 32 stores a 32-bit big-endian unsigned integer
618
342
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
619
342
                            binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
620
342
                        }
621
13.4k
                        else if (val <= (std::numeric_limits<int64_t>::max)())
622
13.4k
                        {
623
                            // int 64 stores a 64-bit big-endian signed integer
624
13.4k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
625
13.4k
                            binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
626
13.4k
                        }
627
15.9k
                    }
628
175k
                    else
629
175k
                    {
630
175k
                        if (val >= -32)
631
117k
                        {
632
                            // negative fixnum stores 5-bit negative integer
633
117k
                            binary::native_to_big(static_cast<int8_t>(val), std::back_inserter(sink_));
634
117k
                        }
635
57.6k
                        else if (val >= (std::numeric_limits<int8_t>::lowest)())
636
35.3k
                        {
637
                            // int 8 stores a 8-bit signed integer
638
35.3k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type);
639
35.3k
                            binary::native_to_big(static_cast<int8_t>(val),std::back_inserter(sink_));
640
35.3k
                        }
641
22.2k
                        else if (val >= (std::numeric_limits<int16_t>::lowest)())
642
12.8k
                        {
643
                            // int 16 stores a 16-bit big-endian signed integer
644
12.8k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type);
645
12.8k
                            binary::native_to_big(static_cast<int16_t>(val),std::back_inserter(sink_));
646
12.8k
                        }
647
9.38k
                        else if (val >= (std::numeric_limits<int32_t>::lowest)())
648
6.34k
                        {
649
                            // int 32 stores a 32-bit big-endian signed integer
650
6.34k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type);
651
6.34k
                            binary::native_to_big(static_cast<int32_t>(val),std::back_inserter(sink_));
652
6.34k
                        }
653
3.04k
                        else if (val >= (std::numeric_limits<int64_t>::lowest)())
654
3.04k
                        {
655
                            // int 64 stores a 64-bit big-endian signed integer
656
3.04k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type);
657
3.04k
                            binary::native_to_big(static_cast<int64_t>(val),std::back_inserter(sink_));
658
3.04k
                        }
659
175k
                    }
660
191k
                }
661
191k
                break;
662
191k
            }
663
191k
            end_value();
664
191k
            JSONCONS_VISITOR_RETURN;
665
191k
        }
666
667
        JSONCONS_VISITOR_RETURN_TYPE visit_uint64(uint64_t val, 
668
            semantic_tag tag, 
669
            const ser_context&,
670
            std::error_code&) final
671
1.40M
        {
672
1.40M
            switch (tag)
673
1.40M
            {
674
1.48k
                case semantic_tag::epoch_second:
675
1.48k
                    write_timestamp(static_cast<int64_t>(val), 0);
676
1.48k
                    break;
677
0
                case semantic_tag::epoch_milli:
678
0
                {
679
0
                    if (val != 0)
680
0
                    {
681
0
                        auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(millis_in_second));
682
0
                        int64_t seconds = dv.quot;
683
0
                        int64_t nanoseconds = dv.rem*nanos_in_milli;
684
0
                        if (nanoseconds < 0)
685
0
                        {
686
0
                            nanoseconds = -nanoseconds; 
687
0
                        }
688
0
                        write_timestamp(seconds, nanoseconds);
689
0
                    }
690
0
                    else
691
0
                    {
692
0
                        write_timestamp(0, 0);
693
0
                    }
694
0
                    break;
695
0
                }
696
0
                case semantic_tag::epoch_nano:
697
0
                {
698
0
                    if (val != 0)
699
0
                    {
700
0
                        auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(nanos_in_second));
701
0
                        int64_t seconds = dv.quot;
702
0
                        int64_t nanoseconds = dv.rem;
703
0
                        if (nanoseconds < 0)
704
0
                        {
705
0
                            nanoseconds = -nanoseconds; 
706
0
                        }
707
0
                        write_timestamp(seconds, nanoseconds);
708
0
                    }
709
0
                    else
710
0
                    {
711
0
                        write_timestamp(0, 0);
712
0
                    }
713
0
                    break;
714
0
                }
715
1.40M
                default:
716
1.40M
                {
717
1.40M
                    if (val <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
718
1.28M
                    {
719
                        // positive fixnum stores 7-bit positive integer
720
1.28M
                        sink_.push_back(static_cast<uint8_t>(val));
721
1.28M
                    }
722
116k
                    else if (val <= (std::numeric_limits<uint8_t>::max)())
723
14.0k
                    {
724
                        // uint 8 stores a 8-bit unsigned integer
725
14.0k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
726
14.0k
                        sink_.push_back(static_cast<uint8_t>(val));
727
14.0k
                    }
728
102k
                    else if (val <= (std::numeric_limits<uint16_t>::max)())
729
98.2k
                    {
730
                        // uint 16 stores a 16-bit big-endian unsigned integer
731
98.2k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
732
98.2k
                        binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
733
98.2k
                    }
734
3.74k
                    else if (val <= (std::numeric_limits<uint32_t>::max)())
735
1.02k
                    {
736
                        // uint 32 stores a 32-bit big-endian unsigned integer
737
1.02k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
738
1.02k
                        binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
739
1.02k
                    }
740
2.72k
                    else if (val <= (std::numeric_limits<uint64_t>::max)())
741
2.72k
                    {
742
                        // uint 64 stores a 64-bit big-endian unsigned integer
743
2.72k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
744
2.72k
                        binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
745
2.72k
                    }
746
1.40M
                    break;
747
0
                }
748
1.40M
            }
749
1.40M
            end_value();
750
1.40M
            JSONCONS_VISITOR_RETURN;
751
1.40M
        }
752
753
        JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) final
754
426k
        {
755
            // true and false
756
426k
            sink_.push_back(static_cast<uint8_t>(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type));
757
758
426k
            end_value();
759
426k
            JSONCONS_VISITOR_RETURN;
760
426k
        }
761
762
        void end_value()
763
3.66M
        {
764
3.66M
            if (!stack_.empty())
765
3.66M
            {
766
3.66M
                ++stack_.back().index_;
767
3.66M
            }
768
3.66M
        }
769
    };
770
771
    using msgpack_stream_encoder = basic_msgpack_encoder<jsoncons::binary_stream_sink>;
772
    using msgpack_bytes_encoder = basic_msgpack_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>;
773
774
} // namespace msgpack
775
} // namespace jsoncons
776
777
#endif // JSONCONS_EXT_MSGPACK_MSGPACK_ENCODER_HPP