Coverage Report

Created: 2023-06-07 06:18

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