Coverage Report

Created: 2026-05-20 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/ubjson/ubjson_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_UBJSON_UBJSON_PARSER_HPP
8
#define JSONCONS_EXT_UBJSON_UBJSON_PARSER_HPP
9
10
#include <cstddef>
11
#include <cstdint>
12
#include <memory>
13
#include <string>
14
#include <system_error>
15
#include <vector>
16
#include <utility> // std::move
17
18
#include <jsoncons/config/jsoncons_config.hpp>
19
#include <jsoncons/utility/read_number.hpp>
20
#include <jsoncons/json_type.hpp>
21
#include <jsoncons/json_visitor.hpp>
22
#include <jsoncons/semantic_tag.hpp>
23
#include <jsoncons/ser_utils.hpp>
24
#include <jsoncons/source.hpp>
25
#include <jsoncons/utility/binary.hpp>
26
#include <jsoncons/utility/unicode_traits.hpp>
27
28
#include <jsoncons_ext/ubjson/ubjson_error.hpp>
29
#include <jsoncons_ext/ubjson/ubjson_options.hpp>
30
#include <jsoncons_ext/ubjson/ubjson_type.hpp>
31
32
namespace jsoncons { 
33
namespace ubjson {
34
35
enum class parse_mode {root,accept,array,indefinite_array,strongly_typed_array,map_key,map_value,strongly_typed_map_key,strongly_typed_map_value,indefinite_map_key,indefinite_map_value};
36
37
struct parse_state 
38
{
39
    parse_mode mode; 
40
    std::size_t length{0};
41
    uint8_t type;
42
    std::size_t index{0};
43
44
    parse_state(parse_mode mode, std::size_t length, uint8_t type = 0) noexcept
45
14.9M
        : mode(mode), length(length), type(type)
46
14.9M
    {
47
14.9M
    }
48
49
    parse_state(const parse_state&) = default;
50
    parse_state(parse_state&&) = default;
51
};
52
53
template <typename Source,typename Allocator=std::allocator<char>>
54
class basic_ubjson_parser : public ser_context
55
{
56
    using char_type = char;
57
    using char_traits_type = std::char_traits<char>;
58
    using temp_allocator_type = Allocator;
59
    using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>;                  
60
    using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>;                  
61
    using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>;                         
62
63
    bool more_{true};
64
    bool done_{false};
65
    int nesting_depth_{0};
66
    bool cursor_mode_{false};
67
    int mark_level_{0};
68
69
    Source source_;
70
    int max_nesting_depth_;
71
    std::size_t max_items_;
72
    std::basic_string<char,std::char_traits<char>,char_allocator_type> text_buffer_;
73
    std::vector<parse_state,parse_state_allocator_type> state_stack_;
74
public:
75
    template <typename Sourceable>
76
        basic_ubjson_parser(Sourceable&& source,
77
                          const ubjson_decode_options& options = ubjson_decode_options(),
78
                          const Allocator& alloc = Allocator())
79
736
       : source_(std::forward<Sourceable>(source)), 
80
736
         max_nesting_depth_(options.max_nesting_depth()),
81
736
         max_items_(options.max_items()),
82
736
         text_buffer_(alloc),
83
736
         state_stack_(alloc)
84
736
    {
85
736
        state_stack_.emplace_back(parse_mode::root,0);
86
736
    }
jsoncons::ubjson::basic_ubjson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_ubjson_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::ubjson::ubjson_decode_options const&, std::__1::allocator<char> const&)
Line
Count
Source
79
279
       : source_(std::forward<Sourceable>(source)), 
80
279
         max_nesting_depth_(options.max_nesting_depth()),
81
279
         max_items_(options.max_items()),
82
279
         text_buffer_(alloc),
83
279
         state_stack_(alloc)
84
279
    {
85
279
        state_stack_.emplace_back(parse_mode::root,0);
86
279
    }
jsoncons::ubjson::basic_ubjson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_ubjson_parser<std::__1::basic_istream<char, std::__1::char_traits<char> >&>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, jsoncons::ubjson::ubjson_decode_options const&, std::__1::allocator<char> const&)
Line
Count
Source
79
457
       : source_(std::forward<Sourceable>(source)), 
80
457
         max_nesting_depth_(options.max_nesting_depth()),
81
457
         max_items_(options.max_items()),
82
457
         text_buffer_(alloc),
83
457
         state_stack_(alloc)
84
457
    {
85
457
        state_stack_.emplace_back(parse_mode::root,0);
86
457
    }
87
88
    void restart()
89
    {
90
        more_ = true;
91
    }
92
93
    void reset()
94
736
    {
95
736
        more_ = true;
96
736
        done_ = false;
97
736
        text_buffer_.clear();
98
736
        state_stack_.clear();
99
736
        state_stack_.emplace_back(parse_mode::root,0,uint8_t(0));
100
736
        nesting_depth_ = 0;
101
736
    }
102
103
    template <typename Sourceable>
104
    void reset(Sourceable&& source)
105
    {
106
        source_ = std::forward<Sourceable>(source);
107
        reset();
108
    }
109
110
    void cursor_mode(bool value)
111
    {
112
        cursor_mode_ = value;
113
    }
114
115
    int level() const
116
14.9M
    {
117
14.9M
        return static_cast<int>(state_stack_.size());
118
14.9M
    }
119
120
    int mark_level() const 
121
    {
122
        return mark_level_;
123
    }
124
125
    void mark_level(int value)
126
    {
127
        mark_level_ = value;
128
    }
129
130
    bool done() const
131
    {
132
        return done_;
133
    }
134
135
    bool stopped() const
136
    {
137
        return !more_;
138
    }
139
140
    std::size_t line() const override
141
328
    {
142
328
        return 0;
143
328
    }
144
145
    std::size_t column() const override
146
328
    {
147
328
        return source_.position();
148
328
    }
149
150
    void parse(json_visitor& visitor, std::error_code& ec)
151
736
    {
152
76.3M
        while (!done_ && more_)
153
76.3M
        {
154
76.3M
            switch (state_stack_.back().mode)
155
76.3M
            {
156
123k
                case parse_mode::array:
157
123k
                {
158
123k
                    if (state_stack_.back().index < state_stack_.back().length)
159
31.4k
                    {
160
31.4k
                        ++state_stack_.back().index;
161
31.4k
                        read_type_and_value(visitor, ec);
162
31.4k
                        if (JSONCONS_UNLIKELY(ec))
163
3
                        {
164
3
                            return;
165
3
                        }
166
31.4k
                    }
167
92.1k
                    else
168
92.1k
                    {
169
92.1k
                        end_array(visitor, ec);
170
92.1k
                    }
171
123k
                    break;
172
123k
                }
173
30.1M
                case parse_mode::strongly_typed_array:
174
30.1M
                {
175
30.1M
                    if (state_stack_.back().index < state_stack_.back().length)
176
30.1M
                    {
177
30.1M
                        ++state_stack_.back().index;
178
30.1M
                        read_value(visitor, state_stack_.back().type, ec);
179
30.1M
                        if (JSONCONS_UNLIKELY(ec))
180
177
                        {
181
177
                            return;
182
177
                        }
183
30.1M
                    }
184
20.2k
                    else
185
20.2k
                    {
186
20.2k
                        end_array(visitor, ec);
187
20.2k
                    }
188
30.1M
                    break;
189
30.1M
                }
190
30.1M
                case parse_mode::indefinite_array:
191
27.4M
                {
192
27.4M
                    auto c = source_.peek();
193
27.4M
                    if (JSONCONS_UNLIKELY(c.eof))
194
55
                    {
195
55
                        ec = ubjson_errc::unexpected_eof;
196
55
                        more_ = false;
197
55
                        return;
198
55
                    }
199
27.4M
                    if (c.value == jsoncons::ubjson::ubjson_type::end_array_marker)
200
7.90M
                    {
201
7.90M
                        source_.ignore(1);
202
7.90M
                        end_array(visitor, ec);
203
7.90M
                        if (JSONCONS_UNLIKELY(ec))
204
0
                        {
205
0
                            return;
206
0
                        }
207
7.90M
                    }
208
19.5M
                    else
209
19.5M
                    {
210
19.5M
                        if (++state_stack_.back().index > max_items_)
211
0
                        {
212
0
                            ec = ubjson_errc::max_items_exceeded;
213
0
                            more_ = false;
214
0
                            return;
215
0
                        }
216
19.5M
                        read_type_and_value(visitor, ec);
217
19.5M
                        if (JSONCONS_UNLIKELY(ec))
218
104
                        {
219
104
                            return;
220
104
                        }
221
19.5M
                    }
222
27.4M
                    break;
223
27.4M
                }
224
27.4M
                case parse_mode::map_key:
225
14.0k
                {
226
14.0k
                    if (state_stack_.back().index < state_stack_.back().length)
227
9.94k
                    {
228
9.94k
                        ++state_stack_.back().index;
229
9.94k
                        read_key(visitor, ec);
230
9.94k
                        if (JSONCONS_UNLIKELY(ec))
231
4
                        {
232
4
                            return;
233
4
                        }
234
9.93k
                        state_stack_.back().mode = parse_mode::map_value;
235
9.93k
                    }
236
4.10k
                    else
237
4.10k
                    {
238
4.10k
                        end_object(visitor, ec);
239
4.10k
                    }
240
14.0k
                    break;
241
14.0k
                }
242
14.0k
                case parse_mode::map_value:
243
9.93k
                {
244
9.93k
                    state_stack_.back().mode = parse_mode::map_key;
245
9.93k
                    read_type_and_value(visitor, ec);
246
9.93k
                    if (JSONCONS_UNLIKELY(ec))
247
8
                    {
248
8
                        return;
249
8
                    }
250
9.92k
                    break;
251
9.93k
                }
252
208k
                case parse_mode::strongly_typed_map_key:
253
208k
                {
254
208k
                    if (state_stack_.back().index < state_stack_.back().length)
255
134k
                    {
256
134k
                        ++state_stack_.back().index;
257
134k
                        read_key(visitor, ec);
258
134k
                        if (JSONCONS_UNLIKELY(ec))
259
9
                        {
260
9
                            return;
261
9
                        }
262
134k
                        state_stack_.back().mode = parse_mode::strongly_typed_map_value;
263
134k
                    }
264
74.1k
                    else
265
74.1k
                    {
266
74.1k
                        end_object(visitor, ec);
267
74.1k
                    }
268
208k
                    break;
269
208k
                }
270
208k
                case parse_mode::strongly_typed_map_value:
271
134k
                {
272
134k
                    state_stack_.back().mode = parse_mode::strongly_typed_map_key;
273
134k
                    read_value(visitor, state_stack_.back().type, ec);
274
134k
                    if (JSONCONS_UNLIKELY(ec))
275
0
                    {
276
0
                        return;
277
0
                    }
278
134k
                    break;
279
134k
                }
280
12.4M
                case parse_mode::indefinite_map_key:
281
12.4M
                {
282
12.4M
                    auto c = source_.peek();
283
12.4M
                    if (JSONCONS_UNLIKELY(c.eof))
284
18
                    {
285
18
                        ec = ubjson_errc::unexpected_eof;
286
18
                        more_ = false;
287
18
                        return;
288
18
                    }
289
12.4M
                    if (c.value == jsoncons::ubjson::ubjson_type::end_object_marker)
290
6.83M
                    {
291
6.83M
                        source_.ignore(1);
292
6.83M
                        end_object(visitor, ec);
293
6.83M
                        if (JSONCONS_UNLIKELY(ec))
294
0
                        {
295
0
                            return;
296
0
                        }
297
6.83M
                    }
298
5.65M
                    else
299
5.65M
                    {
300
5.65M
                        if (++state_stack_.back().index > max_items_)
301
0
                        {
302
0
                            ec = ubjson_errc::max_items_exceeded;
303
0
                            more_ = false;
304
0
                            return;
305
0
                        }
306
5.65M
                        read_key(visitor, ec);
307
5.65M
                        if (JSONCONS_UNLIKELY(ec))
308
93
                        {
309
93
                            return;
310
93
                        }
311
5.65M
                        state_stack_.back().mode = parse_mode::indefinite_map_value;
312
5.65M
                    }
313
12.4M
                    break;
314
12.4M
                }
315
12.4M
                case parse_mode::indefinite_map_value:
316
5.65M
                {
317
5.65M
                    state_stack_.back().mode = parse_mode::indefinite_map_key;
318
5.65M
                    read_type_and_value(visitor, ec);
319
5.65M
                    if (JSONCONS_UNLIKELY(ec))
320
49
                    {
321
49
                        return;
322
49
                    }
323
5.65M
                    break;
324
5.65M
                }
325
5.65M
                case parse_mode::root:
326
736
                {
327
736
                    state_stack_.back().mode = parse_mode::accept;
328
736
                    read_type_and_value(visitor, ec);
329
736
                    if (JSONCONS_UNLIKELY(ec))
330
71
                    {
331
71
                        return;
332
71
                    }
333
665
                    break;
334
736
                }
335
665
                case parse_mode::accept:
336
145
                {
337
145
                    JSONCONS_ASSERT(state_stack_.size() == 1);
338
145
                    state_stack_.clear();
339
145
                    more_ = false;
340
145
                    done_ = true;
341
145
                    visitor.flush();
342
145
                    break;
343
145
                }
344
76.3M
            }
345
76.3M
        }
346
736
    }
347
private:
348
    void read_type_and_value(json_visitor& visitor, std::error_code& ec)
349
25.2M
    {
350
25.2M
        if (source_.is_error())
351
0
        {
352
0
            ec = ubjson_errc::source_error;
353
0
            more_ = false;
354
0
            return;
355
0
        }   
356
357
25.2M
        uint8_t b;
358
25.2M
        if (source_.read(&b, 1) == 0)
359
29
        {
360
29
            ec = ubjson_errc::unexpected_eof;
361
29
            more_ = false;
362
29
            return;
363
29
        }
364
25.2M
        read_value(visitor, b, ec);
365
25.2M
    }
366
367
    void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec)
368
55.5M
    {
369
55.5M
        switch (type)
370
55.5M
        {
371
21.3M
            case jsoncons::ubjson::ubjson_type::null_type: 
372
21.3M
            {
373
21.3M
                visitor.null_value(semantic_tag::none, *this, ec);
374
21.3M
                more_ = !cursor_mode_;
375
21.3M
                break;
376
0
            }
377
488k
            case jsoncons::ubjson::ubjson_type::no_op_type: 
378
488k
            {
379
488k
                break;
380
0
            }
381
2.82M
            case jsoncons::ubjson::ubjson_type::true_type:
382
2.82M
            {
383
2.82M
                visitor.bool_value(true, semantic_tag::none, *this, ec);
384
2.82M
                more_ = !cursor_mode_;
385
2.82M
                break;
386
0
            }
387
2.17M
            case jsoncons::ubjson::ubjson_type::false_type:
388
2.17M
            {
389
2.17M
                visitor.bool_value(false, semantic_tag::none, *this, ec);
390
2.17M
                more_ = !cursor_mode_;
391
2.17M
                break;
392
0
            }
393
2.73M
            case jsoncons::ubjson::ubjson_type::int8_type: 
394
2.73M
            {
395
2.73M
                uint8_t buf[sizeof(int8_t)];
396
2.73M
                if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t))
397
17
                {
398
17
                    ec = ubjson_errc::unexpected_eof;
399
17
                    more_ = false;
400
17
                    return;
401
17
                }
402
2.73M
                int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf));
403
2.73M
                visitor.int64_value(val, semantic_tag::none, *this, ec);
404
2.73M
                more_ = !cursor_mode_;
405
2.73M
                break;
406
2.73M
            }
407
2.66M
            case jsoncons::ubjson::ubjson_type::uint8_type: 
408
2.66M
            {
409
2.66M
                uint8_t b;
410
2.66M
                if (source_.read(&b, 1) == 0)
411
13
                {
412
13
                    ec = ubjson_errc::unexpected_eof;
413
13
                    more_ = false;
414
13
                    return;
415
13
                }
416
2.66M
                visitor.uint64_value(b, semantic_tag::none, *this, ec);
417
2.66M
                more_ = !cursor_mode_;
418
2.66M
                break;
419
2.66M
            }
420
272k
            case jsoncons::ubjson::ubjson_type::int16_type: 
421
272k
            {
422
272k
                uint8_t buf[sizeof(int16_t)];
423
272k
                if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t))
424
7
                {
425
7
                    ec = ubjson_errc::unexpected_eof;
426
7
                    more_ = false;
427
7
                    return;
428
7
                }
429
272k
                int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf));
430
272k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
431
272k
                more_ = !cursor_mode_;
432
272k
                break;
433
272k
            }
434
83.8k
            case jsoncons::ubjson::ubjson_type::int32_type: 
435
83.8k
            {
436
83.8k
                uint8_t buf[sizeof(int32_t)];
437
83.8k
                if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t))
438
3
                {
439
3
                    ec = ubjson_errc::unexpected_eof;
440
3
                    more_ = false;
441
3
                    return;
442
3
                }
443
83.8k
                int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf));
444
83.8k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
445
83.8k
                more_ = !cursor_mode_;
446
83.8k
                break;
447
83.8k
            }
448
42.5k
            case jsoncons::ubjson::ubjson_type::int64_type: 
449
42.5k
            {
450
42.5k
                uint8_t buf[sizeof(int64_t)];
451
42.5k
                if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t))
452
12
                {
453
12
                    ec = ubjson_errc::unexpected_eof;
454
12
                    more_ = false;
455
12
                    return;
456
12
                }
457
42.5k
                int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf));
458
42.5k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
459
42.5k
                more_ = !cursor_mode_;
460
42.5k
                break;
461
42.5k
            }
462
231k
            case jsoncons::ubjson::ubjson_type::float32_type: 
463
231k
            {
464
231k
                uint8_t buf[sizeof(float)];
465
231k
                if (source_.read(buf, sizeof(float)) != sizeof(float))
466
10
                {
467
10
                    ec = ubjson_errc::unexpected_eof;
468
10
                    more_ = false;
469
10
                    return;
470
10
                }
471
231k
                float val = binary::big_to_native<float>(buf, sizeof(buf));
472
231k
                visitor.double_value(val, semantic_tag::none, *this, ec);
473
231k
                more_ = !cursor_mode_;
474
231k
                break;
475
231k
            }
476
30.3k
            case jsoncons::ubjson::ubjson_type::float64_type: 
477
30.3k
            {
478
30.3k
                uint8_t buf[sizeof(double)];
479
30.3k
                if (source_.read(buf, sizeof(double)) != sizeof(double))
480
1
                {
481
1
                    ec = ubjson_errc::unexpected_eof;
482
1
                    more_ = false;
483
1
                    return;
484
1
                }
485
30.3k
                double val = binary::big_to_native<double>(buf, sizeof(buf));
486
30.3k
                visitor.double_value(val, semantic_tag::none, *this, ec);
487
30.3k
                more_ = !cursor_mode_;
488
30.3k
                break;
489
30.3k
            }
490
7.66M
            case jsoncons::ubjson::ubjson_type::char_type: 
491
7.66M
            {
492
7.66M
                text_buffer_.clear();
493
7.66M
                if (source_reader<Source>::read(source_,text_buffer_,1) != 1)
494
31
                {
495
31
                    ec = ubjson_errc::unexpected_eof;
496
31
                    more_ = false;
497
31
                    return;
498
31
                }
499
7.66M
                auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
500
7.66M
                if (result.ec != unicode_traits::conv_errc())
501
5
                {
502
5
                    ec = ubjson_errc::invalid_utf8_text_string;
503
5
                    more_ = false;
504
5
                    return;
505
5
                }
506
7.66M
                visitor.string_value(text_buffer_, semantic_tag::none, *this, ec);
507
7.66M
                more_ = !cursor_mode_;
508
7.66M
                break;
509
7.66M
            }
510
1.22k
            case jsoncons::ubjson::ubjson_type::string_type: 
511
1.22k
            {
512
1.22k
                std::size_t length = get_length(ec);
513
1.22k
                if (JSONCONS_UNLIKELY(ec))
514
2
                {
515
2
                    return;
516
2
                }
517
1.22k
                text_buffer_.clear();
518
1.22k
                if (source_reader<Source>::read(source_,text_buffer_,length) != length)
519
8
                {
520
8
                    ec = ubjson_errc::unexpected_eof;
521
8
                    more_ = false;
522
8
                    return;
523
8
                }
524
1.21k
                auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
525
1.21k
                if (result.ec != unicode_traits::conv_errc())
526
12
                {
527
12
                    ec = ubjson_errc::invalid_utf8_text_string;
528
12
                    more_ = false;
529
12
                    return;
530
12
                }
531
1.20k
                visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::none, *this, ec);
532
1.20k
                more_ = !cursor_mode_;
533
1.20k
                break;
534
1.21k
            }
535
2.14k
            case jsoncons::ubjson::ubjson_type::high_precision_number_type: 
536
2.14k
            {
537
2.14k
                std::size_t length = get_length(ec);
538
2.14k
                if (JSONCONS_UNLIKELY(ec))
539
2
                {
540
2
                    return;
541
2
                }
542
2.14k
                text_buffer_.clear();
543
2.14k
                if (source_reader<Source>::read(source_,text_buffer_,length) != length)
544
33
                {
545
33
                    ec = ubjson_errc::unexpected_eof;
546
33
                    more_ = false;
547
33
                    return;
548
33
                }
549
2.10k
                if (jsoncons::is_base10(text_buffer_.data(),text_buffer_.length()))
550
88
                {
551
88
                    visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigint, *this, ec);
552
88
                    more_ = !cursor_mode_;
553
88
                }
554
2.02k
                else
555
2.02k
                {
556
2.02k
                    visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigdec, *this, ec);
557
2.02k
                    more_ = !cursor_mode_;
558
2.02k
                }
559
2.10k
                break;
560
2.14k
            }
561
8.05M
            case jsoncons::ubjson::ubjson_type::start_array_marker: 
562
8.05M
            {
563
8.05M
                begin_array(visitor,ec);
564
8.05M
                break;
565
2.14k
            }
566
6.91M
            case jsoncons::ubjson::ubjson_type::start_object_marker: 
567
6.91M
            {
568
6.91M
                begin_object(visitor, ec);
569
6.91M
                break;
570
2.14k
            }
571
85
            default:
572
85
            {
573
85
                ec = ubjson_errc::unknown_type;
574
85
                break;
575
2.14k
            }
576
55.5M
        }
577
55.5M
        if (JSONCONS_UNLIKELY(ec))
578
227
        {
579
227
            more_ = false;
580
227
        }
581
55.5M
    }
582
583
    void begin_array(json_visitor& visitor, std::error_code& ec)
584
8.05M
    {
585
8.05M
        if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_))
586
1
        {
587
1
            ec = ubjson_errc::max_nesting_depth_exceeded;
588
1
            more_ = false;
589
1
            return;
590
1
        } 
591
592
8.05M
        auto c = source_.peek();
593
8.05M
        if (JSONCONS_UNLIKELY(c.eof))
594
26
        {
595
26
            ec = ubjson_errc::unexpected_eof;
596
26
            more_ = false;
597
26
            return;
598
26
        }
599
8.05M
        if (c.value == jsoncons::ubjson::ubjson_type::type_marker)
600
35.7k
        {
601
35.7k
            source_.ignore(1);
602
35.7k
            uint8_t b;
603
35.7k
            if (source_.read(&b, 1) == 0)
604
10
            {
605
10
                ec = ubjson_errc::unexpected_eof;
606
10
                more_ = false;
607
10
                return;
608
10
            }
609
35.7k
            c = source_.peek();
610
35.7k
            if (JSONCONS_UNLIKELY(c.eof))
611
8
            {
612
8
                ec = ubjson_errc::unexpected_eof;
613
8
                more_ = false;
614
8
                return;
615
8
            }
616
35.7k
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
617
35.7k
            {
618
35.7k
                source_.ignore(1);
619
35.7k
                std::size_t length = get_length(ec);
620
35.7k
                if (JSONCONS_UNLIKELY(ec))
621
9
                {
622
9
                    return;
623
9
                }
624
35.7k
                if (length > max_items_)
625
1
                {
626
1
                    ec = ubjson_errc::max_items_exceeded;
627
1
                    more_ = false;
628
1
                    return;
629
1
                }
630
35.7k
                state_stack_.emplace_back(parse_mode::strongly_typed_array,length,b);
631
35.7k
                visitor.begin_array(length, semantic_tag::none, *this, ec);
632
35.7k
                more_ = !cursor_mode_;
633
35.7k
            }
634
1
            else
635
1
            {
636
1
                ec = ubjson_errc::count_required_after_type;
637
1
                more_ = false;
638
1
                return;
639
1
            }
640
35.7k
        }
641
8.02M
        else if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
642
93.1k
        {
643
93.1k
            source_.ignore(1);
644
93.1k
            std::size_t length = get_length(ec);
645
93.1k
            if (JSONCONS_UNLIKELY(ec))
646
10
            {
647
10
                return;
648
10
            }
649
93.0k
            if (length > max_items_)
650
1
            {
651
1
                ec = ubjson_errc::max_items_exceeded;
652
1
                more_ = false;
653
1
                return;
654
1
            }
655
93.0k
            state_stack_.emplace_back(parse_mode::array,length);
656
93.0k
            visitor.begin_array(length, semantic_tag::none, *this, ec);
657
93.0k
            more_ = !cursor_mode_;
658
93.0k
        }
659
7.92M
        else
660
7.92M
        {
661
7.92M
            state_stack_.emplace_back(parse_mode::indefinite_array,0);
662
7.92M
            visitor.begin_array(semantic_tag::none, *this, ec);
663
7.92M
            more_ = !cursor_mode_;
664
7.92M
        }
665
8.05M
    }
666
667
    void end_array(json_visitor& visitor, std::error_code& ec)
668
8.01M
    {
669
8.01M
        --nesting_depth_;
670
671
8.01M
        visitor.end_array(*this, ec);
672
8.01M
        more_ = !cursor_mode_;
673
8.01M
        if (level() == mark_level_)
674
0
        {
675
0
            more_ = false;
676
0
        }
677
8.01M
        state_stack_.pop_back();
678
8.01M
    }
679
680
    void begin_object(json_visitor& visitor, std::error_code& ec)
681
6.91M
    {
682
6.91M
        if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_))
683
0
        {
684
0
            ec = ubjson_errc::max_nesting_depth_exceeded;
685
0
            more_ = false;
686
0
            return;
687
0
        } 
688
689
6.91M
        auto c = source_.peek();
690
6.91M
        if (JSONCONS_UNLIKELY(c.eof))
691
30
        {
692
30
            ec = ubjson_errc::unexpected_eof;
693
30
            more_ = false;
694
30
            return;
695
30
        }
696
6.91M
        if (c.value == jsoncons::ubjson::ubjson_type::type_marker)
697
74.1k
        {
698
74.1k
            source_.ignore(1);
699
74.1k
            uint8_t b;
700
74.1k
            if (source_.read(&b, 1) == 0)
701
9
            {
702
9
                ec = ubjson_errc::unexpected_eof;
703
9
                more_ = false;
704
9
                return;
705
9
            }
706
74.1k
            c = source_.peek();
707
74.1k
            if (JSONCONS_UNLIKELY(c.eof))
708
7
            {
709
7
                ec = ubjson_errc::unexpected_eof;
710
7
                more_ = false;
711
7
                return;
712
7
            }
713
74.1k
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
714
74.1k
            {
715
74.1k
                source_.ignore(1);
716
74.1k
                std::size_t length = get_length(ec);
717
74.1k
                if (JSONCONS_UNLIKELY(ec))
718
10
                {
719
10
                    return;
720
10
                }
721
74.1k
                if (length > max_items_)
722
2
                {
723
2
                    ec = ubjson_errc::max_items_exceeded;
724
2
                    more_ = false;
725
2
                    return;
726
2
                }
727
74.1k
                state_stack_.emplace_back(parse_mode::strongly_typed_map_key,length,b);
728
74.1k
                visitor.begin_object(length, semantic_tag::none, *this, ec);
729
74.1k
                more_ = !cursor_mode_;
730
74.1k
            }
731
1
            else
732
1
            {
733
1
                ec = ubjson_errc::count_required_after_type;
734
1
                more_ = false;
735
1
                return;
736
1
            }
737
74.1k
        }
738
6.84M
        else
739
6.84M
        {
740
6.84M
            c = source_.peek();
741
6.84M
            if (JSONCONS_UNLIKELY(c.eof))
742
0
            {
743
0
                ec = ubjson_errc::unexpected_eof;
744
0
                more_ = false;
745
0
                return;
746
0
            }
747
6.84M
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
748
5.46k
            {
749
5.46k
                source_.ignore(1);
750
5.46k
                std::size_t length = get_length(ec);
751
5.46k
                if (JSONCONS_UNLIKELY(ec))
752
5
                {
753
5
                    return;
754
5
                }
755
5.46k
                if (length > max_items_)
756
4
                {
757
4
                    ec = ubjson_errc::max_items_exceeded;
758
4
                    more_ = false;
759
4
                    return;
760
4
                }
761
5.45k
                state_stack_.emplace_back(parse_mode::map_key,length);
762
5.45k
                visitor.begin_object(length, semantic_tag::none, *this, ec);
763
5.45k
                more_ = !cursor_mode_;
764
5.45k
            }
765
6.83M
            else
766
6.83M
            {
767
6.83M
                state_stack_.emplace_back(parse_mode::indefinite_map_key,0);
768
6.83M
                visitor.begin_object(semantic_tag::none, *this, ec);
769
6.83M
                more_ = !cursor_mode_;
770
6.83M
            }
771
6.84M
        }
772
6.91M
    }
773
774
    void end_object(json_visitor& visitor, std::error_code& ec)
775
6.91M
    {
776
6.91M
        --nesting_depth_;
777
6.91M
        visitor.end_object(*this, ec);
778
6.91M
        more_ = !cursor_mode_;
779
6.91M
        if (level() == mark_level_)
780
0
        {
781
0
            more_ = false;
782
0
        }
783
6.91M
        state_stack_.pop_back();
784
6.91M
    }
785
786
    std::size_t get_length(std::error_code& ec)
787
6.01M
    {
788
6.01M
        std::size_t length = 0;
789
6.01M
        uint8_t type;
790
6.01M
        if (source_.read(&type, 1) == 0)
791
27
        {
792
27
            ec = ubjson_errc::unexpected_eof;
793
27
            more_ = false;
794
27
            return length;
795
27
        }
796
6.01M
        switch (type)
797
6.01M
        {
798
1.25M
            case jsoncons::ubjson::ubjson_type::int8_type: 
799
1.25M
            {
800
1.25M
                uint8_t buf[sizeof(int8_t)];
801
1.25M
                if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t))
802
2
                {
803
2
                    ec = ubjson_errc::unexpected_eof;
804
2
                    more_ = false;
805
2
                    return length;
806
2
                }
807
1.25M
                int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf));
808
1.25M
                if (val >= 0)
809
1.25M
                {
810
1.25M
                    length = val;
811
1.25M
                }
812
0
                else
813
0
                {
814
0
                    ec = ubjson_errc::length_is_negative;
815
0
                    more_ = false;
816
0
                    return length;
817
0
                }
818
1.25M
                break;
819
1.25M
            }
820
4.74M
            case jsoncons::ubjson::ubjson_type::uint8_type: 
821
4.74M
            {
822
4.74M
                uint8_t b;
823
4.74M
                if (source_.read(&b, 1) == 0)
824
1
                {
825
1
                    ec = ubjson_errc::unexpected_eof;
826
1
                    more_ = false;
827
1
                    return length;
828
1
                }
829
4.74M
                length = b;
830
4.74M
                break;
831
4.74M
            }
832
13.4k
            case jsoncons::ubjson::ubjson_type::int16_type: 
833
13.4k
            {
834
13.4k
                uint8_t buf[sizeof(int16_t)];
835
13.4k
                if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t))
836
0
                {
837
0
                    ec = ubjson_errc::unexpected_eof;
838
0
                    more_ = false;
839
0
                    return length;
840
0
                }
841
13.4k
                int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf));
842
13.4k
                if (val >= 0)
843
13.4k
                {
844
13.4k
                    length = val;
845
13.4k
                }
846
0
                else
847
0
                {
848
0
                    ec = ubjson_errc::length_is_negative;
849
0
                    more_ = false;
850
0
                    return length;
851
0
                }
852
13.4k
                break;
853
13.4k
            }
854
13.4k
            case jsoncons::ubjson::ubjson_type::int32_type: 
855
455
            {
856
455
                uint8_t buf[sizeof(int32_t)];
857
455
                if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t))
858
0
                {
859
0
                    ec = ubjson_errc::unexpected_eof;
860
0
                    more_ = false;
861
0
                    return length;
862
0
                }
863
455
                int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf));
864
455
                if (val >= 0)
865
455
                {
866
455
                    length = static_cast<std::size_t>(val);
867
455
                }
868
0
                else
869
0
                {
870
0
                    ec = ubjson_errc::length_is_negative;
871
0
                    more_ = false;
872
0
                    return length;
873
0
                }
874
455
                break;
875
455
            }
876
455
            case jsoncons::ubjson::ubjson_type::int64_type: 
877
112
            {
878
112
                uint8_t buf[sizeof(int64_t)];
879
112
                if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t))
880
0
                {
881
0
                    ec = ubjson_errc::unexpected_eof;
882
0
                    more_ = false;
883
0
                    return length;
884
0
                }
885
112
                int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf));
886
112
                if (val >= 0)
887
110
                {
888
110
                    length = (std::size_t)val;
889
110
                    if (length != (uint64_t)val)
890
0
                    {
891
0
                        ec = ubjson_errc::number_too_large;
892
0
                        more_ = false;
893
0
                        return length;
894
0
                    }
895
110
                }
896
2
                else
897
2
                {
898
2
                    ec = ubjson_errc::length_is_negative;
899
2
                    more_ = false;
900
2
                    return length;
901
2
                }
902
110
                break;
903
112
            }
904
110
            default:
905
50
            {
906
50
                ec = ubjson_errc::length_must_be_integer;
907
50
                more_ = false;
908
50
                return length;
909
112
            }
910
6.01M
        }
911
6.01M
        return length;
912
6.01M
    }
913
914
    void read_key(json_visitor& visitor, std::error_code& ec)
915
5.79M
    {
916
5.79M
        std::size_t length = get_length(ec);
917
5.79M
        if (JSONCONS_UNLIKELY(ec))
918
44
        {
919
44
            ec = ubjson_errc::key_expected;
920
44
            more_ = false;
921
44
            return;
922
44
        }
923
5.79M
        text_buffer_.clear();
924
5.79M
        if (source_reader<Source>::read(source_,text_buffer_,length) != length)
925
44
        {
926
44
            ec = ubjson_errc::unexpected_eof;
927
44
            more_ = false;
928
44
            return;
929
44
        }
930
931
5.79M
        auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
932
5.79M
        if (result.ec != unicode_traits::conv_errc())
933
18
        {
934
18
            ec = ubjson_errc::invalid_utf8_text_string;
935
18
            more_ = false;
936
18
            return;
937
18
        }
938
5.79M
        visitor.key(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), *this, ec);
939
5.79M
        more_ = !cursor_mode_;
940
5.79M
    }
941
};
942
943
} // namespace ubjson
944
} // namespace jsoncons
945
946
#endif