Coverage Report

Created: 2026-01-15 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/bson/bson_parser.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_BSON_BSON_PARSER_HPP
8
#define JSONCONS_EXT_BSON_BSON_PARSER_HPP
9
10
#include <cstddef>
11
#include <cstdint>
12
#include <memory>
13
#include <string>
14
#include <system_error>
15
#include <utility> // std::move
16
#include <vector>
17
18
#include <jsoncons/config/compiler_support.hpp>
19
#include <jsoncons/config/jsoncons_config.hpp>
20
#include <jsoncons/json_type.hpp>
21
#include <jsoncons/json_visitor.hpp>
22
#include <jsoncons/semantic_tag.hpp>
23
#include <jsoncons/ser_util.hpp>
24
#include <jsoncons/source.hpp>
25
#include <jsoncons/utility/binary.hpp>
26
#include <jsoncons/utility/unicode_traits.hpp>
27
28
#include <jsoncons_ext/bson/bson_decimal128.hpp>
29
#include <jsoncons_ext/bson/bson_error.hpp>
30
#include <jsoncons_ext/bson/bson_oid.hpp>
31
#include <jsoncons_ext/bson/bson_options.hpp>
32
#include <jsoncons_ext/bson/bson_type.hpp>
33
34
namespace jsoncons { 
35
namespace bson {
36
37
enum class parse_mode {root,accept,document,array,value};
38
39
struct parse_state 
40
{
41
    parse_mode mode; 
42
    std::size_t length;
43
    std::size_t pos;
44
    uint8_t type;
45
    std::size_t index{0};
46
47
    parse_state(parse_mode mode_, std::size_t length_, std::size_t pos_, uint8_t type_ = 0) noexcept
48
207k
        : mode(mode_), length(length_), pos(pos_), type(type_)
49
207k
    {
50
207k
    }
51
52
    parse_state(const parse_state&) = default;
53
    parse_state(parse_state&&) = default;
54
    parse_state& operator=(const parse_state&) = default;
55
    parse_state& operator=(parse_state&&) = default;
56
};
57
58
template <typename Source,typename TempAlloc =std::allocator<char>>
59
class basic_bson_parser : public ser_context
60
{
61
    using char_type = char;
62
    using char_traits_type = std::char_traits<char>;
63
    using temp_allocator_type = TempAlloc;
64
    using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>;                  
65
    using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>;                  
66
    using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>;
67
    using string_type = std::basic_string<char,std::char_traits<char>,char_allocator_type>;
68
69
    bool more_{true};
70
    bool done_{false};
71
    bool cursor_mode_{false};
72
    int mark_level_{0};
73
    
74
    Source source_;
75
    int max_nesting_depth_;
76
    std::vector<uint8_t,byte_allocator_type> bytes_buffer_;
77
    string_type name_buffer_;
78
    string_type text_buffer_;
79
    std::vector<parse_state,parse_state_allocator_type> state_stack_;
80
public:
81
    template <typename Sourceable>
82
    basic_bson_parser(Sourceable&& source,
83
                      const bson_decode_options& options = bson_decode_options(),
84
                      const TempAlloc& temp_alloc = TempAlloc())
85
9.28k
       : source_(std::forward<Sourceable>(source)), 
86
9.28k
         max_nesting_depth_(options.max_nesting_depth()),
87
9.28k
         bytes_buffer_(temp_alloc),
88
9.28k
         name_buffer_(temp_alloc),
89
9.28k
         text_buffer_(temp_alloc),
90
9.28k
         state_stack_(temp_alloc)
91
9.28k
    {
92
9.28k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
9.28k
    }
jsoncons::bson::basic_bson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_bson_parser<std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, jsoncons::bson::bson_decode_options const&, std::__1::allocator<char> const&)
Line
Count
Source
85
4.77k
       : source_(std::forward<Sourceable>(source)), 
86
4.77k
         max_nesting_depth_(options.max_nesting_depth()),
87
4.77k
         bytes_buffer_(temp_alloc),
88
4.77k
         name_buffer_(temp_alloc),
89
4.77k
         text_buffer_(temp_alloc),
90
4.77k
         state_stack_(temp_alloc)
91
4.77k
    {
92
4.77k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
4.77k
    }
jsoncons::bson::basic_bson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_bson_parser<std::__1::basic_istream<char, std::__1::char_traits<char> >&>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, jsoncons::bson::bson_decode_options const&, std::__1::allocator<char> const&)
Line
Count
Source
85
4.51k
       : source_(std::forward<Sourceable>(source)), 
86
4.51k
         max_nesting_depth_(options.max_nesting_depth()),
87
4.51k
         bytes_buffer_(temp_alloc),
88
4.51k
         name_buffer_(temp_alloc),
89
4.51k
         text_buffer_(temp_alloc),
90
4.51k
         state_stack_(temp_alloc)
91
4.51k
    {
92
4.51k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
4.51k
    }
94
95
    void restart()
96
    {
97
        more_ = true;
98
    }
99
100
    void reset()
101
9.28k
    {
102
9.28k
        more_ = true;
103
9.28k
        done_ = false;
104
9.28k
        bytes_buffer_.clear();
105
9.28k
        name_buffer_.clear();
106
9.28k
        text_buffer_.clear();
107
9.28k
        state_stack_.clear();
108
9.28k
        state_stack_.emplace_back(parse_mode::root,0,0);
109
9.28k
    }
110
111
    template <typename Sourceable>
112
    void reset(Sourceable&& source)
113
    {
114
        source_ = std::forward<Sourceable>(source);
115
        reset();
116
    }
117
118
    void cursor_mode(bool value)
119
    {
120
        cursor_mode_ = value;
121
    }
122
123
    int level() const
124
48.8k
    {
125
48.8k
        return static_cast<int>(state_stack_.size());
126
48.8k
    }
127
128
    int mark_level() const 
129
    {
130
        return mark_level_;
131
    }
132
133
    void mark_level(int value)
134
    {
135
        mark_level_ = value;
136
    }
137
138
    bool done() const
139
    {
140
        return done_;
141
    }
142
143
    bool stopped() const
144
    {
145
        return !more_;
146
    }
147
148
    std::size_t line() const override
149
4.49k
    {
150
4.49k
        return 0;
151
4.49k
    }
152
153
    std::size_t column() const override
154
4.49k
    {
155
4.49k
        return source_.position();
156
4.49k
    }
157
158
    void array_expected(json_visitor& visitor, std::error_code& ec)
159
    {
160
        if (state_stack_.size() == 2 && state_stack_.back().mode == parse_mode::document)
161
        {
162
            state_stack_.back().mode = parse_mode::array;
163
            visitor.begin_array(semantic_tag::none, *this, ec);
164
            more_ = !cursor_mode_;
165
        }
166
    }
167
168
    void parse(json_visitor& visitor, std::error_code& ec)
169
9.28k
    {
170
9.28k
        if (JSONCONS_UNLIKELY(source_.is_error()))
171
0
        {
172
0
            ec = bson_errc::source_error;
173
0
            more_ = false;
174
0
            return;
175
0
        }
176
        
177
37.5M
        while (!done_ && more_)
178
37.5M
        {
179
37.5M
            switch (state_stack_.back().mode)
180
37.5M
            {
181
9.28k
                case parse_mode::root:
182
9.28k
                    state_stack_.back().mode = parse_mode::accept;
183
9.28k
                    begin_document(visitor, ec);
184
9.28k
                    break;
185
10.3M
                case parse_mode::document:
186
10.3M
                {
187
10.3M
                    uint8_t type;
188
10.3M
                    std::size_t n = source_.read(&type, 1);
189
10.3M
                    state_stack_.back().pos += n;
190
10.3M
                    if (JSONCONS_UNLIKELY(n != 1))
191
2.72k
                    {
192
2.72k
                        ec = bson_errc::unexpected_eof;
193
2.72k
                        more_ = false;
194
2.72k
                        return;
195
2.72k
                    }
196
10.3M
                    if (type != 0x00)
197
10.2M
                    {
198
10.2M
                        read_e_name(visitor,jsoncons::bson::bson_container_type::document,ec);
199
10.2M
                        state_stack_.back().mode = parse_mode::value;
200
10.2M
                        state_stack_.back().type = type;
201
10.2M
                    }
202
29.8k
                    else
203
29.8k
                    {
204
29.8k
                        end_document(visitor,ec);
205
29.8k
                    }
206
10.3M
                    break;
207
10.3M
                }
208
16.9M
                case parse_mode::array:
209
16.9M
                {
210
16.9M
                    uint8_t type;
211
16.9M
                    std::size_t n = source_.read(&type, 1);
212
16.9M
                    state_stack_.back().pos += n;
213
16.9M
                    if (JSONCONS_UNLIKELY(n != 1))
214
414
                    {
215
414
                        ec = bson_errc::unexpected_eof;
216
414
                        more_ = false;
217
414
                        return;
218
414
                    }
219
16.9M
                    if (type != 0x00)
220
16.9M
                    {
221
16.9M
                        read_e_name(visitor,jsoncons::bson::bson_container_type::array,ec);
222
16.9M
                        read_value(visitor, type, ec);
223
16.9M
                    }
224
18.9k
                    else
225
18.9k
                    {
226
18.9k
                        end_array(visitor,ec);
227
18.9k
                    }
228
16.9M
                    break;
229
16.9M
                }
230
10.2M
                case parse_mode::value:
231
10.2M
                    state_stack_.back().mode = parse_mode::document;
232
10.2M
                    read_value(visitor,state_stack_.back().type,ec);
233
10.2M
                    break;
234
27
                case parse_mode::accept:
235
27
                {
236
27
                    JSONCONS_ASSERT(state_stack_.size() == 1);
237
27
                    state_stack_.clear();
238
27
                    more_ = false;
239
27
                    done_ = true;
240
27
                    visitor.flush();
241
27
                    break;
242
27
                }
243
37.5M
            }
244
37.5M
        }
245
9.28k
    }
246
247
private:
248
249
    void begin_document(json_visitor& visitor, std::error_code& ec)
250
107k
    {
251
107k
        if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > max_nesting_depth_))
252
5
        {
253
5
            ec = bson_errc::max_nesting_depth_exceeded;
254
5
            more_ = false;
255
5
            return;
256
5
        } 
257
258
107k
        uint8_t buf[sizeof(int32_t)]; 
259
107k
        std::size_t n = source_.read(buf, sizeof(int32_t));
260
107k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
261
102
        {
262
102
            ec = bson_errc::unexpected_eof;
263
102
            more_ = false;
264
102
            return;
265
102
        }
266
267
107k
        auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
268
269
107k
        visitor.begin_object(semantic_tag::none, *this, ec);
270
107k
        more_ = !cursor_mode_;
271
107k
        state_stack_.emplace_back(parse_mode::document,length,n);
272
107k
    }
273
274
    void end_document(json_visitor& visitor, std::error_code& ec)
275
29.8k
    {
276
29.8k
        JSONCONS_ASSERT(state_stack_.size() >= 2);
277
278
29.8k
        visitor.end_object(*this,ec);
279
29.8k
        more_ = !cursor_mode_;
280
29.8k
        if (level() == mark_level_)
281
0
        {
282
0
            more_ = false;
283
0
        }
284
29.8k
        if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
285
2.56k
        {
286
2.56k
            ec = bson_errc::size_mismatch;
287
2.56k
            more_ = false;
288
2.56k
            return;
289
2.56k
        }
290
27.3k
        std::size_t pos = state_stack_.back().pos;
291
27.3k
        state_stack_.pop_back();
292
27.3k
        state_stack_.back().pos += pos;
293
27.3k
    }
294
295
    void begin_array(json_visitor& visitor, std::error_code& ec)
296
921k
    {
297
921k
        if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > max_nesting_depth_))
298
3
        {
299
3
            ec = bson_errc::max_nesting_depth_exceeded;
300
3
            more_ = false;
301
3
            return;
302
3
        } 
303
921k
        uint8_t buf[sizeof(int32_t)]; 
304
921k
        std::size_t n = source_.read(buf, sizeof(int32_t));
305
921k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
306
80
        {
307
80
            ec = bson_errc::unexpected_eof;
308
80
            more_ = false;
309
80
            return;
310
80
        }
311
921k
        auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
312
313
921k
        visitor.begin_array(semantic_tag::none, *this, ec);
314
921k
        more_ = !cursor_mode_;
315
921k
        if (JSONCONS_UNLIKELY(ec))
316
840k
        {
317
840k
            return;
318
840k
        }
319
81.3k
        state_stack_.emplace_back(parse_mode::array, length, n);
320
81.3k
    }
321
322
    void end_array(json_visitor& visitor, std::error_code& ec)
323
18.9k
    {
324
18.9k
        JSONCONS_ASSERT(state_stack_.size() >= 2);
325
326
18.9k
        visitor.end_array(*this, ec);
327
18.9k
        more_ = !cursor_mode_;
328
18.9k
        if (level() == mark_level_)
329
0
        {
330
0
            more_ = false;
331
0
        }
332
18.9k
        if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
333
562
        {
334
562
            ec = bson_errc::size_mismatch;
335
562
            more_ = false;
336
562
            return;
337
562
        }
338
18.4k
        std::size_t pos = state_stack_.back().pos;
339
18.4k
        state_stack_.pop_back();
340
18.4k
        state_stack_.back().pos += pos;
341
18.4k
    }
342
343
    void read_e_name(json_visitor& visitor, jsoncons::bson::bson_container_type type, std::error_code& ec)
344
27.1M
    {
345
27.1M
        name_buffer_.clear();
346
27.1M
        read_cstring(name_buffer_, ec);
347
27.1M
        if (JSONCONS_UNLIKELY(ec))
348
952k
        {
349
952k
            return;
350
952k
        }
351
26.2M
        if (type == jsoncons::bson::bson_container_type::document)
352
9.32M
        {
353
9.32M
            auto result = unicode_traits::validate(name_buffer_.data(),name_buffer_.size());
354
9.32M
            if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
355
240
            {
356
240
                ec = bson_errc::invalid_utf8_text_string;
357
240
                more_ = false;
358
240
                return;
359
240
            }
360
9.32M
            visitor.key(jsoncons::basic_string_view<char>(name_buffer_.data(),name_buffer_.length()), *this, ec);
361
9.32M
            more_ = !cursor_mode_;
362
9.32M
        }
363
26.2M
    }
364
365
    void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec)
366
27.1M
    {
367
27.1M
        switch (type)
368
27.1M
        {
369
13.9k
            case jsoncons::bson::bson_type::double_type:
370
13.9k
            {
371
13.9k
                uint8_t buf[sizeof(double)]; 
372
13.9k
                std::size_t n = source_.read(buf, sizeof(double));
373
13.9k
                state_stack_.back().pos += n;
374
13.9k
                if (JSONCONS_UNLIKELY(n != sizeof(double)))
375
23
                {
376
23
                    ec = bson_errc::unexpected_eof;
377
23
                    more_ = false;
378
23
                    return;
379
23
                }
380
13.9k
                double res = binary::little_to_native<double>(buf, sizeof(buf));
381
13.9k
                visitor.double_value(res, semantic_tag::none, *this, ec);
382
13.9k
                more_ = !cursor_mode_;
383
13.9k
                break;
384
13.9k
            }
385
2.28k
            case jsoncons::bson::bson_type::symbol_type:
386
4.46k
            case jsoncons::bson::bson_type::min_key_type:
387
8.69k
            case jsoncons::bson::bson_type::max_key_type:
388
11.4k
            case jsoncons::bson::bson_type::string_type:
389
11.4k
            {
390
11.4k
                text_buffer_.clear();
391
11.4k
                read_string(text_buffer_, ec);
392
11.4k
                if (JSONCONS_UNLIKELY(ec))
393
863
                {
394
863
                    return;
395
863
                }
396
10.6k
                auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
397
10.6k
                if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
398
66
                {
399
66
                    ec = bson_errc::invalid_utf8_text_string;
400
66
                    more_ = false;
401
66
                    return;
402
66
                }
403
10.5k
                visitor.string_value(text_buffer_, semantic_tag::none, *this, ec);
404
10.5k
                more_ = !cursor_mode_;
405
10.5k
                break;
406
10.6k
            }
407
3.22k
            case jsoncons::bson::bson_type::javascript_type:
408
3.22k
            {
409
3.22k
                text_buffer_.clear();
410
3.22k
                read_string(text_buffer_, ec);
411
3.22k
                if (JSONCONS_UNLIKELY(ec))
412
339
                {
413
339
                    return;
414
339
                }
415
2.88k
                auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
416
2.88k
                if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
417
87
                {
418
87
                    ec = bson_errc::invalid_utf8_text_string;
419
87
                    more_ = false;
420
87
                    return;
421
87
                }
422
2.79k
                visitor.string_value(text_buffer_, semantic_tag::code, *this, ec);
423
2.79k
                more_ = !cursor_mode_;
424
2.79k
                break;
425
2.88k
            }
426
26.5k
            case jsoncons::bson::bson_type::regex_type:
427
26.5k
            {
428
26.5k
                text_buffer_.clear();
429
26.5k
                text_buffer_.push_back('/');
430
26.5k
                read_cstring(text_buffer_, ec);
431
26.5k
                if (JSONCONS_UNLIKELY(ec))
432
5.63k
                {
433
5.63k
                    return;
434
5.63k
                }
435
20.9k
                text_buffer_.push_back('/');
436
20.9k
                read_cstring(text_buffer_, ec);
437
20.9k
                if (JSONCONS_UNLIKELY(ec))
438
67
                {
439
67
                    return;
440
67
                }
441
20.8k
                visitor.string_value(text_buffer_, semantic_tag::regex, *this, ec);
442
20.8k
                more_ = !cursor_mode_;
443
20.8k
                break;
444
20.9k
            }
445
98.3k
            case jsoncons::bson::bson_type::document_type: 
446
98.3k
            {
447
98.3k
                begin_document(visitor,ec);
448
98.3k
                break;
449
20.9k
            }
450
451
921k
            case jsoncons::bson::bson_type::array_type: 
452
921k
            {
453
921k
                begin_array(visitor,ec);
454
921k
                break;
455
20.9k
            }
456
11.4k
            case jsoncons::bson::bson_type::undefined_type: 
457
11.4k
                {
458
11.4k
                    visitor.null_value(semantic_tag::undefined, *this, ec);
459
11.4k
                    more_ = !cursor_mode_;
460
11.4k
                    break;
461
20.9k
                }
462
25.7M
            case jsoncons::bson::bson_type::null_type: 
463
25.7M
            {
464
25.7M
                visitor.null_value(semantic_tag::none, *this, ec);
465
25.7M
                more_ = !cursor_mode_;
466
25.7M
                break;
467
20.9k
            }
468
44.4k
            case jsoncons::bson::bson_type::bool_type:
469
44.4k
            {
470
44.4k
                uint8_t c;
471
44.4k
                std::size_t n = source_.read(&c, 1);
472
44.4k
                state_stack_.back().pos += n;
473
44.4k
                if (JSONCONS_UNLIKELY(n != 1))
474
15
                {
475
15
                    ec = bson_errc::unexpected_eof;
476
15
                    more_ = false;
477
15
                    return;
478
15
                }
479
44.3k
                visitor.bool_value(c != 0, semantic_tag::none, *this, ec);
480
44.3k
                more_ = !cursor_mode_;
481
44.3k
                break;
482
44.4k
            }
483
146k
            case jsoncons::bson::bson_type::int32_type: 
484
146k
            {
485
146k
                uint8_t buf[sizeof(int32_t)]; 
486
146k
                std::size_t n = source_.read(buf, sizeof(int32_t));
487
146k
                state_stack_.back().pos += n;
488
146k
                if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
489
17
                {
490
17
                    ec = bson_errc::unexpected_eof;
491
17
                    more_ = false;
492
17
                    return;
493
17
                }
494
146k
                auto val = binary::little_to_native<int32_t>(buf, sizeof(buf));
495
146k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
496
146k
                more_ = !cursor_mode_;
497
146k
                break;
498
146k
            }
499
500
15.0k
            case jsoncons::bson::bson_type::timestamp_type: 
501
15.0k
            {
502
15.0k
                uint8_t buf[sizeof(uint64_t)]; 
503
15.0k
                std::size_t n = source_.read(buf, sizeof(uint64_t));
504
15.0k
                state_stack_.back().pos += n;
505
15.0k
                if (JSONCONS_UNLIKELY(n != sizeof(uint64_t)))
506
19
                {
507
19
                    ec = bson_errc::unexpected_eof;
508
19
                    more_ = false;
509
19
                    return;
510
19
                }
511
15.0k
                auto val = binary::little_to_native<uint64_t>(buf, sizeof(buf));
512
15.0k
                visitor.uint64_value(val, semantic_tag::none, *this, ec);
513
15.0k
                more_ = !cursor_mode_;
514
15.0k
                break;
515
15.0k
            }
516
517
16.3k
            case jsoncons::bson::bson_type::int64_type: 
518
16.3k
            {
519
16.3k
                uint8_t buf[sizeof(int64_t)]; 
520
16.3k
                std::size_t n = source_.read(buf, sizeof(int64_t));
521
16.3k
                state_stack_.back().pos += n;
522
16.3k
                if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
523
20
                {
524
20
                    ec = bson_errc::unexpected_eof;
525
20
                    more_ = false;
526
20
                    return;
527
20
                }
528
16.3k
                auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
529
16.3k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
530
16.3k
                more_ = !cursor_mode_;
531
16.3k
                break;
532
16.3k
            }
533
534
8.41k
            case jsoncons::bson::bson_type::datetime_type: 
535
8.41k
            {
536
8.41k
                uint8_t buf[sizeof(int64_t)]; 
537
8.41k
                std::size_t n = source_.read(buf, sizeof(int64_t));
538
8.41k
                state_stack_.back().pos += n;
539
8.41k
                if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
540
21
                {
541
21
                    ec = bson_errc::unexpected_eof;
542
21
                    more_ = false;
543
21
                    return;
544
21
                }
545
8.39k
                auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
546
8.39k
                visitor.int64_value(val, semantic_tag::epoch_milli, *this, ec);
547
8.39k
                more_ = !cursor_mode_;
548
8.39k
                break;
549
8.41k
            }
550
31.4k
            case jsoncons::bson::bson_type::binary_type: 
551
31.4k
            {
552
31.4k
                uint8_t buf[sizeof(int32_t)]; 
553
31.4k
                std::size_t n = source_.read(buf, sizeof(int32_t));
554
31.4k
                state_stack_.back().pos += n;
555
31.4k
                if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
556
25
                {
557
25
                    ec = bson_errc::unexpected_eof;
558
25
                    more_ = false;
559
25
                    return;
560
25
                }
561
31.3k
                const auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
562
31.3k
                if (JSONCONS_UNLIKELY(len < 0))
563
107
                {
564
107
                    ec = bson_errc::length_is_negative;
565
107
                    more_ = false;
566
107
                    return;
567
107
                }
568
31.2k
                uint8_t subtype;
569
31.2k
                n = source_.read(&subtype, 1);
570
31.2k
                state_stack_.back().pos += n;
571
31.2k
                if (JSONCONS_UNLIKELY(n != 1))
572
27
                {
573
27
                    ec = bson_errc::unexpected_eof;
574
27
                    more_ = false;
575
27
                    return;
576
27
                }
577
578
31.2k
                bytes_buffer_.clear();
579
31.2k
                n = source_reader<Source>::read(source_, bytes_buffer_, len);
580
31.2k
                state_stack_.back().pos += n;
581
31.2k
                if (JSONCONS_UNLIKELY(n != static_cast<std::size_t>(len)))
582
640
                {
583
640
                    ec = bson_errc::unexpected_eof;
584
640
                    more_ = false;
585
640
                    return;
586
640
                }
587
588
30.6k
                visitor.byte_string_value(bytes_buffer_, 
589
30.6k
                                                  subtype, 
590
30.6k
                                                  *this,
591
30.6k
                                                  ec);
592
30.6k
                more_ = !cursor_mode_;
593
30.6k
                break;
594
31.2k
            }
595
47.8k
            case jsoncons::bson::bson_type::decimal128_type: 
596
47.8k
            {
597
47.8k
                uint8_t buf[sizeof(uint64_t)*2]; 
598
47.8k
                std::size_t n = source_.read(buf, sizeof(buf));
599
47.8k
                state_stack_.back().pos += n;
600
47.8k
                if (JSONCONS_UNLIKELY(n != sizeof(buf)))
601
42
                {
602
42
                    ec = bson_errc::unexpected_eof;
603
42
                    more_ = false;
604
42
                    return;
605
42
                }
606
607
47.7k
                decimal128_t dec;
608
47.7k
                dec.low = binary::little_to_native<uint64_t>(buf, sizeof(uint64_t));
609
47.7k
                dec.high = binary::little_to_native<uint64_t>(buf+sizeof(uint64_t), sizeof(uint64_t));
610
611
47.7k
                text_buffer_.clear();
612
47.7k
                text_buffer_.resize(bson::decimal128_limits::buf_size);
613
47.7k
                auto r = bson::decimal128_to_chars(&text_buffer_[0], &text_buffer_[0]+text_buffer_.size(), dec);
614
47.7k
                visitor.string_value(string_view(text_buffer_.data(),static_cast<std::size_t>(r.ptr-text_buffer_.data())), semantic_tag::float128, *this, ec);
615
47.7k
                more_ = !cursor_mode_;
616
47.7k
                break;
617
47.8k
            }
618
13.0k
            case jsoncons::bson::bson_type::object_id_type: 
619
13.0k
            {
620
13.0k
                uint8_t buf[12]; 
621
13.0k
                std::size_t n = source_.read(buf, sizeof(buf));
622
13.0k
                state_stack_.back().pos += n;
623
13.0k
                if (JSONCONS_UNLIKELY(n != sizeof(buf)))
624
32
                {
625
32
                    ec = bson_errc::unexpected_eof;
626
32
                    more_ = false;
627
32
                    return;
628
32
                }
629
630
13.0k
                oid_t oid(buf);
631
13.0k
                to_string(oid, text_buffer_);
632
633
13.0k
                visitor.string_value(text_buffer_, semantic_tag::id, *this, ec);
634
13.0k
                more_ = !cursor_mode_;
635
13.0k
                break;
636
13.0k
            }
637
298
            default:
638
298
            {
639
298
                ec = bson_errc::unknown_type;
640
298
                more_ = false;
641
298
                return;
642
13.0k
            }
643
27.1M
        }
644
27.1M
    }
645
646
    void read_cstring(string_type& buffer, std::error_code& ec)
647
27.2M
    {
648
27.2M
        uint8_t c = 0xff;
649
83.3M
        while (true)
650
83.3M
        {
651
83.3M
            std::size_t n = source_.read(&c, 1);
652
83.3M
            state_stack_.back().pos += n;
653
83.3M
            if (JSONCONS_UNLIKELY(n != 1))
654
652
            {
655
652
                ec = bson_errc::unexpected_eof;
656
652
                more_ = false;
657
652
                return;
658
652
            }
659
83.3M
            if (c == 0)
660
27.2M
            {
661
27.2M
                break;
662
27.2M
            }
663
56.0M
            buffer.push_back(c);
664
56.0M
        }
665
27.2M
    }
666
667
    void read_string(string_type& buffer, std::error_code& ec)
668
14.6k
    {
669
14.6k
        uint8_t buf[sizeof(int32_t)]; 
670
14.6k
        std::size_t n = source_.read(buf, sizeof(int32_t));
671
14.6k
        state_stack_.back().pos += n;
672
14.6k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
673
224
        {
674
224
            ec = bson_errc::unexpected_eof;
675
224
            more_ = false;
676
224
            return;
677
224
        }
678
14.4k
        auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
679
14.4k
        if (JSONCONS_UNLIKELY(len < 1))
680
94
        {
681
94
            ec = bson_errc::string_length_is_non_positive;
682
94
            more_ = false;
683
94
            return;
684
94
        }
685
686
14.3k
        std::size_t size = static_cast<std::size_t>(len) - static_cast<std::size_t>(1);
687
14.3k
        n = source_reader<Source>::read(source_, buffer, size);
688
14.3k
        state_stack_.back().pos += n;
689
690
14.3k
        if (JSONCONS_UNLIKELY(n != size))
691
371
        {
692
371
            ec = bson_errc::unexpected_eof;
693
371
            more_ = false;
694
371
            return;
695
371
        }
696
14.0k
        uint8_t c;
697
14.0k
        n = source_.read(&c, 1);
698
14.0k
        state_stack_.back().pos += n;
699
14.0k
        if (JSONCONS_UNLIKELY(n != 1))
700
56
        {
701
56
            ec = bson_errc::unexpected_eof;
702
56
            more_ = false;
703
56
            return;
704
56
        }
705
14.0k
    }
706
};
707
708
} // namespace bson
709
} // namespace jsoncons
710
711
#endif // JSONCONS_EXT_BSON_BSON_PARSER_HPP