Coverage Report

Created: 2026-02-26 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp
Line
Count
Source
1
// Copyright 2013-2026 Daniel Parker
2
// Distributed under the Boost license, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5
// See https://github.com/danielaparker/jsoncons for latest version
6
7
#ifndef JSONCONS_EXT_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
209k
        : mode(mode_), length(length_), pos(pos_), type(type_)
49
209k
    {
50
209k
    }
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.27k
       : source_(std::forward<Sourceable>(source)), 
86
9.27k
         max_nesting_depth_(options.max_nesting_depth()),
87
9.27k
         bytes_buffer_(temp_alloc),
88
9.27k
         name_buffer_(temp_alloc),
89
9.27k
         text_buffer_(temp_alloc),
90
9.27k
         state_stack_(temp_alloc)
91
9.27k
    {
92
9.27k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
9.27k
    }
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.83k
       : source_(std::forward<Sourceable>(source)), 
86
4.83k
         max_nesting_depth_(options.max_nesting_depth()),
87
4.83k
         bytes_buffer_(temp_alloc),
88
4.83k
         name_buffer_(temp_alloc),
89
4.83k
         text_buffer_(temp_alloc),
90
4.83k
         state_stack_(temp_alloc)
91
4.83k
    {
92
4.83k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
4.83k
    }
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.43k
       : source_(std::forward<Sourceable>(source)), 
86
4.43k
         max_nesting_depth_(options.max_nesting_depth()),
87
4.43k
         bytes_buffer_(temp_alloc),
88
4.43k
         name_buffer_(temp_alloc),
89
4.43k
         text_buffer_(temp_alloc),
90
4.43k
         state_stack_(temp_alloc)
91
4.43k
    {
92
4.43k
        state_stack_.emplace_back(parse_mode::root,0,0);
93
4.43k
    }
94
95
    void restart()
96
    {
97
        more_ = true;
98
    }
99
100
    void reset()
101
9.27k
    {
102
9.27k
        more_ = true;
103
9.27k
        done_ = false;
104
9.27k
        bytes_buffer_.clear();
105
9.27k
        name_buffer_.clear();
106
9.27k
        text_buffer_.clear();
107
9.27k
        state_stack_.clear();
108
9.27k
        state_stack_.emplace_back(parse_mode::root,0,0);
109
9.27k
    }
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
52.8k
    {
125
52.8k
        return static_cast<int>(state_stack_.size());
126
52.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.42k
    {
150
4.42k
        return 0;
151
4.42k
    }
152
153
    std::size_t column() const override
154
4.42k
    {
155
4.42k
        return source_.position();
156
4.42k
    }
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.27k
    {
170
9.27k
        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
39.1M
        while (!done_ && more_)
178
39.1M
        {
179
39.1M
            switch (state_stack_.back().mode)
180
39.1M
            {
181
9.27k
                case parse_mode::root:
182
9.27k
                    state_stack_.back().mode = parse_mode::accept;
183
9.27k
                    begin_document(visitor, ec);
184
9.27k
                    break;
185
10.7M
                case parse_mode::document:
186
10.7M
                {
187
10.7M
                    uint8_t type;
188
10.7M
                    std::size_t n = source_.read(&type, 1);
189
10.7M
                    state_stack_.back().pos += n;
190
10.7M
                    if (JSONCONS_UNLIKELY(n != 1))
191
2.73k
                    {
192
2.73k
                        ec = bson_errc::unexpected_eof;
193
2.73k
                        more_ = false;
194
2.73k
                        return;
195
2.73k
                    }
196
10.7M
                    if (type != 0x00)
197
10.7M
                    {
198
10.7M
                        read_e_name(visitor,jsoncons::bson::bson_container_type::document,ec);
199
10.7M
                        state_stack_.back().mode = parse_mode::value;
200
10.7M
                        state_stack_.back().type = type;
201
10.7M
                    }
202
35.2k
                    else
203
35.2k
                    {
204
35.2k
                        end_document(visitor,ec);
205
35.2k
                    }
206
10.7M
                    break;
207
10.7M
                }
208
17.6M
                case parse_mode::array:
209
17.6M
                {
210
17.6M
                    uint8_t type;
211
17.6M
                    std::size_t n = source_.read(&type, 1);
212
17.6M
                    state_stack_.back().pos += n;
213
17.6M
                    if (JSONCONS_UNLIKELY(n != 1))
214
414
                    {
215
414
                        ec = bson_errc::unexpected_eof;
216
414
                        more_ = false;
217
414
                        return;
218
414
                    }
219
17.6M
                    if (type != 0x00)
220
17.6M
                    {
221
17.6M
                        read_e_name(visitor,jsoncons::bson::bson_container_type::array,ec);
222
17.6M
                        read_value(visitor, type, ec);
223
17.6M
                    }
224
17.6k
                    else
225
17.6k
                    {
226
17.6k
                        end_array(visitor,ec);
227
17.6k
                    }
228
17.6M
                    break;
229
17.6M
                }
230
10.7M
                case parse_mode::value:
231
10.7M
                    state_stack_.back().mode = parse_mode::document;
232
10.7M
                    read_value(visitor,state_stack_.back().type,ec);
233
10.7M
                    break;
234
26
                case parse_mode::accept:
235
26
                {
236
26
                    JSONCONS_ASSERT(state_stack_.size() == 1);
237
26
                    state_stack_.clear();
238
26
                    more_ = false;
239
26
                    done_ = true;
240
26
                    visitor.flush();
241
26
                    break;
242
26
                }
243
39.1M
            }
244
39.1M
        }
245
9.27k
    }
246
247
private:
248
249
    void begin_document(json_visitor& visitor, std::error_code& ec)
250
110k
    {
251
110k
        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
110k
        uint8_t buf[sizeof(int32_t)]; 
259
110k
        std::size_t n = source_.read(buf, sizeof(int32_t));
260
110k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
261
98
        {
262
98
            ec = bson_errc::unexpected_eof;
263
98
            more_ = false;
264
98
            return;
265
98
        }
266
267
109k
        auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
268
269
109k
        visitor.begin_object(semantic_tag::none, *this, ec);
270
109k
        more_ = !cursor_mode_;
271
109k
        state_stack_.emplace_back(parse_mode::document,length,n);
272
109k
    }
273
274
    void end_document(json_visitor& visitor, std::error_code& ec)
275
35.2k
    {
276
35.2k
        JSONCONS_ASSERT(state_stack_.size() >= 2);
277
278
35.2k
        visitor.end_object(*this,ec);
279
35.2k
        more_ = !cursor_mode_;
280
35.2k
        if (level() == mark_level_)
281
0
        {
282
0
            more_ = false;
283
0
        }
284
35.2k
        if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
285
2.50k
        {
286
2.50k
            ec = bson_errc::size_mismatch;
287
2.50k
            more_ = false;
288
2.50k
            return;
289
2.50k
        }
290
32.7k
        std::size_t pos = state_stack_.back().pos;
291
32.7k
        state_stack_.pop_back();
292
32.7k
        state_stack_.back().pos += pos;
293
32.7k
    }
294
295
    void begin_array(json_visitor& visitor, std::error_code& ec)
296
911k
    {
297
911k
        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
911k
        uint8_t buf[sizeof(int32_t)]; 
304
911k
        std::size_t n = source_.read(buf, sizeof(int32_t));
305
911k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
306
78
        {
307
78
            ec = bson_errc::unexpected_eof;
308
78
            more_ = false;
309
78
            return;
310
78
        }
311
911k
        auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
312
313
911k
        visitor.begin_array(semantic_tag::none, *this, ec);
314
911k
        more_ = !cursor_mode_;
315
911k
        if (JSONCONS_UNLIKELY(ec))
316
830k
        {
317
830k
            return;
318
830k
        }
319
81.0k
        state_stack_.emplace_back(parse_mode::array, length, n);
320
81.0k
    }
321
322
    void end_array(json_visitor& visitor, std::error_code& ec)
323
17.6k
    {
324
17.6k
        JSONCONS_ASSERT(state_stack_.size() >= 2);
325
326
17.6k
        visitor.end_array(*this, ec);
327
17.6k
        more_ = !cursor_mode_;
328
17.6k
        if (level() == mark_level_)
329
0
        {
330
0
            more_ = false;
331
0
        }
332
17.6k
        if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
333
569
        {
334
569
            ec = bson_errc::size_mismatch;
335
569
            more_ = false;
336
569
            return;
337
569
        }
338
17.0k
        std::size_t pos = state_stack_.back().pos;
339
17.0k
        state_stack_.pop_back();
340
17.0k
        state_stack_.back().pos += pos;
341
17.0k
    }
342
343
    void read_e_name(json_visitor& visitor, jsoncons::bson::bson_container_type type, std::error_code& ec)
344
28.3M
    {
345
28.3M
        name_buffer_.clear();
346
28.3M
        read_cstring(name_buffer_, ec);
347
28.3M
        if (JSONCONS_UNLIKELY(ec))
348
1.12M
        {
349
1.12M
            return;
350
1.12M
        }
351
27.1M
        if (type == jsoncons::bson::bson_container_type::document)
352
9.58M
        {
353
9.58M
            auto result = unicode_traits::validate(name_buffer_.data(),name_buffer_.size());
354
9.58M
            if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
355
246
            {
356
246
                ec = bson_errc::invalid_utf8_text_string;
357
246
                more_ = false;
358
246
                return;
359
246
            }
360
9.58M
            visitor.key(jsoncons::basic_string_view<char>(name_buffer_.data(),name_buffer_.length()), *this, ec);
361
9.58M
            more_ = !cursor_mode_;
362
9.58M
        }
363
27.1M
    }
364
365
    void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec)
366
28.3M
    {
367
28.3M
        switch (type)
368
28.3M
        {
369
16.4k
            case jsoncons::bson::bson_type::double_type:
370
16.4k
            {
371
16.4k
                uint8_t buf[sizeof(double)]; 
372
16.4k
                std::size_t n = source_.read(buf, sizeof(double));
373
16.4k
                state_stack_.back().pos += n;
374
16.4k
                if (JSONCONS_UNLIKELY(n != sizeof(double)))
375
22
                {
376
22
                    ec = bson_errc::unexpected_eof;
377
22
                    more_ = false;
378
22
                    return;
379
22
                }
380
16.4k
                double res = binary::little_to_native<double>(buf, sizeof(buf));
381
16.4k
                visitor.double_value(res, semantic_tag::none, *this, ec);
382
16.4k
                more_ = !cursor_mode_;
383
16.4k
                break;
384
16.4k
            }
385
2.23k
            case jsoncons::bson::bson_type::symbol_type:
386
4.42k
            case jsoncons::bson::bson_type::min_key_type:
387
8.42k
            case jsoncons::bson::bson_type::max_key_type:
388
11.1k
            case jsoncons::bson::bson_type::string_type:
389
11.1k
            {
390
11.1k
                text_buffer_.clear();
391
11.1k
                read_string(text_buffer_, ec);
392
11.1k
                if (JSONCONS_UNLIKELY(ec))
393
1.05k
                {
394
1.05k
                    return;
395
1.05k
                }
396
10.1k
                auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
397
10.1k
                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.0k
                visitor.string_value(text_buffer_, semantic_tag::none, *this, ec);
404
10.0k
                more_ = !cursor_mode_;
405
10.0k
                break;
406
10.1k
            }
407
3.06k
            case jsoncons::bson::bson_type::javascript_type:
408
3.06k
            {
409
3.06k
                text_buffer_.clear();
410
3.06k
                read_string(text_buffer_, ec);
411
3.06k
                if (JSONCONS_UNLIKELY(ec))
412
357
                {
413
357
                    return;
414
357
                }
415
2.71k
                auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
416
2.71k
                if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
417
93
                {
418
93
                    ec = bson_errc::invalid_utf8_text_string;
419
93
                    more_ = false;
420
93
                    return;
421
93
                }
422
2.61k
                visitor.string_value(text_buffer_, semantic_tag::code, *this, ec);
423
2.61k
                more_ = !cursor_mode_;
424
2.61k
                break;
425
2.71k
            }
426
37.6k
            case jsoncons::bson::bson_type::regex_type:
427
37.6k
            {
428
37.6k
                text_buffer_.clear();
429
37.6k
                text_buffer_.push_back('/');
430
37.6k
                read_cstring(text_buffer_, ec);
431
37.6k
                if (JSONCONS_UNLIKELY(ec))
432
17.9k
                {
433
17.9k
                    return;
434
17.9k
                }
435
19.7k
                text_buffer_.push_back('/');
436
19.7k
                read_cstring(text_buffer_, ec);
437
19.7k
                if (JSONCONS_UNLIKELY(ec))
438
66
                {
439
66
                    return;
440
66
                }
441
19.6k
                visitor.string_value(text_buffer_, semantic_tag::regex, *this, ec);
442
19.6k
                more_ = !cursor_mode_;
443
19.6k
                break;
444
19.7k
            }
445
100k
            case jsoncons::bson::bson_type::document_type: 
446
100k
            {
447
100k
                begin_document(visitor,ec);
448
100k
                break;
449
19.7k
            }
450
451
911k
            case jsoncons::bson::bson_type::array_type: 
452
911k
            {
453
911k
                begin_array(visitor,ec);
454
911k
                break;
455
19.7k
            }
456
50.0k
            case jsoncons::bson::bson_type::undefined_type: 
457
50.0k
                {
458
50.0k
                    visitor.null_value(semantic_tag::undefined, *this, ec);
459
50.0k
                    more_ = !cursor_mode_;
460
50.0k
                    break;
461
19.7k
                }
462
26.8M
            case jsoncons::bson::bson_type::null_type: 
463
26.8M
            {
464
26.8M
                visitor.null_value(semantic_tag::none, *this, ec);
465
26.8M
                more_ = !cursor_mode_;
466
26.8M
                break;
467
19.7k
            }
468
48.3k
            case jsoncons::bson::bson_type::bool_type:
469
48.3k
            {
470
48.3k
                uint8_t c;
471
48.3k
                std::size_t n = source_.read(&c, 1);
472
48.3k
                state_stack_.back().pos += n;
473
48.3k
                if (JSONCONS_UNLIKELY(n != 1))
474
13
                {
475
13
                    ec = bson_errc::unexpected_eof;
476
13
                    more_ = false;
477
13
                    return;
478
13
                }
479
48.3k
                visitor.bool_value(c != 0, semantic_tag::none, *this, ec);
480
48.3k
                more_ = !cursor_mode_;
481
48.3k
                break;
482
48.3k
            }
483
94.1k
            case jsoncons::bson::bson_type::int32_type: 
484
94.1k
            {
485
94.1k
                uint8_t buf[sizeof(int32_t)]; 
486
94.1k
                std::size_t n = source_.read(buf, sizeof(int32_t));
487
94.1k
                state_stack_.back().pos += n;
488
94.1k
                if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
489
15
                {
490
15
                    ec = bson_errc::unexpected_eof;
491
15
                    more_ = false;
492
15
                    return;
493
15
                }
494
94.1k
                auto val = binary::little_to_native<int32_t>(buf, sizeof(buf));
495
94.1k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
496
94.1k
                more_ = !cursor_mode_;
497
94.1k
                break;
498
94.1k
            }
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
25
                {
507
25
                    ec = bson_errc::unexpected_eof;
508
25
                    more_ = false;
509
25
                    return;
510
25
                }
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
30.7k
            case jsoncons::bson::bson_type::int64_type: 
518
30.7k
            {
519
30.7k
                uint8_t buf[sizeof(int64_t)]; 
520
30.7k
                std::size_t n = source_.read(buf, sizeof(int64_t));
521
30.7k
                state_stack_.back().pos += n;
522
30.7k
                if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
523
17
                {
524
17
                    ec = bson_errc::unexpected_eof;
525
17
                    more_ = false;
526
17
                    return;
527
17
                }
528
30.7k
                auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
529
30.7k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
530
30.7k
                more_ = !cursor_mode_;
531
30.7k
                break;
532
30.7k
            }
533
534
11.2k
            case jsoncons::bson::bson_type::datetime_type: 
535
11.2k
            {
536
11.2k
                uint8_t buf[sizeof(int64_t)]; 
537
11.2k
                std::size_t n = source_.read(buf, sizeof(int64_t));
538
11.2k
                state_stack_.back().pos += n;
539
11.2k
                if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
540
23
                {
541
23
                    ec = bson_errc::unexpected_eof;
542
23
                    more_ = false;
543
23
                    return;
544
23
                }
545
11.2k
                auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
546
11.2k
                visitor.int64_value(val, semantic_tag::epoch_milli, *this, ec);
547
11.2k
                more_ = !cursor_mode_;
548
11.2k
                break;
549
11.2k
            }
550
52.0k
            case jsoncons::bson::bson_type::binary_type: 
551
52.0k
            {
552
52.0k
                uint8_t buf[sizeof(int32_t)]; 
553
52.0k
                std::size_t n = source_.read(buf, sizeof(int32_t));
554
52.0k
                state_stack_.back().pos += n;
555
52.0k
                if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
556
18
                {
557
18
                    ec = bson_errc::unexpected_eof;
558
18
                    more_ = false;
559
18
                    return;
560
18
                }
561
52.0k
                const auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
562
52.0k
                if (JSONCONS_UNLIKELY(len < 0))
563
115
                {
564
115
                    ec = bson_errc::length_is_negative;
565
115
                    more_ = false;
566
115
                    return;
567
115
                }
568
51.9k
                uint8_t subtype;
569
51.9k
                n = source_.read(&subtype, 1);
570
51.9k
                state_stack_.back().pos += n;
571
51.9k
                if (JSONCONS_UNLIKELY(n != 1))
572
25
                {
573
25
                    ec = bson_errc::unexpected_eof;
574
25
                    more_ = false;
575
25
                    return;
576
25
                }
577
578
51.8k
                bytes_buffer_.clear();
579
51.8k
                n = source_reader<Source>::read(source_, bytes_buffer_, len);
580
51.8k
                state_stack_.back().pos += n;
581
51.8k
                if (JSONCONS_UNLIKELY(n != static_cast<std::size_t>(len)))
582
675
                {
583
675
                    ec = bson_errc::unexpected_eof;
584
675
                    more_ = false;
585
675
                    return;
586
675
                }
587
588
51.2k
                visitor.byte_string_value(bytes_buffer_, 
589
51.2k
                                                  subtype, 
590
51.2k
                                                  *this,
591
51.2k
                                                  ec);
592
51.2k
                more_ = !cursor_mode_;
593
51.2k
                break;
594
51.8k
            }
595
92.4k
            case jsoncons::bson::bson_type::decimal128_type: 
596
92.4k
            {
597
92.4k
                uint8_t buf[sizeof(uint64_t)*2]; 
598
92.4k
                std::size_t n = source_.read(buf, sizeof(buf));
599
92.4k
                state_stack_.back().pos += n;
600
92.4k
                if (JSONCONS_UNLIKELY(n != sizeof(buf)))
601
37
                {
602
37
                    ec = bson_errc::unexpected_eof;
603
37
                    more_ = false;
604
37
                    return;
605
37
                }
606
607
92.4k
                decimal128_t dec;
608
92.4k
                dec.low = binary::little_to_native<uint64_t>(buf, sizeof(uint64_t));
609
92.4k
                dec.high = binary::little_to_native<uint64_t>(buf+sizeof(uint64_t), sizeof(uint64_t));
610
611
92.4k
                text_buffer_.clear();
612
92.4k
                text_buffer_.resize(bson::decimal128_limits::buf_size);
613
92.4k
                auto r = bson::decimal128_to_chars(&text_buffer_[0], &text_buffer_[0]+text_buffer_.size(), dec);
614
92.4k
                visitor.string_value(string_view(text_buffer_.data(),static_cast<std::size_t>(r.ptr-text_buffer_.data())), semantic_tag::float128, *this, ec);
615
92.4k
                more_ = !cursor_mode_;
616
92.4k
                break;
617
92.4k
            }
618
18.5k
            case jsoncons::bson::bson_type::object_id_type: 
619
18.5k
            {
620
18.5k
                uint8_t buf[12]; 
621
18.5k
                std::size_t n = source_.read(buf, sizeof(buf));
622
18.5k
                state_stack_.back().pos += n;
623
18.5k
                if (JSONCONS_UNLIKELY(n != sizeof(buf)))
624
30
                {
625
30
                    ec = bson_errc::unexpected_eof;
626
30
                    more_ = false;
627
30
                    return;
628
30
                }
629
630
18.5k
                oid_t oid(buf);
631
18.5k
                to_string(oid, text_buffer_);
632
633
18.5k
                visitor.string_value(text_buffer_, semantic_tag::id, *this, ec);
634
18.5k
                more_ = !cursor_mode_;
635
18.5k
                break;
636
18.5k
            }
637
286
            default:
638
286
            {
639
286
                ec = bson_errc::unknown_type;
640
286
                more_ = false;
641
286
                return;
642
18.5k
            }
643
28.3M
        }
644
28.3M
    }
645
646
    void read_cstring(string_type& buffer, std::error_code& ec)
647
28.3M
    {
648
28.3M
        uint8_t c = 0xff;
649
83.9M
        while (true)
650
83.9M
        {
651
83.9M
            std::size_t n = source_.read(&c, 1);
652
83.9M
            state_stack_.back().pos += n;
653
83.9M
            if (JSONCONS_UNLIKELY(n != 1))
654
634
            {
655
634
                ec = bson_errc::unexpected_eof;
656
634
                more_ = false;
657
634
                return;
658
634
            }
659
83.9M
            if (c == 0)
660
28.3M
            {
661
28.3M
                break;
662
28.3M
            }
663
55.5M
            buffer.push_back(c);
664
55.5M
        }
665
28.3M
    }
666
667
    void read_string(string_type& buffer, std::error_code& ec)
668
14.2k
    {
669
14.2k
        uint8_t buf[sizeof(int32_t)]; 
670
14.2k
        std::size_t n = source_.read(buf, sizeof(int32_t));
671
14.2k
        state_stack_.back().pos += n;
672
14.2k
        if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
673
222
        {
674
222
            ec = bson_errc::unexpected_eof;
675
222
            more_ = false;
676
222
            return;
677
222
        }
678
14.0k
        auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
679
14.0k
        if (JSONCONS_UNLIKELY(len < 1))
680
104
        {
681
104
            ec = bson_errc::string_length_is_non_positive;
682
104
            more_ = false;
683
104
            return;
684
104
        }
685
686
13.9k
        std::size_t size = static_cast<std::size_t>(len) - static_cast<std::size_t>(1);
687
13.9k
        n = source_reader<Source>::read(source_, buffer, size);
688
13.9k
        state_stack_.back().pos += n;
689
690
13.9k
        if (JSONCONS_UNLIKELY(n != size))
691
397
        {
692
397
            ec = bson_errc::unexpected_eof;
693
397
            more_ = false;
694
397
            return;
695
397
        }
696
13.5k
        uint8_t c;
697
13.5k
        n = source_.read(&c, 1);
698
13.5k
        state_stack_.back().pos += n;
699
13.5k
        if (JSONCONS_UNLIKELY(n != 1))
700
55
        {
701
55
            ec = bson_errc::unexpected_eof;
702
55
            more_ = false;
703
55
            return;
704
55
        }
705
13.5k
    }
706
};
707
708
} // namespace bson
709
} // namespace jsoncons
710
711
#endif // JSONCONS_EXT_BSON_BSON_PARSER_HPP