Coverage Report

Created: 2025-12-05 06:20

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