Coverage Report

Created: 2026-01-17 06:22

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_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/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
11.5M
        : mode(mode), length(length), type(type)
46
11.5M
    {
47
11.5M
    }
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
743
       : source_(std::forward<Sourceable>(source)), 
80
743
         max_nesting_depth_(options.max_nesting_depth()),
81
743
         max_items_(options.max_items()),
82
743
         text_buffer_(alloc),
83
743
         state_stack_(alloc)
84
743
    {
85
743
        state_stack_.emplace_back(parse_mode::root,0);
86
743
    }
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
284
       : source_(std::forward<Sourceable>(source)), 
80
284
         max_nesting_depth_(options.max_nesting_depth()),
81
284
         max_items_(options.max_items()),
82
284
         text_buffer_(alloc),
83
284
         state_stack_(alloc)
84
284
    {
85
284
        state_stack_.emplace_back(parse_mode::root,0);
86
284
    }
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
459
       : source_(std::forward<Sourceable>(source)), 
80
459
         max_nesting_depth_(options.max_nesting_depth()),
81
459
         max_items_(options.max_items()),
82
459
         text_buffer_(alloc),
83
459
         state_stack_(alloc)
84
459
    {
85
459
        state_stack_.emplace_back(parse_mode::root,0);
86
459
    }
87
88
    void restart()
89
    {
90
        more_ = true;
91
    }
92
93
    void reset()
94
743
    {
95
743
        more_ = true;
96
743
        done_ = false;
97
743
        text_buffer_.clear();
98
743
        state_stack_.clear();
99
743
        state_stack_.emplace_back(parse_mode::root,0,uint8_t(0));
100
743
        nesting_depth_ = 0;
101
743
    }
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
11.4M
    {
117
11.4M
        return static_cast<int>(state_stack_.size());
118
11.4M
    }
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
335
    {
142
335
        return 0;
143
335
    }
144
145
    std::size_t column() const override
146
335
    {
147
335
        return source_.position();
148
335
    }
149
150
    void parse(json_visitor& visitor, std::error_code& ec)
151
743
    {
152
73.6M
        while (!done_ && more_)
153
73.6M
        {
154
73.6M
            switch (state_stack_.back().mode)
155
73.6M
            {
156
127k
                case parse_mode::array:
157
127k
                {
158
127k
                    if (state_stack_.back().index < state_stack_.back().length)
159
29.3k
                    {
160
29.3k
                        ++state_stack_.back().index;
161
29.3k
                        read_type_and_value(visitor, ec);
162
29.3k
                        if (JSONCONS_UNLIKELY(ec))
163
2
                        {
164
2
                            return;
165
2
                        }
166
29.3k
                    }
167
97.6k
                    else
168
97.6k
                    {
169
97.6k
                        end_array(visitor, ec);
170
97.6k
                    }
171
127k
                    break;
172
127k
                }
173
35.5M
                case parse_mode::strongly_typed_array:
174
35.5M
                {
175
35.5M
                    if (state_stack_.back().index < state_stack_.back().length)
176
35.4M
                    {
177
35.4M
                        ++state_stack_.back().index;
178
35.4M
                        read_value(visitor, state_stack_.back().type, ec);
179
35.4M
                        if (JSONCONS_UNLIKELY(ec))
180
174
                        {
181
174
                            return;
182
174
                        }
183
35.4M
                    }
184
23.1k
                    else
185
23.1k
                    {
186
23.1k
                        end_array(visitor, ec);
187
23.1k
                    }
188
35.5M
                    break;
189
35.5M
                }
190
35.5M
                case parse_mode::indefinite_array:
191
21.1M
                {
192
21.1M
                    auto c = source_.peek();
193
21.1M
                    if (JSONCONS_UNLIKELY(c.eof))
194
55
                    {
195
55
                        ec = ubjson_errc::unexpected_eof;
196
55
                        more_ = false;
197
55
                        return;
198
55
                    }
199
21.1M
                    if (c.value == jsoncons::ubjson::ubjson_type::end_array_marker)
200
6.69M
                    {
201
6.69M
                        source_.ignore(1);
202
6.69M
                        end_array(visitor, ec);
203
6.69M
                        if (JSONCONS_UNLIKELY(ec))
204
0
                        {
205
0
                            return;
206
0
                        }
207
6.69M
                    }
208
14.4M
                    else
209
14.4M
                    {
210
14.4M
                        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
14.4M
                        read_type_and_value(visitor, ec);
217
14.4M
                        if (JSONCONS_UNLIKELY(ec))
218
102
                        {
219
102
                            return;
220
102
                        }
221
14.4M
                    }
222
21.1M
                    break;
223
21.1M
                }
224
21.1M
                case parse_mode::map_key:
225
15.0k
                {
226
15.0k
                    if (state_stack_.back().index < state_stack_.back().length)
227
10.4k
                    {
228
10.4k
                        ++state_stack_.back().index;
229
10.4k
                        read_key(visitor, ec);
230
10.4k
                        if (JSONCONS_UNLIKELY(ec))
231
7
                        {
232
7
                            return;
233
7
                        }
234
10.4k
                        state_stack_.back().mode = parse_mode::map_value;
235
10.4k
                    }
236
4.51k
                    else
237
4.51k
                    {
238
4.51k
                        end_object(visitor, ec);
239
4.51k
                    }
240
14.9k
                    break;
241
15.0k
                }
242
14.9k
                case parse_mode::map_value:
243
10.4k
                {
244
10.4k
                    state_stack_.back().mode = parse_mode::map_key;
245
10.4k
                    read_type_and_value(visitor, ec);
246
10.4k
                    if (JSONCONS_UNLIKELY(ec))
247
9
                    {
248
9
                        return;
249
9
                    }
250
10.4k
                    break;
251
10.4k
                }
252
148k
                case parse_mode::strongly_typed_map_key:
253
148k
                {
254
148k
                    if (state_stack_.back().index < state_stack_.back().length)
255
63.3k
                    {
256
63.3k
                        ++state_stack_.back().index;
257
63.3k
                        read_key(visitor, ec);
258
63.3k
                        if (JSONCONS_UNLIKELY(ec))
259
6
                        {
260
6
                            return;
261
6
                        }
262
63.3k
                        state_stack_.back().mode = parse_mode::strongly_typed_map_value;
263
63.3k
                    }
264
85.2k
                    else
265
85.2k
                    {
266
85.2k
                        end_object(visitor, ec);
267
85.2k
                    }
268
148k
                    break;
269
148k
                }
270
148k
                case parse_mode::strongly_typed_map_value:
271
63.3k
                {
272
63.3k
                    state_stack_.back().mode = parse_mode::strongly_typed_map_key;
273
63.3k
                    read_value(visitor, state_stack_.back().type, ec);
274
63.3k
                    if (JSONCONS_UNLIKELY(ec))
275
0
                    {
276
0
                        return;
277
0
                    }
278
63.3k
                    break;
279
63.3k
                }
280
10.6M
                case parse_mode::indefinite_map_key:
281
10.6M
                {
282
10.6M
                    auto c = source_.peek();
283
10.6M
                    if (JSONCONS_UNLIKELY(c.eof))
284
23
                    {
285
23
                        ec = ubjson_errc::unexpected_eof;
286
23
                        more_ = false;
287
23
                        return;
288
23
                    }
289
10.6M
                    if (c.value == jsoncons::ubjson::ubjson_type::end_object_marker)
290
4.57M
                    {
291
4.57M
                        source_.ignore(1);
292
4.57M
                        end_object(visitor, ec);
293
4.57M
                        if (JSONCONS_UNLIKELY(ec))
294
0
                        {
295
0
                            return;
296
0
                        }
297
4.57M
                    }
298
6.03M
                    else
299
6.03M
                    {
300
6.03M
                        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
6.03M
                        read_key(visitor, ec);
307
6.03M
                        if (JSONCONS_UNLIKELY(ec))
308
89
                        {
309
89
                            return;
310
89
                        }
311
6.03M
                        state_stack_.back().mode = parse_mode::indefinite_map_value;
312
6.03M
                    }
313
10.6M
                    break;
314
10.6M
                }
315
10.6M
                case parse_mode::indefinite_map_value:
316
6.03M
                {
317
6.03M
                    state_stack_.back().mode = parse_mode::indefinite_map_key;
318
6.03M
                    read_type_and_value(visitor, ec);
319
6.03M
                    if (JSONCONS_UNLIKELY(ec))
320
52
                    {
321
52
                        return;
322
52
                    }
323
6.03M
                    break;
324
6.03M
                }
325
6.03M
                case parse_mode::root:
326
743
                {
327
743
                    state_stack_.back().mode = parse_mode::accept;
328
743
                    read_type_and_value(visitor, ec);
329
743
                    if (JSONCONS_UNLIKELY(ec))
330
83
                    {
331
83
                        return;
332
83
                    }
333
660
                    break;
334
743
                }
335
660
                case parse_mode::accept:
336
141
                {
337
141
                    JSONCONS_ASSERT(state_stack_.size() == 1);
338
141
                    state_stack_.clear();
339
141
                    more_ = false;
340
141
                    done_ = true;
341
141
                    visitor.flush();
342
141
                    break;
343
141
                }
344
73.6M
            }
345
73.6M
        }
346
743
    }
347
private:
348
    void read_type_and_value(json_visitor& visitor, std::error_code& ec)
349
20.5M
    {
350
20.5M
        if (source_.is_error())
351
0
        {
352
0
            ec = ubjson_errc::source_error;
353
0
            more_ = false;
354
0
            return;
355
0
        }   
356
357
20.5M
        uint8_t b;
358
20.5M
        if (source_.read(&b, 1) == 0)
359
33
        {
360
33
            ec = ubjson_errc::unexpected_eof;
361
33
            more_ = false;
362
33
            return;
363
33
        }
364
20.5M
        read_value(visitor, b, ec);
365
20.5M
    }
366
367
    void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec)
368
56.0M
    {
369
56.0M
        switch (type)
370
56.0M
        {
371
23.3M
            case jsoncons::ubjson::ubjson_type::null_type: 
372
23.3M
            {
373
23.3M
                visitor.null_value(semantic_tag::none, *this, ec);
374
23.3M
                more_ = !cursor_mode_;
375
23.3M
                break;
376
0
            }
377
482k
            case jsoncons::ubjson::ubjson_type::no_op_type: 
378
482k
            {
379
482k
                break;
380
0
            }
381
2.96M
            case jsoncons::ubjson::ubjson_type::true_type:
382
2.96M
            {
383
2.96M
                visitor.bool_value(true, semantic_tag::none, *this, ec);
384
2.96M
                more_ = !cursor_mode_;
385
2.96M
                break;
386
0
            }
387
2.01M
            case jsoncons::ubjson::ubjson_type::false_type:
388
2.01M
            {
389
2.01M
                visitor.bool_value(false, semantic_tag::none, *this, ec);
390
2.01M
                more_ = !cursor_mode_;
391
2.01M
                break;
392
0
            }
393
3.63M
            case jsoncons::ubjson::ubjson_type::int8_type: 
394
3.63M
            {
395
3.63M
                uint8_t buf[sizeof(int8_t)];
396
3.63M
                if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t))
397
15
                {
398
15
                    ec = ubjson_errc::unexpected_eof;
399
15
                    more_ = false;
400
15
                    return;
401
15
                }
402
3.63M
                int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf));
403
3.63M
                visitor.int64_value(val, semantic_tag::none, *this, ec);
404
3.63M
                more_ = !cursor_mode_;
405
3.63M
                break;
406
3.63M
            }
407
2.36M
            case jsoncons::ubjson::ubjson_type::uint8_type: 
408
2.36M
            {
409
2.36M
                uint8_t b;
410
2.36M
                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.36M
                visitor.uint64_value(b, semantic_tag::none, *this, ec);
417
2.36M
                more_ = !cursor_mode_;
418
2.36M
                break;
419
2.36M
            }
420
873k
            case jsoncons::ubjson::ubjson_type::int16_type: 
421
873k
            {
422
873k
                uint8_t buf[sizeof(int16_t)];
423
873k
                if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t))
424
10
                {
425
10
                    ec = ubjson_errc::unexpected_eof;
426
10
                    more_ = false;
427
10
                    return;
428
10
                }
429
873k
                int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf));
430
873k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
431
873k
                more_ = !cursor_mode_;
432
873k
                break;
433
873k
            }
434
87.4k
            case jsoncons::ubjson::ubjson_type::int32_type: 
435
87.4k
            {
436
87.4k
                uint8_t buf[sizeof(int32_t)];
437
87.4k
                if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t))
438
4
                {
439
4
                    ec = ubjson_errc::unexpected_eof;
440
4
                    more_ = false;
441
4
                    return;
442
4
                }
443
87.4k
                int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf));
444
87.4k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
445
87.4k
                more_ = !cursor_mode_;
446
87.4k
                break;
447
87.4k
            }
448
43.0k
            case jsoncons::ubjson::ubjson_type::int64_type: 
449
43.0k
            {
450
43.0k
                uint8_t buf[sizeof(int64_t)];
451
43.0k
                if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t))
452
10
                {
453
10
                    ec = ubjson_errc::unexpected_eof;
454
10
                    more_ = false;
455
10
                    return;
456
10
                }
457
43.0k
                int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf));
458
43.0k
                visitor.int64_value(val, semantic_tag::none, *this, ec);
459
43.0k
                more_ = !cursor_mode_;
460
43.0k
                break;
461
43.0k
            }
462
239k
            case jsoncons::ubjson::ubjson_type::float32_type: 
463
239k
            {
464
239k
                uint8_t buf[sizeof(float)];
465
239k
                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
239k
                float val = binary::big_to_native<float>(buf, sizeof(buf));
472
239k
                visitor.double_value(val, semantic_tag::none, *this, ec);
473
239k
                more_ = !cursor_mode_;
474
239k
                break;
475
239k
            }
476
1.65k
            case jsoncons::ubjson::ubjson_type::float64_type: 
477
1.65k
            {
478
1.65k
                uint8_t buf[sizeof(double)];
479
1.65k
                if (source_.read(buf, sizeof(double)) != sizeof(double))
480
0
                {
481
0
                    ec = ubjson_errc::unexpected_eof;
482
0
                    more_ = false;
483
0
                    return;
484
0
                }
485
1.65k
                double val = binary::big_to_native<double>(buf, sizeof(buf));
486
1.65k
                visitor.double_value(val, semantic_tag::none, *this, ec);
487
1.65k
                more_ = !cursor_mode_;
488
1.65k
                break;
489
1.65k
            }
490
8.43M
            case jsoncons::ubjson::ubjson_type::char_type: 
491
8.43M
            {
492
8.43M
                text_buffer_.clear();
493
8.43M
                if (source_reader<Source>::read(source_,text_buffer_,1) != 1)
494
34
                {
495
34
                    ec = ubjson_errc::unexpected_eof;
496
34
                    more_ = false;
497
34
                    return;
498
34
                }
499
8.43M
                auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
500
8.43M
                if (result.ec != unicode_traits::conv_errc())
501
3
                {
502
3
                    ec = ubjson_errc::invalid_utf8_text_string;
503
3
                    more_ = false;
504
3
                    return;
505
3
                }
506
8.43M
                visitor.string_value(text_buffer_, semantic_tag::none, *this, ec);
507
8.43M
                more_ = !cursor_mode_;
508
8.43M
                break;
509
8.43M
            }
510
1.33k
            case jsoncons::ubjson::ubjson_type::string_type: 
511
1.33k
            {
512
1.33k
                std::size_t length = get_length(ec);
513
1.33k
                if (JSONCONS_UNLIKELY(ec))
514
0
                {
515
0
                    return;
516
0
                }
517
1.33k
                text_buffer_.clear();
518
1.33k
                if (source_reader<Source>::read(source_,text_buffer_,length) != length)
519
17
                {
520
17
                    ec = ubjson_errc::unexpected_eof;
521
17
                    more_ = false;
522
17
                    return;
523
17
                }
524
1.31k
                auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
525
1.31k
                if (result.ec != unicode_traits::conv_errc())
526
16
                {
527
16
                    ec = ubjson_errc::invalid_utf8_text_string;
528
16
                    more_ = false;
529
16
                    return;
530
16
                }
531
1.30k
                visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::none, *this, ec);
532
1.30k
                more_ = !cursor_mode_;
533
1.30k
                break;
534
1.31k
            }
535
8.52k
            case jsoncons::ubjson::ubjson_type::high_precision_number_type: 
536
8.52k
            {
537
8.52k
                std::size_t length = get_length(ec);
538
8.52k
                if (JSONCONS_UNLIKELY(ec))
539
4
                {
540
4
                    return;
541
4
                }
542
8.52k
                text_buffer_.clear();
543
8.52k
                if (source_reader<Source>::read(source_,text_buffer_,length) != length)
544
31
                {
545
31
                    ec = ubjson_errc::unexpected_eof;
546
31
                    more_ = false;
547
31
                    return;
548
31
                }
549
8.49k
                if (jsoncons::is_base10(text_buffer_.data(),text_buffer_.length()))
550
95
                {
551
95
                    visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigint, *this, ec);
552
95
                    more_ = !cursor_mode_;
553
95
                }
554
8.39k
                else
555
8.39k
                {
556
8.39k
                    visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigdec, *this, ec);
557
8.39k
                    more_ = !cursor_mode_;
558
8.39k
                }
559
8.49k
                break;
560
8.52k
            }
561
6.85M
            case jsoncons::ubjson::ubjson_type::start_array_marker: 
562
6.85M
            {
563
6.85M
                begin_array(visitor,ec);
564
6.85M
                break;
565
8.52k
            }
566
4.66M
            case jsoncons::ubjson::ubjson_type::start_object_marker: 
567
4.66M
            {
568
4.66M
                begin_object(visitor, ec);
569
4.66M
                break;
570
8.52k
            }
571
86
            default:
572
86
            {
573
86
                ec = ubjson_errc::unknown_type;
574
86
                break;
575
8.52k
            }
576
56.0M
        }
577
56.0M
        if (JSONCONS_UNLIKELY(ec))
578
222
        {
579
222
            more_ = false;
580
222
        }
581
56.0M
    }
582
583
    void begin_array(json_visitor& visitor, std::error_code& ec)
584
6.85M
    {
585
6.85M
        if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_))
586
0
        {
587
0
            ec = ubjson_errc::max_nesting_depth_exceeded;
588
0
            more_ = false;
589
0
            return;
590
0
        } 
591
592
6.85M
        auto c = source_.peek();
593
6.85M
        if (JSONCONS_UNLIKELY(c.eof))
594
23
        {
595
23
            ec = ubjson_errc::unexpected_eof;
596
23
            more_ = false;
597
23
            return;
598
23
        }
599
6.85M
        if (c.value == jsoncons::ubjson::ubjson_type::type_marker)
600
40.4k
        {
601
40.4k
            source_.ignore(1);
602
40.4k
            uint8_t b;
603
40.4k
            if (source_.read(&b, 1) == 0)
604
9
            {
605
9
                ec = ubjson_errc::unexpected_eof;
606
9
                more_ = false;
607
9
                return;
608
9
            }
609
40.4k
            c = source_.peek();
610
40.4k
            if (JSONCONS_UNLIKELY(c.eof))
611
8
            {
612
8
                ec = ubjson_errc::unexpected_eof;
613
8
                more_ = false;
614
8
                return;
615
8
            }
616
40.4k
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
617
40.4k
            {
618
40.4k
                source_.ignore(1);
619
40.4k
                std::size_t length = get_length(ec);
620
40.4k
                if (JSONCONS_UNLIKELY(ec))
621
8
                {
622
8
                    return;
623
8
                }
624
40.4k
                if (length > max_items_)
625
1
                {
626
1
                    ec = ubjson_errc::max_items_exceeded;
627
1
                    more_ = false;
628
1
                    return;
629
1
                }
630
40.4k
                state_stack_.emplace_back(parse_mode::strongly_typed_array,length,b);
631
40.4k
                visitor.begin_array(length, semantic_tag::none, *this, ec);
632
40.4k
                more_ = !cursor_mode_;
633
40.4k
            }
634
0
            else
635
0
            {
636
0
                ec = ubjson_errc::count_required_after_type;
637
0
                more_ = false;
638
0
                return;
639
0
            }
640
40.4k
        }
641
6.81M
        else if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
642
98.0k
        {
643
98.0k
            source_.ignore(1);
644
98.0k
            std::size_t length = get_length(ec);
645
98.0k
            if (JSONCONS_UNLIKELY(ec))
646
11
            {
647
11
                return;
648
11
            }
649
98.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
98.0k
            state_stack_.emplace_back(parse_mode::array,length);
656
98.0k
            visitor.begin_array(length, semantic_tag::none, *this, ec);
657
98.0k
            more_ = !cursor_mode_;
658
98.0k
        }
659
6.71M
        else
660
6.71M
        {
661
6.71M
            state_stack_.emplace_back(parse_mode::indefinite_array,0);
662
6.71M
            visitor.begin_array(semantic_tag::none, *this, ec);
663
6.71M
            more_ = !cursor_mode_;
664
6.71M
        }
665
6.85M
    }
666
667
    void end_array(json_visitor& visitor, std::error_code& ec)
668
6.81M
    {
669
6.81M
        --nesting_depth_;
670
671
6.81M
        visitor.end_array(*this, ec);
672
6.81M
        more_ = !cursor_mode_;
673
6.81M
        if (level() == mark_level_)
674
0
        {
675
0
            more_ = false;
676
0
        }
677
6.81M
        state_stack_.pop_back();
678
6.81M
    }
679
680
    void begin_object(json_visitor& visitor, std::error_code& ec)
681
4.66M
    {
682
4.66M
        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
4.66M
        auto c = source_.peek();
690
4.66M
        if (JSONCONS_UNLIKELY(c.eof))
691
25
        {
692
25
            ec = ubjson_errc::unexpected_eof;
693
25
            more_ = false;
694
25
            return;
695
25
        }
696
4.66M
        if (c.value == jsoncons::ubjson::ubjson_type::type_marker)
697
85.2k
        {
698
85.2k
            source_.ignore(1);
699
85.2k
            uint8_t b;
700
85.2k
            if (source_.read(&b, 1) == 0)
701
10
            {
702
10
                ec = ubjson_errc::unexpected_eof;
703
10
                more_ = false;
704
10
                return;
705
10
            }
706
85.2k
            c = source_.peek();
707
85.2k
            if (JSONCONS_UNLIKELY(c.eof))
708
7
            {
709
7
                ec = ubjson_errc::unexpected_eof;
710
7
                more_ = false;
711
7
                return;
712
7
            }
713
85.2k
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
714
85.2k
            {
715
85.2k
                source_.ignore(1);
716
85.2k
                std::size_t length = get_length(ec);
717
85.2k
                if (JSONCONS_UNLIKELY(ec))
718
10
                {
719
10
                    return;
720
10
                }
721
85.2k
                if (length > max_items_)
722
3
                {
723
3
                    ec = ubjson_errc::max_items_exceeded;
724
3
                    more_ = false;
725
3
                    return;
726
3
                }
727
85.2k
                state_stack_.emplace_back(parse_mode::strongly_typed_map_key,length,b);
728
85.2k
                visitor.begin_object(length, semantic_tag::none, *this, ec);
729
85.2k
                more_ = !cursor_mode_;
730
85.2k
            }
731
2
            else
732
2
            {
733
2
                ec = ubjson_errc::count_required_after_type;
734
2
                more_ = false;
735
2
                return;
736
2
            }
737
85.2k
        }
738
4.58M
        else
739
4.58M
        {
740
4.58M
            c = source_.peek();
741
4.58M
            if (JSONCONS_UNLIKELY(c.eof))
742
0
            {
743
0
                ec = ubjson_errc::unexpected_eof;
744
0
                more_ = false;
745
0
                return;
746
0
            }
747
4.58M
            if (c.value == jsoncons::ubjson::ubjson_type::count_marker)
748
5.25k
            {
749
5.25k
                source_.ignore(1);
750
5.25k
                std::size_t length = get_length(ec);
751
5.25k
                if (JSONCONS_UNLIKELY(ec))
752
5
                {
753
5
                    return;
754
5
                }
755
5.25k
                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.24k
                state_stack_.emplace_back(parse_mode::map_key,length);
762
5.24k
                visitor.begin_object(length, semantic_tag::none, *this, ec);
763
5.24k
                more_ = !cursor_mode_;
764
5.24k
            }
765
4.57M
            else
766
4.57M
            {
767
4.57M
                state_stack_.emplace_back(parse_mode::indefinite_map_key,0);
768
4.57M
                visitor.begin_object(semantic_tag::none, *this, ec);
769
4.57M
                more_ = !cursor_mode_;
770
4.57M
            }
771
4.58M
        }
772
4.66M
    }
773
774
    void end_object(json_visitor& visitor, std::error_code& ec)
775
4.66M
    {
776
4.66M
        --nesting_depth_;
777
4.66M
        visitor.end_object(*this, ec);
778
4.66M
        more_ = !cursor_mode_;
779
4.66M
        if (level() == mark_level_)
780
0
        {
781
0
            more_ = false;
782
0
        }
783
4.66M
        state_stack_.pop_back();
784
4.66M
    }
785
786
    std::size_t get_length(std::error_code& ec)
787
6.34M
    {
788
6.34M
        std::size_t length = 0;
789
6.34M
        uint8_t type;
790
6.34M
        if (source_.read(&type, 1) == 0)
791
29
        {
792
29
            ec = ubjson_errc::unexpected_eof;
793
29
            more_ = false;
794
29
            return length;
795
29
        }
796
6.34M
        switch (type)
797
6.34M
        {
798
1.39M
            case jsoncons::ubjson::ubjson_type::int8_type: 
799
1.39M
            {
800
1.39M
                uint8_t buf[sizeof(int8_t)];
801
1.39M
                if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t))
802
0
                {
803
0
                    ec = ubjson_errc::unexpected_eof;
804
0
                    more_ = false;
805
0
                    return length;
806
0
                }
807
1.39M
                int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf));
808
1.39M
                if (val >= 0)
809
1.39M
                {
810
1.39M
                    length = val;
811
1.39M
                }
812
1
                else
813
1
                {
814
1
                    ec = ubjson_errc::length_is_negative;
815
1
                    more_ = false;
816
1
                    return length;
817
1
                }
818
1.39M
                break;
819
1.39M
            }
820
4.94M
            case jsoncons::ubjson::ubjson_type::uint8_type: 
821
4.94M
            {
822
4.94M
                uint8_t b;
823
4.94M
                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.94M
                length = b;
830
4.94M
                break;
831
4.94M
            }
832
14.8k
            case jsoncons::ubjson::ubjson_type::int16_type: 
833
14.8k
            {
834
14.8k
                uint8_t buf[sizeof(int16_t)];
835
14.8k
                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
14.8k
                int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf));
842
14.8k
                if (val >= 0)
843
14.8k
                {
844
14.8k
                    length = val;
845
14.8k
                }
846
0
                else
847
0
                {
848
0
                    ec = ubjson_errc::length_is_negative;
849
0
                    more_ = false;
850
0
                    return length;
851
0
                }
852
14.8k
                break;
853
14.8k
            }
854
14.8k
            case jsoncons::ubjson::ubjson_type::int32_type: 
855
506
            {
856
506
                uint8_t buf[sizeof(int32_t)];
857
506
                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
506
                int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf));
864
506
                if (val >= 0)
865
506
                {
866
506
                    length = static_cast<std::size_t>(val);
867
506
                }
868
0
                else
869
0
                {
870
0
                    ec = ubjson_errc::length_is_negative;
871
0
                    more_ = false;
872
0
                    return length;
873
0
                }
874
506
                break;
875
506
            }
876
506
            case jsoncons::ubjson::ubjson_type::int64_type: 
877
115
            {
878
115
                uint8_t buf[sizeof(int64_t)];
879
115
                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
115
                int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf));
886
115
                if (val >= 0)
887
114
                {
888
114
                    length = (std::size_t)val;
889
114
                    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
114
                }
896
1
                else
897
1
                {
898
1
                    ec = ubjson_errc::length_is_negative;
899
1
                    more_ = false;
900
1
                    return length;
901
1
                }
902
114
                break;
903
115
            }
904
114
            default:
905
46
            {
906
46
                ec = ubjson_errc::length_must_be_integer;
907
46
                more_ = false;
908
46
                return length;
909
115
            }
910
6.34M
        }
911
6.34M
        return length;
912
6.34M
    }
913
914
    void read_key(json_visitor& visitor, std::error_code& ec)
915
6.10M
    {
916
6.10M
        std::size_t length = get_length(ec);
917
6.10M
        if (JSONCONS_UNLIKELY(ec))
918
40
        {
919
40
            ec = ubjson_errc::key_expected;
920
40
            more_ = false;
921
40
            return;
922
40
        }
923
6.10M
        text_buffer_.clear();
924
6.10M
        if (source_reader<Source>::read(source_,text_buffer_,length) != length)
925
45
        {
926
45
            ec = ubjson_errc::unexpected_eof;
927
45
            more_ = false;
928
45
            return;
929
45
        }
930
931
6.10M
        auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
932
6.10M
        if (result.ec != unicode_traits::conv_errc())
933
17
        {
934
17
            ec = ubjson_errc::invalid_utf8_text_string;
935
17
            more_ = false;
936
17
            return;
937
17
        }
938
6.10M
        visitor.key(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), *this, ec);
939
6.10M
        more_ = !cursor_mode_;
940
6.10M
    }
941
};
942
943
} // namespace ubjson
944
} // namespace jsoncons
945
946
#endif