Coverage Report

Created: 2025-12-14 06:38

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-2025 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
103k
               : type_(type), length_(length)
65
103k
            {
66
103k
            }
67
68
            std::size_t length() const
69
163k
            {
70
163k
                return length_;
71
163k
            }
72
73
            std::size_t count() const
74
163k
            {
75
163k
                return is_object() ? index_/2 : index_;
76
163k
            }
77
78
            bool is_object() const
79
163k
            {
80
163k
                return type_ == msgpack_container_type::object;
81
163k
            }
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.12k
           : basic_msgpack_encoder(std::forward<Sink>(sink), msgpack_encode_options(), alloc)
98
6.12k
        {
99
6.12k
        }
100
101
        explicit basic_msgpack_encoder(Sink&& sink, 
102
            const msgpack_encode_options& options, 
103
            const Allocator& alloc = Allocator())
104
6.12k
           : sink_(std::forward<Sink>(sink)),
105
6.12k
             max_nesting_depth_(options.max_nesting_depth()),
106
6.12k
             alloc_(alloc)
107
6.12k
        {
108
6.12k
        }
109
110
        ~basic_msgpack_encoder() noexcept
111
6.12k
        {
112
6.12k
            sink_.flush();
113
6.12k
        }
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.45k
        {
135
1.45k
            sink_.flush();
136
1.45k
        }
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
41.9k
        {
146
41.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
41.9k
            stack_.emplace_back(msgpack_container_type::object, length);
152
153
41.9k
            if (length <= 15)
154
40.2k
            {
155
                // fixmap
156
40.2k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf));
157
40.2k
            }
158
1.65k
            else if (length <= 65535)
159
692
            {
160
                // map 16
161
692
                sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type);
162
692
                binary::native_to_big(static_cast<uint16_t>(length), 
163
692
                                      std::back_inserter(sink_));
164
692
            }
165
961
            else if (length <= (std::numeric_limits<uint32_t>::max)())
166
961
            {
167
                // map 32
168
961
                sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type);
169
961
                binary::native_to_big(static_cast<uint32_t>(length),
170
961
                                      std::back_inserter(sink_));
171
961
            }
172
173
41.9k
            JSONCONS_VISITOR_RETURN;
174
41.9k
        }
175
176
        JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context&, std::error_code& ec) final
177
34.4k
        {
178
34.4k
            JSONCONS_ASSERT(!stack_.empty());
179
34.4k
            --nesting_depth_;
180
181
34.4k
            if (stack_.back().count() < stack_.back().length())
182
422
            {
183
422
                ec = msgpack_errc::too_few_items;
184
422
                JSONCONS_VISITOR_RETURN;
185
422
            }
186
33.9k
            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
33.9k
            stack_.pop_back();
193
33.9k
            end_value();
194
33.9k
            JSONCONS_VISITOR_RETURN;
195
34.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
61.1k
        {
205
61.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
61.1k
            stack_.emplace_back(msgpack_container_type::array, length);
211
61.1k
            if (length <= 15)
212
58.3k
            {
213
                // fixarray
214
58.3k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf));
215
58.3k
            }
216
2.73k
            else if (length <= (std::numeric_limits<uint16_t>::max)())
217
1.37k
            {
218
                // array 16
219
1.37k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type);
220
1.37k
                binary::native_to_big(static_cast<uint16_t>(length),std::back_inserter(sink_));
221
1.37k
            }
222
1.35k
            else if (length <= (std::numeric_limits<uint32_t>::max)())
223
1.35k
            {
224
                // array 32
225
1.35k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type);
226
1.35k
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
227
1.35k
            }
228
61.1k
            JSONCONS_VISITOR_RETURN;
229
61.1k
        }
230
231
        JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context&, std::error_code& ec) final
232
47.6k
        {
233
47.6k
            JSONCONS_ASSERT(!stack_.empty());
234
235
47.6k
            --nesting_depth_;
236
237
47.6k
            if (stack_.back().count() < stack_.back().length())
238
488
            {
239
488
                ec = msgpack_errc::too_few_items;
240
488
                JSONCONS_VISITOR_RETURN;
241
488
            }
242
47.1k
            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
47.1k
            stack_.pop_back();
249
47.1k
            end_value();
250
47.1k
            JSONCONS_VISITOR_RETURN;
251
47.6k
        }
252
253
        JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context& context, std::error_code& ec) override
254
202k
        {
255
202k
            visit_string(name, semantic_tag::none, context, ec);
256
202k
            JSONCONS_VISITOR_RETURN;
257
202k
        }
258
259
        JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag, const ser_context&, std::error_code&) final
260
6.93k
        {
261
            // nil
262
6.93k
            sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type);
263
6.93k
            end_value();
264
6.93k
            JSONCONS_VISITOR_RETURN;
265
6.93k
        }
266
267
        void write_timestamp(int64_t seconds, int64_t nanoseconds)
268
7.78k
        {
269
7.78k
            if ((seconds >> 34) == 0) 
270
3.75k
            {
271
3.75k
                uint64_t data64 = (nanoseconds << 34) | seconds;
272
3.75k
                if ((data64 & 0xffffffff00000000L) == 0) 
273
1.79k
                {
274
                    // timestamp 32
275
1.79k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
276
1.79k
                    sink_.push_back(0xff);
277
1.79k
                    binary::native_to_big(static_cast<uint32_t>(data64), std::back_inserter(sink_));
278
1.79k
                }
279
1.95k
                else 
280
1.95k
                {
281
                    // timestamp 64
282
1.95k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
283
1.95k
                    sink_.push_back(0xff);
284
1.95k
                    binary::native_to_big(static_cast<uint64_t>(data64), std::back_inserter(sink_));
285
1.95k
                }
286
3.75k
            }
287
4.03k
            else 
288
4.03k
            {
289
                // timestamp 96
290
4.03k
                sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
291
4.03k
                sink_.push_back(0x0c); // 12
292
4.03k
                sink_.push_back(0xff);
293
4.03k
                binary::native_to_big(static_cast<uint32_t>(nanoseconds), std::back_inserter(sink_));
294
4.03k
                binary::native_to_big(static_cast<uint64_t>(seconds), std::back_inserter(sink_));
295
4.03k
            }
296
7.78k
        }
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
211k
        {
300
211k
            switch (tag)
301
211k
            {
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
6.52k
                case semantic_tag::epoch_nano:
343
6.52k
                {
344
6.52k
                    bigint n;
345
6.52k
                    auto result = to_bigint(sv.data(), sv.length(), n);
346
6.52k
                    if (!result)
347
0
                    {
348
0
                        ec = msgpack_errc::invalid_timestamp;
349
0
                        JSONCONS_VISITOR_RETURN;
350
0
                    }
351
6.52k
                    if (n != 0)
352
5.99k
                    {
353
5.99k
                        bigint q;
354
5.99k
                        bigint rem;
355
5.99k
                        n.divide(nanos_in_second, q, rem, true);
356
5.99k
                        auto seconds = static_cast<int64_t>(q);
357
5.99k
                        auto nanoseconds = static_cast<int64_t>(rem);
358
5.99k
                        if (nanoseconds < 0)
359
1.20k
                        {
360
1.20k
                            nanoseconds = -nanoseconds; 
361
1.20k
                        }
362
5.99k
                        write_timestamp(seconds, nanoseconds);
363
5.99k
                    }
364
531
                    else
365
531
                    {
366
531
                        write_timestamp(0, 0);
367
531
                    }
368
6.52k
                    break;
369
6.52k
                }
370
204k
                default:
371
204k
                {
372
204k
                    write_string_value(sv);
373
204k
                    end_value();
374
204k
                    break;
375
6.52k
                }
376
211k
            }
377
211k
            JSONCONS_VISITOR_RETURN;
378
211k
        }
379
380
        void write_string_value(const string_view_type& sv) 
381
204k
        {
382
204k
            auto sink = unicode_traits::validate(sv.data(), sv.size());
383
204k
            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
204k
            const size_t length = sv.length();
389
204k
            if (length <= 31)
390
202k
            {
391
                // fixstr stores a byte array whose length is upto 31 bytes
392
202k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast<uint8_t>(length));
393
202k
            }
394
1.87k
            else if (length <= (std::numeric_limits<uint8_t>::max)())
395
877
            {
396
                // str 8 stores a byte array whose length is upto (2^8)-1 bytes
397
877
                sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type);
398
877
                sink_.push_back(static_cast<uint8_t>(length));
399
877
            }
400
995
            else if (length <= (std::numeric_limits<uint16_t>::max)())
401
672
            {
402
                // str 16 stores a byte array whose length is upto (2^16)-1 bytes
403
672
                sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type);
404
672
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
405
672
            }
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
204k
            for (auto c : sv)
414
85.1M
            {
415
85.1M
                sink_.push_back(c);
416
85.1M
            }
417
204k
        }
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.13k
        {
424
425
2.13k
            const std::size_t length = b.size();
426
2.13k
            if (length <= (std::numeric_limits<uint8_t>::max)())
427
1.63k
            {
428
                // bin 8 stores a byte array whose length is upto (2^8)-1 bytes
429
1.63k
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type);
430
1.63k
                sink_.push_back(static_cast<uint8_t>(length));
431
1.63k
            }
432
497
            else if (length <= (std::numeric_limits<uint16_t>::max)())
433
433
            {
434
                // bin 16 stores a byte array whose length is upto (2^16)-1 bytes
435
433
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type);
436
433
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
437
433
            }
438
64
            else if (length <= (std::numeric_limits<uint32_t>::max)())
439
64
            {
440
                // bin 32 stores a byte array whose length is upto (2^32)-1 bytes
441
64
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type);
442
64
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
443
64
            }
444
445
2.13k
            for (auto c : b)
446
8.72M
            {
447
8.72M
                sink_.push_back(c);
448
8.72M
            }
449
450
2.13k
            end_value();
451
2.13k
            JSONCONS_VISITOR_RETURN;
452
2.13k
        }
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
27.8k
        {
459
27.8k
            const std::size_t length = b.size();
460
27.8k
            switch (length)
461
27.8k
            {
462
1.40k
                case 1:
463
1.40k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type);
464
1.40k
                    sink_.push_back(static_cast<uint8_t>(ext_tag));
465
1.40k
                    break;
466
21.3k
                case 2:
467
21.3k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type);
468
21.3k
                    sink_.push_back(static_cast<uint8_t>(ext_tag));
469
21.3k
                    break;
470
838
                case 4:
471
838
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
472
838
                    sink_.push_back(static_cast<uint8_t>(ext_tag));
473
838
                    break;
474
731
                case 8:
475
731
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
476
731
                    sink_.push_back(static_cast<uint8_t>(ext_tag));
477
731
                    break;
478
1.80k
                case 16:
479
1.80k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type);
480
1.80k
                    sink_.push_back(static_cast<uint8_t>(ext_tag));
481
1.80k
                    break;
482
1.74k
                default:
483
1.74k
                    if (length <= (std::numeric_limits<uint8_t>::max)())
484
1.26k
                    {
485
1.26k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
486
1.26k
                        sink_.push_back(static_cast<uint8_t>(length));
487
1.26k
                        sink_.push_back(static_cast<uint8_t>(ext_tag));
488
1.26k
                    }
489
481
                    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
73
                    else if (length <= (std::numeric_limits<uint32_t>::max)())
496
73
                    {
497
73
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type);
498
73
                        binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
499
73
                        sink_.push_back(static_cast<uint8_t>(ext_tag));
500
73
                    }
501
1.74k
                    break;
502
27.8k
            }
503
504
27.8k
            for (auto c : b)
505
7.72M
            {
506
7.72M
                sink_.push_back(c);
507
7.72M
            }
508
509
27.8k
            end_value();
510
27.8k
            JSONCONS_VISITOR_RETURN;
511
27.8k
        }
512
513
        JSONCONS_VISITOR_RETURN_TYPE visit_double(double val, 
514
            semantic_tag,
515
            const ser_context&,
516
            std::error_code&) final
517
44.1k
        {
518
44.1k
            float valf = (float)val;
519
44.1k
            if ((double)valf == val)
520
39.2k
            {
521
                // float 32
522
39.2k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type);
523
39.2k
                binary::native_to_big(valf,std::back_inserter(sink_));
524
39.2k
            }
525
4.94k
            else
526
4.94k
            {
527
                // float 64
528
4.94k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type);
529
4.94k
                binary::native_to_big(val,std::back_inserter(sink_));
530
4.94k
            }
531
532
            // write double
533
534
44.1k
            end_value();
535
44.1k
            JSONCONS_VISITOR_RETURN;
536
44.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
131k
        {
543
131k
            switch (tag)
544
131k
            {
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
131k
                default:
587
131k
                {
588
131k
                    if (val >= 0)
589
8.01k
                    {
590
8.01k
                        if (val <= 0x7f)
591
348
                        {
592
                            // positive fixnum stores 7-bit positive integer
593
348
                            sink_.push_back(static_cast<uint8_t>(val));
594
348
                        }
595
7.67k
                        else if (val <= (std::numeric_limits<uint8_t>::max)())
596
455
                        {
597
                            // uint 8 stores a 8-bit unsigned integer
598
455
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
599
455
                            sink_.push_back(static_cast<uint8_t>(val));
600
455
                        }
601
7.21k
                        else if (val <= (std::numeric_limits<uint16_t>::max)())
602
425
                        {
603
                            // uint 16 stores a 16-bit big-endian unsigned integer
604
425
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
605
425
                            binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
606
425
                        }
607
6.79k
                        else if (val <= (std::numeric_limits<uint32_t>::max)())
608
303
                        {
609
                            // uint 32 stores a 32-bit big-endian unsigned integer
610
303
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
611
303
                            binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
612
303
                        }
613
6.48k
                        else if (val <= (std::numeric_limits<int64_t>::max)())
614
6.48k
                        {
615
                            // int 64 stores a 64-bit big-endian signed integer
616
6.48k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
617
6.48k
                            binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
618
6.48k
                        }
619
8.01k
                    }
620
123k
                    else
621
123k
                    {
622
123k
                        if (val >= -32)
623
66.7k
                        {
624
                            // negative fixnum stores 5-bit negative integer
625
66.7k
                            binary::native_to_big(static_cast<int8_t>(val), std::back_inserter(sink_));
626
66.7k
                        }
627
57.0k
                        else if (val >= (std::numeric_limits<int8_t>::lowest)())
628
37.2k
                        {
629
                            // int 8 stores a 8-bit signed integer
630
37.2k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type);
631
37.2k
                            binary::native_to_big(static_cast<int8_t>(val),std::back_inserter(sink_));
632
37.2k
                        }
633
19.7k
                        else if (val >= (std::numeric_limits<int16_t>::lowest)())
634
12.1k
                        {
635
                            // int 16 stores a 16-bit big-endian signed integer
636
12.1k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type);
637
12.1k
                            binary::native_to_big(static_cast<int16_t>(val),std::back_inserter(sink_));
638
12.1k
                        }
639
7.57k
                        else if (val >= (std::numeric_limits<int32_t>::lowest)())
640
5.94k
                        {
641
                            // int 32 stores a 32-bit big-endian signed integer
642
5.94k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type);
643
5.94k
                            binary::native_to_big(static_cast<int32_t>(val),std::back_inserter(sink_));
644
5.94k
                        }
645
1.62k
                        else if (val >= (std::numeric_limits<int64_t>::lowest)())
646
1.62k
                        {
647
                            // int 64 stores a 64-bit big-endian signed integer
648
1.62k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type);
649
1.62k
                            binary::native_to_big(static_cast<int64_t>(val),std::back_inserter(sink_));
650
1.62k
                        }
651
123k
                    }
652
131k
                }
653
131k
                break;
654
131k
            }
655
131k
            end_value();
656
131k
            JSONCONS_VISITOR_RETURN;
657
131k
        }
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
199k
        {
664
199k
            switch (tag)
665
199k
            {
666
1.25k
                case semantic_tag::epoch_second:
667
1.25k
                    write_timestamp(static_cast<int64_t>(val), 0);
668
1.25k
                    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
197k
                default:
708
197k
                {
709
197k
                    if (val <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
710
177k
                    {
711
                        // positive fixnum stores 7-bit positive integer
712
177k
                        sink_.push_back(static_cast<uint8_t>(val));
713
177k
                    }
714
20.6k
                    else if (val <= (std::numeric_limits<uint8_t>::max)())
715
14.0k
                    {
716
                        // uint 8 stores a 8-bit unsigned integer
717
14.0k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
718
14.0k
                        sink_.push_back(static_cast<uint8_t>(val));
719
14.0k
                    }
720
6.65k
                    else if (val <= (std::numeric_limits<uint16_t>::max)())
721
764
                    {
722
                        // uint 16 stores a 16-bit big-endian unsigned integer
723
764
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
724
764
                        binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
725
764
                    }
726
5.89k
                    else if (val <= (std::numeric_limits<uint32_t>::max)())
727
4.80k
                    {
728
                        // uint 32 stores a 32-bit big-endian unsigned integer
729
4.80k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
730
4.80k
                        binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
731
4.80k
                    }
732
1.08k
                    else if (val <= (std::numeric_limits<uint64_t>::max)())
733
1.08k
                    {
734
                        // uint 64 stores a 64-bit big-endian unsigned integer
735
1.08k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
736
1.08k
                        binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
737
1.08k
                    }
738
197k
                    break;
739
0
                }
740
199k
            }
741
199k
            end_value();
742
199k
            JSONCONS_VISITOR_RETURN;
743
199k
        }
744
745
        JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) final
746
245k
        {
747
            // true and false
748
245k
            sink_.push_back(static_cast<uint8_t>(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type));
749
750
245k
            end_value();
751
245k
            JSONCONS_VISITOR_RETURN;
752
245k
        }
753
754
        void end_value()
755
942k
        {
756
942k
            if (!stack_.empty())
757
941k
            {
758
941k
                ++stack_.back().index_;
759
941k
            }
760
942k
        }
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