Coverage Report

Created: 2025-06-22 07:08

/src/jsoncons/include/jsoncons/staj_cursor.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2013-2025 Daniel Parker
2
// Distributed under the Boost license, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5
// See https://github.com/danielaparker/jsoncons for latest version
6
7
#ifndef JSONCONS_STAJ_CURSOR_HPP
8
#define JSONCONS_STAJ_CURSOR_HPP
9
10
#include <array> // std::array
11
#include <cstddef>
12
#include <cstdint>
13
#include <functional> // std::function
14
#include <ios>
15
#include <memory> // std::allocator
16
#include <system_error>
17
18
#include <jsoncons/json_parser.hpp>
19
#include <jsoncons/json_type.hpp>
20
#include <jsoncons/json_visitor.hpp>
21
#include <jsoncons/semantic_tag.hpp>
22
#include <jsoncons/ser_context.hpp>
23
#include <jsoncons/sink.hpp>
24
#include <jsoncons/staj_event.hpp>
25
#include <jsoncons/typed_array_view.hpp>
26
#include <jsoncons/utility/bigint.hpp>
27
#include <jsoncons/utility/write_number.hpp>
28
#include <jsoncons/value_converter.hpp>
29
30
namespace jsoncons {
31
32
// basic_staj_visitor
33
34
enum class staj_cursor_state
35
{
36
    typed_array = 1,
37
    multi_dim,
38
    shape
39
};
40
41
template <typename CharT>
42
class basic_staj_visitor : public basic_json_visitor<CharT>
43
{
44
    using super_type = basic_json_visitor<CharT>;
45
public:
46
    using char_type = CharT;
47
    using typename super_type::string_view_type;
48
private:
49
    basic_staj_event<CharT> event_;
50
51
    staj_cursor_state state_;
52
    typed_array_view data_;
53
    jsoncons::span<const size_t> shape_;
54
    std::size_t index_{0};
55
public:
56
    basic_staj_visitor()
57
3.31k
        : event_(staj_event_type::null_value),
58
3.31k
          state_(), data_(), shape_()
59
3.31k
    {
60
3.31k
    }
61
    
62
    ~basic_staj_visitor() = default;
63
64
    void reset()
65
    {
66
        event_ = staj_event_type::null_value;
67
        state_ = {};
68
        data_ = {};
69
        shape_ = {};
70
        index_ = 0;
71
    }
72
73
    const basic_staj_event<CharT>& event() const
74
1.98k
    {
75
1.98k
        return event_;
76
1.98k
    }
77
78
    bool in_available() const
79
    {
80
        return state_ != staj_cursor_state();
81
    }
82
83
    void send_available(std::error_code& ec)
84
    {
85
        switch (state_)
86
        {
87
            case staj_cursor_state::typed_array:
88
                advance_typed_array(ec);
89
                break;
90
            case staj_cursor_state::multi_dim:
91
            case staj_cursor_state::shape:
92
                advance_multi_dim(ec);
93
                break;
94
            default:
95
                break;
96
        }
97
    }
98
99
    bool is_typed_array() const
100
    {
101
        return data_.type() != typed_array_type();
102
    }
103
104
    staj_cursor_state state() const
105
    {
106
        return state_;
107
    }
108
109
    void advance_typed_array(std::error_code& ec)
110
    {
111
        if (is_typed_array())
112
        {
113
            if (index_ < data_.size())
114
            {
115
                switch (data_.type())
116
                {
117
                    case typed_array_type::uint8_value:
118
                    {
119
                        this->uint64_value(data_.data(uint8_array_arg)[index_], semantic_tag::none, ser_context(), ec);
120
                        break;
121
                    }
122
                    case typed_array_type::uint16_value:
123
                    {
124
                        this->uint64_value(data_.data(uint16_array_arg)[index_], semantic_tag::none, ser_context(), ec);
125
                        break;
126
                    }
127
                    case typed_array_type::uint32_value:
128
                    {
129
                        this->uint64_value(data_.data(uint32_array_arg)[index_], semantic_tag::none, ser_context(), ec);
130
                        break;
131
                    }
132
                    case typed_array_type::uint64_value:
133
                    {
134
                        this->uint64_value(data_.data(uint64_array_arg)[index_], semantic_tag::none, ser_context(), ec);
135
                        break;
136
                    }
137
                    case typed_array_type::int8_value:
138
                    {
139
                        this->int64_value(data_.data(int8_array_arg)[index_], semantic_tag::none, ser_context(), ec);
140
                        break;
141
                    }
142
                    case typed_array_type::int16_value:
143
                    {
144
                        this->int64_value(data_.data(int16_array_arg)[index_], semantic_tag::none, ser_context(), ec);
145
                        break;
146
                    }
147
                    case typed_array_type::int32_value:
148
                    {
149
                        this->int64_value(data_.data(int32_array_arg)[index_], semantic_tag::none, ser_context(), ec);
150
                        break;
151
                    }
152
                    case typed_array_type::int64_value:
153
                    {
154
                        this->int64_value(data_.data(int64_array_arg)[index_], semantic_tag::none, ser_context(), ec);
155
                        break;
156
                    }
157
                    case typed_array_type::half_value:
158
                    {
159
                        this->half_value(data_.data(half_array_arg)[index_], semantic_tag::none, ser_context(), ec);
160
                        break;
161
                    }
162
                    case typed_array_type::float_value:
163
                    {
164
                        this->double_value(data_.data(float_array_arg)[index_], semantic_tag::none, ser_context(), ec);
165
                        break;
166
                    }
167
                    case typed_array_type::double_value:
168
                    {
169
                        this->double_value(data_.data(double_array_arg)[index_], semantic_tag::none, ser_context(), ec);
170
                        break;
171
                    }
172
                    default:
173
                        break;
174
                }
175
                ++index_;
176
            }
177
            else
178
            {
179
                this->end_array();
180
                state_ = staj_cursor_state();
181
                data_ = typed_array_view();
182
                index_ = 0;
183
            }
184
        }
185
    }
186
187
    void advance_multi_dim(std::error_code& ec)
188
    {
189
        if (shape_.size() != 0)
190
        {
191
            if (state_ == staj_cursor_state::multi_dim)
192
            {
193
                this->begin_array(shape_.size(), semantic_tag::none, ser_context(), ec);
194
                state_ = staj_cursor_state::shape;
195
            }
196
            else if (index_ < shape_.size())
197
            {
198
                this->uint64_value(shape_[index_], semantic_tag::none, ser_context(), ec);
199
                ++index_;
200
            }
201
            else
202
            {
203
                state_ = staj_cursor_state();
204
                this->end_array(ser_context(), ec);
205
                shape_ = jsoncons::span<const size_t>();
206
                index_ = 0;
207
            }
208
        }
209
    }
210
211
    void dump(basic_json_visitor<CharT>& visitor, const ser_context& context, std::error_code& ec)
212
    {
213
        if (is_typed_array())
214
        {
215
            if (index_ != 0)
216
            {
217
                event().send_json_event(visitor, context, ec);
218
                const std::size_t len = data_.size();
219
                switch (data_.type())
220
                {
221
                    case typed_array_type::uint8_value:
222
                    {
223
                        for (auto i = index_; i < len; ++i) 
224
                        {
225
                            visitor.uint64_value(data_.data(uint8_array_arg)[i]);
226
                        }
227
                        break;
228
                    }
229
                    case typed_array_type::uint16_value:
230
                    {
231
                        for (auto i = index_; i < len; ++i) 
232
                        {
233
                            visitor.uint64_value(data_.data(uint16_array_arg)[i]);
234
                        }
235
                        break;
236
                    }
237
                    case typed_array_type::uint32_value:
238
                    {
239
                        for (auto i = index_; i < len; ++i) 
240
                        {
241
                            visitor.uint64_value(data_.data(uint32_array_arg)[i]);
242
                        }
243
                        break;
244
                    }
245
                    case typed_array_type::uint64_value:
246
                    {
247
                        for (auto i = index_; i < len; ++i) 
248
                        {
249
                            visitor.uint64_value(data_.data(uint64_array_arg)[i]);
250
                        }
251
                        break;
252
                    }
253
                    case typed_array_type::int8_value:
254
                    {
255
                        for (auto i = index_; i < len; ++i) 
256
                        {
257
                            visitor.int64_value(data_.data(int8_array_arg)[i]);
258
                        }
259
                        break;
260
                    }
261
                    case typed_array_type::int16_value:
262
                    {
263
                        for (auto i = index_; i < len; ++i) 
264
                        {
265
                            visitor.int64_value(data_.data(int16_array_arg)[i]);
266
                        }
267
                        break;
268
                    }
269
                    case typed_array_type::int32_value:
270
                    {
271
                        for (auto i = index_; i < len; ++i) 
272
                        {
273
                            visitor.int64_value(data_.data(int32_array_arg)[i]);
274
                        }
275
                        break;
276
                    }
277
                    case typed_array_type::int64_value:
278
                    {
279
                        for (auto i = index_; i < len; ++i) 
280
                        {
281
                            visitor.int64_value(data_.data(int64_array_arg)[i]);
282
                        }
283
                        break;
284
                    }
285
                    case typed_array_type::float_value:
286
                    {
287
                        for (auto i = index_; i < len; ++i) 
288
                        {
289
                            visitor.double_value(data_.data(float_array_arg)[i]);
290
                        }
291
                        break;
292
                    }
293
                    case typed_array_type::double_value:
294
                    {
295
                        for (auto i = index_; i < len; ++i) 
296
                        {
297
                            visitor.double_value(data_.data(double_array_arg)[i]);
298
                        }
299
                        break;
300
                    }
301
                    default:
302
                        break;
303
                }
304
                
305
                state_ = staj_cursor_state();
306
                data_ = typed_array_view();
307
                index_ = 0;
308
            }
309
            else
310
            {
311
                switch (data_.type())
312
                {
313
                    case typed_array_type::uint8_value:
314
                    {
315
                        visitor.typed_array(data_.data(uint8_array_arg));
316
                        break;
317
                    }
318
                    case typed_array_type::uint16_value:
319
                    {
320
                        visitor.typed_array(data_.data(uint16_array_arg));
321
                        break;
322
                    }
323
                    case typed_array_type::uint32_value:
324
                    {
325
                        visitor.typed_array(data_.data(uint32_array_arg));
326
                        break;
327
                    }
328
                    case typed_array_type::uint64_value:
329
                    {
330
                        visitor.typed_array(data_.data(uint64_array_arg));
331
                        break;
332
                    }
333
                    case typed_array_type::int8_value:
334
                    {
335
                        visitor.typed_array(data_.data(int8_array_arg));
336
                        break;
337
                    }
338
                    case typed_array_type::int16_value:
339
                    {
340
                        visitor.typed_array(data_.data(int16_array_arg));
341
                        break;
342
                    }
343
                    case typed_array_type::int32_value:
344
                    {
345
                        visitor.typed_array(data_.data(int32_array_arg));
346
                        break;
347
                    }
348
                    case typed_array_type::int64_value:
349
                    {
350
                        visitor.typed_array(data_.data(int64_array_arg));
351
                        break;
352
                    }
353
                    case typed_array_type::float_value:
354
                    {
355
                        visitor.typed_array(data_.data(float_array_arg));
356
                        break;
357
                    }
358
                    case typed_array_type::double_value:
359
                    {
360
                        visitor.typed_array(data_.data(double_array_arg));
361
                        break;
362
                    }
363
                    default:
364
                        break;
365
                }
366
367
                state_ = staj_cursor_state();
368
                data_ = typed_array_view();
369
            }
370
        }
371
        else
372
        {
373
            event().send_json_event(visitor, context, ec);
374
        }
375
    }
376
377
private:
378
    static constexpr bool accept(const basic_staj_event<CharT>&, const ser_context&) 
379
    {
380
        return true;
381
    }
382
383
    JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(semantic_tag tag, const ser_context&, std::error_code&) override
384
2
    {
385
2
        event_ = basic_staj_event<CharT>(staj_event_type::begin_object, tag);
386
2
        JSONCONS_VISITOR_RETURN;
387
2
    }
388
389
    JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(std::size_t length, semantic_tag tag, const ser_context&, std::error_code&) override
390
0
    {
391
0
        event_ = basic_staj_event<CharT>(staj_event_type::begin_object, length, tag);
392
0
        JSONCONS_VISITOR_RETURN;
393
0
    }
394
395
    JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context&, std::error_code&) override
396
0
    {
397
0
        event_ = basic_staj_event<CharT>(staj_event_type::end_object);
398
0
        JSONCONS_VISITOR_RETURN;
399
0
    }
400
401
    JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(semantic_tag tag, const ser_context&, std::error_code&) override
402
2
    {
403
2
        event_ = basic_staj_event<CharT>(staj_event_type::begin_array, tag);
404
2
        JSONCONS_VISITOR_RETURN;
405
2
    }
406
407
    JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(std::size_t length, semantic_tag tag, const ser_context&, std::error_code&) override
408
0
    {
409
0
        event_ = basic_staj_event<CharT>(staj_event_type::begin_array, length, tag);
410
0
        JSONCONS_VISITOR_RETURN;
411
0
    }
412
413
    JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context&, std::error_code&) override
414
0
    {
415
0
        event_ = basic_staj_event<CharT>(staj_event_type::end_array);
416
0
        JSONCONS_VISITOR_RETURN;
417
0
    }
418
419
    JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
420
0
    {
421
0
        event_ = basic_staj_event<CharT>(name, staj_event_type::key);
422
0
        JSONCONS_VISITOR_RETURN;
423
0
    }
424
425
    JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag tag, const ser_context&, std::error_code&) override
426
2
    {
427
2
        event_ = basic_staj_event<CharT>(staj_event_type::null_value, tag);
428
2
        JSONCONS_VISITOR_RETURN;
429
2
    }
430
431
    JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool value, semantic_tag tag, const ser_context&, std::error_code&) override
432
4
    {
433
4
        event_ = basic_staj_event<CharT>(value, tag);
434
4
        JSONCONS_VISITOR_RETURN;
435
4
    }
436
437
    JSONCONS_VISITOR_RETURN_TYPE visit_string(const string_view_type& s, semantic_tag tag, const ser_context&, std::error_code&) override
438
432
    {
439
432
        event_ = basic_staj_event<CharT>(s, staj_event_type::string_value, tag);
440
432
        JSONCONS_VISITOR_RETURN;
441
432
    }
442
443
    JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& s, 
444
        semantic_tag tag,
445
        const ser_context&,
446
        std::error_code&) override
447
0
    {
448
0
        event_ = basic_staj_event<CharT>(s, staj_event_type::byte_string_value, tag);
449
0
        JSONCONS_VISITOR_RETURN;
450
0
    }
451
452
    JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& s, 
453
        uint64_t ext_tag,
454
        const ser_context&,
455
        std::error_code&) override
456
0
    {
457
0
        event_ = basic_staj_event<CharT>(s, staj_event_type::byte_string_value, ext_tag);
458
0
        JSONCONS_VISITOR_RETURN;
459
0
    }
460
461
    JSONCONS_VISITOR_RETURN_TYPE visit_uint64(uint64_t value, 
462
        semantic_tag tag, 
463
        const ser_context&,
464
        std::error_code&) override
465
294
    {
466
294
        event_ = basic_staj_event<CharT>(value, tag);
467
294
        JSONCONS_VISITOR_RETURN;
468
294
    }
469
470
    JSONCONS_VISITOR_RETURN_TYPE visit_int64(int64_t value, 
471
        semantic_tag tag,
472
        const ser_context&,
473
        std::error_code&) override
474
213
    {
475
213
        event_ = basic_staj_event<CharT>(value, tag);
476
213
        JSONCONS_VISITOR_RETURN;
477
213
    }
478
479
    JSONCONS_VISITOR_RETURN_TYPE visit_half(uint16_t value, 
480
        semantic_tag tag,
481
        const ser_context&,
482
        std::error_code&) override
483
0
    {
484
0
        event_ = basic_staj_event<CharT>(half_arg, value, tag);
485
0
        JSONCONS_VISITOR_RETURN;
486
0
    }
487
488
    JSONCONS_VISITOR_RETURN_TYPE visit_double(double value, 
489
        semantic_tag tag, 
490
        const ser_context&,
491
        std::error_code&) override
492
1.03k
    {
493
1.03k
        event_ = basic_staj_event<CharT>(value, tag);
494
1.03k
        JSONCONS_VISITOR_RETURN;
495
1.03k
    }
496
497
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint8_t>& v, 
498
        semantic_tag tag,
499
        const ser_context& context,
500
        std::error_code& ec) override
501
0
    {
502
0
        state_ = staj_cursor_state::typed_array;
503
0
        data_ = typed_array_view(v.data(), v.size());
504
0
        index_ = 0;
505
0
        this->begin_array(tag, context, ec);
506
0
        JSONCONS_VISITOR_RETURN;
507
0
    }
508
509
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint16_t>& data, 
510
        semantic_tag tag,
511
        const ser_context& context,
512
        std::error_code& ec) override
513
0
    {
514
0
        state_ = staj_cursor_state::typed_array;
515
0
        data_ = typed_array_view(data.data(), data.size());
516
0
        index_ = 0;
517
0
        this->begin_array(tag, context, ec);
518
0
        JSONCONS_VISITOR_RETURN;
519
0
    }
520
521
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint32_t>& data, 
522
        semantic_tag tag,
523
        const ser_context& context,
524
        std::error_code& ec) override
525
0
    {
526
0
        state_ = staj_cursor_state::typed_array;
527
0
        data_ = typed_array_view(data.data(), data.size());
528
0
        index_ = 0;
529
0
        this->begin_array(tag, context, ec);
530
0
        JSONCONS_VISITOR_RETURN;
531
0
    }
532
533
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint64_t>& data, 
534
        semantic_tag tag,
535
        const ser_context& context,
536
        std::error_code& ec) override
537
0
    {
538
0
        state_ = staj_cursor_state::typed_array;
539
0
        data_ = typed_array_view(data.data(), data.size());
540
0
        index_ = 0;
541
0
        this->begin_array(tag, context, ec);
542
0
        JSONCONS_VISITOR_RETURN;
543
0
    }
544
545
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int8_t>& data, 
546
        semantic_tag tag,
547
        const ser_context& context,
548
        std::error_code& ec) override
549
0
    {
550
0
        state_ = staj_cursor_state::typed_array;
551
0
        data_ = typed_array_view(data.data(), data.size());
552
0
        index_ = 0;
553
0
        this->begin_array(tag, context, ec);
554
0
        JSONCONS_VISITOR_RETURN;
555
0
    }
556
557
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int16_t>& data, 
558
        semantic_tag tag,
559
        const ser_context& context,
560
        std::error_code& ec) override
561
0
    {
562
0
        state_ = staj_cursor_state::typed_array;
563
0
        data_ = typed_array_view(data.data(), data.size());
564
0
        index_ = 0;
565
0
        this->begin_array(tag, context, ec);
566
0
        JSONCONS_VISITOR_RETURN;
567
0
    }
568
569
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int32_t>& data, 
570
        semantic_tag tag,
571
        const ser_context& context,
572
        std::error_code& ec) override
573
0
    {
574
0
        state_ = staj_cursor_state::typed_array;
575
0
        data_ = typed_array_view(data.data(), data.size());
576
0
        index_ = 0;
577
0
        this->begin_array(tag, context, ec);
578
0
        JSONCONS_VISITOR_RETURN;
579
0
    }
580
581
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int64_t>& data, 
582
        semantic_tag tag,
583
        const ser_context& context,
584
        std::error_code& ec) override
585
0
    {
586
0
        state_ = staj_cursor_state::typed_array;
587
0
        data_ = typed_array_view(data.data(), data.size());
588
0
        index_ = 0;
589
0
        this->begin_array(tag, context, ec);
590
0
        JSONCONS_VISITOR_RETURN;
591
0
    }
592
593
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(half_arg_t, const jsoncons::span<const uint16_t>& data, 
594
        semantic_tag tag,
595
        const ser_context& context,
596
        std::error_code& ec) override
597
0
    {
598
0
        state_ = staj_cursor_state::typed_array;
599
0
        data_ = typed_array_view(data.data(), data.size());
600
0
        index_ = 0;
601
0
        this->begin_array(tag, context, ec);
602
0
        JSONCONS_VISITOR_RETURN;
603
0
    }
604
605
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const float>& data, 
606
        semantic_tag tag,
607
        const ser_context& context,
608
        std::error_code& ec) override
609
0
    {
610
0
        state_ = staj_cursor_state::typed_array;
611
0
        data_ = typed_array_view(data.data(), data.size());
612
0
        index_ = 0;
613
0
        this->begin_array(tag, context, ec);
614
0
        JSONCONS_VISITOR_RETURN;
615
0
    }
616
617
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const double>& data, 
618
        semantic_tag tag,
619
        const ser_context& context,
620
        std::error_code& ec) override
621
0
    {
622
0
        state_ = staj_cursor_state::typed_array;
623
0
        data_ = typed_array_view(data.data(), data.size());
624
0
        index_ = 0;
625
0
        this->begin_array(tag, context, ec);
626
0
        JSONCONS_VISITOR_RETURN;
627
0
    }
628
/*
629
    JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const float128_type>&, 
630
        semantic_tag,
631
        const ser_context&,
632
        std::error_code&) override
633
    {
634
        JSONCONS_VISITOR_RETURN;
635
    }
636
*/
637
    JSONCONS_VISITOR_RETURN_TYPE visit_begin_multi_dim(const jsoncons::span<const size_t>& shape,
638
        semantic_tag tag,
639
        const ser_context& context, 
640
        std::error_code& ec) override
641
0
    {
642
0
        state_ = staj_cursor_state::multi_dim;
643
0
        shape_ = shape;
644
0
        this->begin_array(2, tag, context, ec);
645
0
        JSONCONS_VISITOR_RETURN;
646
0
    }
647
648
    JSONCONS_VISITOR_RETURN_TYPE visit_end_multi_dim(const ser_context& context,
649
        std::error_code& ec) override
650
0
    {
651
0
        this->end_array(context, ec);
652
0
        JSONCONS_VISITOR_RETURN;
653
0
    }
654
655
    void visit_flush() override
656
1.97k
    {
657
1.97k
    }
658
};
659
660
661
// basic_staj_cursor
662
663
template <typename CharT>
664
class basic_staj_cursor
665
{
666
public:
667
3.31k
    virtual ~basic_staj_cursor() = default;
668
669
    virtual void array_expected(std::error_code& ec)
670
0
    {
671
0
        if (!(current().event_type() == staj_event_type::begin_array || current().event_type() == staj_event_type::byte_string_value))
672
0
        {
673
0
            ec = conv_errc::not_vector;
674
0
        }
675
0
    }
676
677
    virtual bool done() const = 0;
678
679
    virtual const basic_staj_event<CharT>& current() const = 0;
680
681
    virtual void read_to(basic_json_visitor<CharT>& visitor) = 0;
682
683
    virtual void read_to(basic_json_visitor<CharT>& visitor,
684
                         std::error_code& ec) = 0;
685
686
    virtual void next() = 0;
687
688
    virtual void next(std::error_code& ec) = 0;
689
690
    virtual const ser_context& context() const = 0;
691
    
692
    virtual std::size_t line() const = 0;
693
694
    virtual std::size_t column() const = 0;
695
    
696
};
697
698
template <typename CharT>
699
class basic_staj_filter_view : basic_staj_cursor<CharT>
700
{
701
    basic_staj_cursor<CharT>* cursor_;
702
    std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred_;
703
public:
704
    basic_staj_filter_view(basic_staj_cursor<CharT>& cursor, 
705
                     std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred)
706
        : cursor_(std::addressof(cursor)), pred_(pred)
707
    {
708
        while (!done() && !pred_(current(),context()))
709
        {
710
            cursor_->next();
711
        }
712
    }
713
714
    bool done() const override
715
    {
716
        return cursor_->done();
717
    }
718
719
    const basic_staj_event<CharT>& current() const override
720
    {
721
        return cursor_->current();
722
    }
723
724
    void read_to(basic_json_visitor<CharT>& visitor) override
725
    {
726
        cursor_->read_to(visitor);
727
    }
728
729
    void read_to(basic_json_visitor<CharT>& visitor,
730
                 std::error_code& ec) override
731
    {
732
        cursor_->read_to(visitor, ec);
733
    }
734
735
    void next() override
736
    {
737
        cursor_->next();
738
        while (!done() && !pred_(current(),context()))
739
        {
740
            cursor_->next();
741
        }
742
    }
743
744
    void next(std::error_code& ec) override
745
    {
746
        cursor_->next(ec);
747
        while (!done() && !pred_(current(),context()) && !ec)
748
        {
749
            cursor_->next(ec);
750
        }
751
    }
752
753
    const ser_context& context() const override
754
    {
755
        return cursor_->context();
756
    }
757
758
    std::size_t line() const override
759
    {
760
        return cursor_->line();
761
    }
762
763
    std::size_t column() const override
764
    {
765
        return cursor_->column();
766
    }
767
768
    friend
769
    basic_staj_filter_view<CharT> operator|(basic_staj_filter_view& cursor, 
770
                                      std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred)
771
    {
772
        return basic_staj_filter_view<CharT>(cursor, pred);
773
    }
774
};
775
template <typename Json>
776
Json to_basic_json_single(basic_staj_cursor<typename Json::char_type>& cursor, 
777
    std::error_code& ec)
778
{
779
    switch (cursor.current().event_type())
780
    {
781
        case staj_event_type::string_value:
782
            return Json{cursor.current().template get<jsoncons::basic_string_view<typename Json::char_type>>(ec), cursor.current().tag()};
783
        case staj_event_type::byte_string_value:
784
            return Json{byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag()};
785
        case staj_event_type::null_value:
786
            return Json{null_arg};
787
        case staj_event_type::bool_value:
788
            return Json{cursor.current().template get<bool>(ec), cursor.current().tag()};
789
        case staj_event_type::int64_value:
790
            return Json{cursor.current().template get<std::int64_t>(ec), cursor.current().tag()};
791
        case staj_event_type::uint64_value:
792
            return Json{cursor.current().template get<std::uint64_t>(ec), cursor.current().tag()};
793
        case staj_event_type::half_value:
794
            return Json{half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag()};
795
        case staj_event_type::double_value:
796
            return Json{cursor.current().template get<double>(ec), cursor.current().tag()};
797
        default:
798
            ec = conv_errc::conversion_failed; 
799
            return Json{};
800
    }
801
}
802
803
template <typename Json>
804
Json to_basic_json_container(basic_staj_cursor<typename Json::char_type>& cursor,
805
    std::error_code& ec)
806
{
807
    auto cont = cursor.current().event_type() == staj_event_type::begin_object ? 
808
        Json(json_object_arg) : Json(json_array_arg);
809
    std::vector<Json*> stack;
810
    stack.push_back(std::addressof(cont));
811
    std::basic_string<typename Json::char_type> key;
812
    if (cursor.current().event_type() == staj_event_type::begin_object)
813
    {
814
        goto begin_object;
815
    }
816
    goto begin_array;
817
    
818
begin_object:    
819
    cursor.next(ec);
820
    if (JSONCONS_UNLIKELY(ec))
821
    {
822
        return Json{};
823
    }
824
    while (!cursor.done() && !stack.empty())
825
    {
826
        switch (cursor.current().event_type())
827
        {
828
            case staj_event_type::begin_object:
829
            {
830
                auto result = stack.back()->try_emplace(key, json_object_arg);
831
                stack.push_back(std::addressof(result.first->value()));
832
                goto begin_object;
833
            }
834
            case staj_event_type::begin_array:
835
            {
836
                auto result = stack.back()->try_emplace(key, json_array_arg);
837
                stack.push_back(std::addressof(result.first->value()));
838
                goto begin_array;
839
            }
840
            case staj_event_type::key:
841
                key = cursor.current().template get<std::basic_string<typename Json::char_type>>(ec);
842
                break;
843
            case staj_event_type::string_value:
844
                stack.back()->try_emplace(key, cursor.current().template get<jsoncons::basic_string_view<typename Json::char_type>>(ec), cursor.current().tag());
845
                break;
846
            case staj_event_type::byte_string_value:
847
                stack.back()->try_emplace(key, byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag());
848
                break;
849
            case staj_event_type::null_value:
850
                stack.back()->try_emplace(key, null_arg);
851
                break;
852
            case staj_event_type::bool_value:
853
                stack.back()->try_emplace(key, cursor.current().template get<bool>(ec), cursor.current().tag());
854
                break;
855
            case staj_event_type::int64_value:
856
                stack.back()->try_emplace(key, cursor.current().template get<std::int64_t>(ec), cursor.current().tag());
857
                break;
858
            case staj_event_type::uint64_value:
859
                stack.back()->try_emplace(key, cursor.current().template get<std::uint64_t>(ec), cursor.current().tag());
860
                break;
861
            case staj_event_type::half_value:
862
                stack.back()->try_emplace(key, half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag());
863
                break;
864
            case staj_event_type::double_value:
865
                stack.back()->try_emplace(key, cursor.current().template get<double>(ec), cursor.current().tag());
866
                break;
867
            case staj_event_type::end_object:
868
                stack.pop_back();
869
                if (stack.empty())
870
                {
871
                    return cont;
872
                }
873
                if (stack.back()->type() == json_type::object_value)
874
                {
875
                    goto begin_object;
876
                }
877
                goto begin_array;
878
                break;
879
            default:
880
                ec = conv_errc::conversion_failed; 
881
                return Json{};
882
        }
883
        if (JSONCONS_UNLIKELY(ec))
884
        {
885
            return Json{};
886
        }
887
        cursor.next(ec);
888
        if (JSONCONS_UNLIKELY(ec))
889
        {
890
            return Json{};
891
        }
892
    }
893
    return cont;
894
895
begin_array:    
896
    cursor.next(ec);
897
    if (JSONCONS_UNLIKELY(ec))
898
    {
899
        return Json{};
900
    }
901
    while (!cursor.done() && !stack.empty())
902
    {
903
        switch (cursor.current().event_type())
904
        {
905
            case staj_event_type::begin_object:
906
            {
907
                auto& result = stack.back()->emplace_back(json_object_arg);
908
                stack.push_back(std::addressof(result));
909
                goto begin_object;
910
            }
911
            case staj_event_type::begin_array:
912
            {
913
                auto& result = stack.back()->emplace_back(json_array_arg);
914
                stack.push_back(std::addressof(result));
915
                goto begin_array;
916
            }
917
            case staj_event_type::string_value:
918
                stack.back()->emplace_back(cursor.current().template get<jsoncons::basic_string_view<typename Json::char_type>>(ec), cursor.current().tag());
919
                break;
920
            case staj_event_type::byte_string_value:
921
                stack.back()->emplace_back(byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag());
922
                break;
923
            case staj_event_type::null_value:
924
                stack.back()->emplace_back(null_arg);
925
                break;
926
            case staj_event_type::bool_value:
927
                stack.back()->emplace_back(cursor.current().template get<bool>(ec), cursor.current().tag());
928
                break;
929
            case staj_event_type::int64_value:
930
                stack.back()->emplace_back(cursor.current().template get<std::int64_t>(ec), cursor.current().tag());
931
                break;
932
            case staj_event_type::uint64_value:
933
                stack.back()->emplace_back(cursor.current().template get<std::uint64_t>(ec), cursor.current().tag());
934
                break;
935
            case staj_event_type::half_value:
936
                stack.back()->emplace_back(half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag());
937
                break;
938
            case staj_event_type::double_value:
939
                stack.back()->emplace_back(cursor.current().template get<double>(ec), cursor.current().tag());
940
                break;
941
            case staj_event_type::end_array:
942
                stack.pop_back();
943
                if (stack.empty())
944
                {
945
                    return cont;
946
                }
947
                if (stack.back()->type() == json_type::object_value)
948
                {
949
                    goto begin_object;
950
                }
951
                goto begin_array;
952
                break;
953
            default:
954
                ec = conv_errc::conversion_failed; 
955
                return Json{};
956
        }
957
        if (JSONCONS_UNLIKELY(ec))
958
        {
959
            return Json{};
960
        }
961
        cursor.next(ec);
962
        if (JSONCONS_UNLIKELY(ec))
963
        {
964
            return Json{};
965
        }
966
    }
967
    
968
    JSONCONS_UNREACHABLE();
969
}
970
971
template <typename Json>
972
Json try_to_json(basic_staj_cursor<typename Json::char_type>& cursor, 
973
    std::error_code& ec)
974
{
975
    if (JSONCONS_UNLIKELY(is_end_container(cursor.current().event_type())))
976
    {
977
        ec = conv_errc::conversion_failed; 
978
        return Json{};
979
    }
980
    if (!is_begin_container(cursor.current().event_type()))
981
    {
982
        return to_basic_json_single<Json>(cursor, ec);
983
    }
984
    return to_basic_json_container<Json>(cursor, ec);
985
}
986
987
using staj_event = basic_staj_event<char>;
988
using wstaj_event = basic_staj_event<wchar_t>;
989
990
using staj_cursor = basic_staj_cursor<char>;
991
using wstaj_cursor = basic_staj_cursor<wchar_t>;
992
993
using staj_filter_view = basic_staj_filter_view<char>;
994
using wstaj_filter_view = basic_staj_filter_view<wchar_t>;
995
996
} // namespace jsoncons
997
998
#endif // JSONCONS_STAJ_CURSOR_HPP
999