Coverage Report

Created: 2025-07-18 06:42

/src/jsoncons/include/jsoncons/staj_event.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_EVENT_HPP
8
#define JSONCONS_STAJ_EVENT_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
#include <type_traits> // std::enable_if
18
19
#include <jsoncons/config/compiler_support.hpp>
20
#include <jsoncons/conv_error.hpp>
21
#include <jsoncons/utility/write_number.hpp>
22
#include <jsoncons/item_event_visitor.hpp>
23
#include <jsoncons/json_exception.hpp>
24
#include <jsoncons/json_parser.hpp>
25
#include <jsoncons/json_type.hpp>
26
#include <jsoncons/json_visitor.hpp>
27
#include <jsoncons/semantic_tag.hpp>
28
#include <jsoncons/ser_context.hpp>
29
#include <jsoncons/sink.hpp>
30
#include <jsoncons/typed_array_view.hpp>
31
#include <jsoncons/utility/bigint.hpp>
32
#include <jsoncons/utility/more_type_traits.hpp>
33
34
#include <jsoncons/value_converter.hpp>
35
36
namespace jsoncons {
37
38
enum class staj_event_type : uint8_t
39
{
40
    key = 0,                // 0000
41
    string_value = 1,       // 0001
42
    byte_string_value = 2,  // 0010
43
    null_value = 3,         // 0011
44
    bool_value = 4,         // 0100
45
    int64_value = 5,        // 0101
46
    uint64_value = 6,       // 0110
47
    half_value = 8,         // 1000
48
    double_value = 9,       // 1001
49
    begin_object = 13,      // 1101
50
    end_object = 7,         // 0111    
51
    begin_array = 14,       // 1110
52
    end_array = 15          // 1111
53
};
54
55
inline bool is_begin_container(staj_event_type event_type) noexcept
56
0
{
57
0
    static const uint8_t mask{ uint8_t(staj_event_type::begin_object) & uint8_t(staj_event_type::begin_array) };
58
0
    return (uint8_t(event_type) & mask) == mask;
59
0
}
60
61
inline bool is_end_container(staj_event_type event_type) noexcept
62
0
{
63
0
    static const uint8_t mask{ uint8_t(staj_event_type::end_object) & uint8_t(staj_event_type::end_array) };
64
0
    return (uint8_t(event_type) & mask) == mask;
65
0
}
66
67
template <typename CharT>
68
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, staj_event_type tag)
69
{
70
    static constexpr const CharT* begin_array_name = JSONCONS_CSTRING_CONSTANT(CharT, "begin_array");
71
    static constexpr const CharT* end_array_name = JSONCONS_CSTRING_CONSTANT(CharT, "end_array");
72
    static constexpr const CharT* begin_object_name = JSONCONS_CSTRING_CONSTANT(CharT, "begin_object");
73
    static constexpr const CharT* end_object_name = JSONCONS_CSTRING_CONSTANT(CharT, "end_object");
74
    static constexpr const CharT* key_name = JSONCONS_CSTRING_CONSTANT(CharT, "key");
75
    static constexpr const CharT* string_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "string_value");
76
    static constexpr const CharT* byte_string_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "byte_string_value");
77
    static constexpr const CharT* null_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "null_value");
78
    static constexpr const CharT* bool_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "bool_value");
79
    static constexpr const CharT* uint64_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "uint64_value");
80
    static constexpr const CharT* int64_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "int64_value");
81
    static constexpr const CharT* half_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "half_value");
82
    static constexpr const CharT* double_value_name = JSONCONS_CSTRING_CONSTANT(CharT, "double_value");
83
84
    switch (tag)
85
    {
86
        case staj_event_type::begin_array:
87
        {
88
            os << begin_array_name;
89
            break;
90
        }
91
        case staj_event_type::end_array:
92
        {
93
            os << end_array_name;
94
            break;
95
        }
96
        case staj_event_type::begin_object:
97
        {
98
            os << begin_object_name;
99
            break;
100
        }
101
        case staj_event_type::end_object:
102
        {
103
            os << end_object_name;
104
            break;
105
        }
106
        case staj_event_type::key:
107
        {
108
            os << key_name;
109
            break;
110
        }
111
        case staj_event_type::string_value:
112
        {
113
            os << string_value_name;
114
            break;
115
        }
116
        case staj_event_type::byte_string_value:
117
        {
118
            os << byte_string_value_name;
119
            break;
120
        }
121
        case staj_event_type::null_value:
122
        {
123
            os << null_value_name;
124
            break;
125
        }
126
        case staj_event_type::bool_value:
127
        {
128
            os << bool_value_name;
129
            break;
130
        }
131
        case staj_event_type::int64_value:
132
        {
133
            os << int64_value_name;
134
            break;
135
        }
136
        case staj_event_type::uint64_value:
137
        {
138
            os << uint64_value_name;
139
            break;
140
        }
141
        case staj_event_type::half_value:
142
        {
143
            os << half_value_name;
144
            break;
145
        }
146
        case staj_event_type::double_value:
147
        {
148
            os << double_value_name;
149
            break;
150
        }
151
    }
152
    return os;
153
}
154
155
template <typename CharT>
156
class basic_staj_event
157
{
158
    staj_event_type event_type_;
159
    semantic_tag tag_;
160
    uint64_t ext_tag_{0};
161
    union
162
    {
163
        bool bool_value_;
164
        int64_t int64_value_;
165
        uint64_t uint64_value_;
166
        uint16_t half_value_;
167
        double double_value_;
168
        const CharT* string_data_;
169
        const uint8_t* byte_string_data_;
170
    } value_;
171
    std::size_t length_{0};
172
public:
173
    using string_view_type = jsoncons::basic_string_view<CharT>;
174
175
    basic_staj_event(staj_event_type event_type, semantic_tag tag = semantic_tag::none)
176
        : event_type_(event_type), tag_(tag), value_()
177
    {
178
    }
179
180
    basic_staj_event(staj_event_type event_type, std::size_t length, semantic_tag tag = semantic_tag::none)
181
        : event_type_(event_type), tag_(tag), value_(), length_(length)
182
    {
183
    }
184
185
    basic_staj_event(null_type, semantic_tag tag)
186
        : event_type_(staj_event_type::null_value), tag_(tag), value_()
187
    {
188
    }
189
190
    basic_staj_event(bool value, semantic_tag tag)
191
        : event_type_(staj_event_type::bool_value), tag_(tag)
192
    {
193
        value_.bool_value_ = value;
194
    }
195
196
    basic_staj_event(int64_t value, semantic_tag tag)
197
        : event_type_(staj_event_type::int64_value), tag_(tag)
198
    {
199
        value_.int64_value_ = value;
200
    }
201
202
    basic_staj_event(uint64_t value, semantic_tag tag)
203
        : event_type_(staj_event_type::uint64_value), tag_(tag)
204
    {
205
        value_.uint64_value_ = value;
206
    }
207
208
    basic_staj_event(half_arg_t, uint16_t value, semantic_tag tag)
209
        : event_type_(staj_event_type::half_value), tag_(tag)
210
    {
211
        value_.half_value_ = value;
212
    }
213
214
    basic_staj_event(double value, semantic_tag tag)
215
        : event_type_(staj_event_type::double_value), tag_(tag)
216
    {
217
        value_.double_value_ = value;
218
    }
219
220
    basic_staj_event(const string_view_type& s,
221
        staj_event_type event_type,
222
        semantic_tag tag = semantic_tag::none)
223
        : event_type_(event_type), tag_(tag), length_(s.length())
224
    {
225
        value_.string_data_ = s.data();
226
    }
227
228
    basic_staj_event(const byte_string_view& s,
229
        staj_event_type event_type,
230
        semantic_tag tag = semantic_tag::none)
231
        : event_type_(event_type), tag_(tag), length_(s.size())
232
    {
233
        value_.byte_string_data_ = s.data();
234
    }
235
236
    basic_staj_event(const byte_string_view& s,
237
        staj_event_type event_type,
238
        uint64_t ext_tag)
239
        : event_type_(event_type), tag_(semantic_tag::ext), ext_tag_(ext_tag), length_(s.size())
240
    {
241
        value_.byte_string_data_ = s.data();
242
    }
243
    
244
    ~basic_staj_event() = default;
245
246
    std::size_t size() const
247
    {
248
        return length_;
249
    }
250
251
    template <typename T>
252
    T get() const
253
    {
254
        std::error_code ec;
255
        T val = get<T>(ec);
256
        if (JSONCONS_UNLIKELY(ec))
257
        {
258
            JSONCONS_THROW(ser_error(ec));
259
        }
260
        return val;
261
    }
262
263
    template <typename T>
264
    T get(std::error_code& ec) const
265
    {
266
        return get_<T>(std::allocator<char>{}, ec);
267
    }
268
269
    template <typename T,typename Allocator,typename CharT_ = CharT>
270
    typename std::enable_if<ext_traits::is_string<T>::value && std::is_same<typename T::value_type, CharT_>::value, T>::type
271
    get_(Allocator,std::error_code& ec) const
272
    {
273
        switch (event_type_)
274
        {
275
            case staj_event_type::key:
276
            case staj_event_type::string_value:
277
            {
278
                value_converter<jsoncons::basic_string_view<CharT>,T> converter;
279
                return converter.convert(jsoncons::basic_string_view<CharT>(value_.string_data_, length_), tag(), ec);
280
            }
281
            case staj_event_type::byte_string_value:
282
            {
283
                value_converter<jsoncons::byte_string_view,T> converter;
284
                return converter.convert(byte_string_view(value_.byte_string_data_,length_),tag(),ec);
285
            }
286
            case staj_event_type::uint64_value:
287
            {
288
                value_converter<uint64_t,T> converter;
289
                return converter.convert(value_.uint64_value_, tag(), ec);
290
            }
291
            case staj_event_type::int64_value:
292
            {
293
                value_converter<int64_t,T> converter;
294
                return converter.convert(value_.int64_value_, tag(), ec);
295
            }
296
            case staj_event_type::half_value:
297
            {
298
                value_converter<half_arg_t,T> converter;
299
                return converter.convert(value_.half_value_, tag(), ec);
300
            }
301
            case staj_event_type::double_value:
302
            {
303
                value_converter<double,T> converter;
304
                return converter.convert(value_.double_value_, tag(), ec);
305
            }
306
            case staj_event_type::bool_value:
307
            {
308
                value_converter<bool,T> converter;
309
                return converter.convert(value_.bool_value_,tag(),ec);
310
            }
311
            case staj_event_type::null_value:
312
            {
313
                value_converter<null_type,T> converter;
314
                return converter.convert(tag(), ec);
315
            }
316
            default:
317
            {
318
                ec = conv_errc::not_string;
319
                return T{};
320
            }
321
        }
322
    }
323
324
    template <typename T,typename Allocator,typename CharT_ = CharT>
325
    typename std::enable_if<ext_traits::is_string_view<T>::value && std::is_same<typename T::value_type, CharT_>::value, T>::type
326
        get_(Allocator, std::error_code& ec) const
327
    {
328
        T s;
329
        switch (event_type_)
330
        {
331
        case staj_event_type::key:
332
        case staj_event_type::string_value:
333
            s = T(value_.string_data_, length_);
334
            break;
335
        default:
336
            ec = conv_errc::not_string_view;
337
            break;        
338
        }
339
        return s;
340
    }
341
342
    template <typename T,typename Allocator>
343
    typename std::enable_if<std::is_same<T, byte_string_view>::value, T>::type
344
        get_(Allocator, std::error_code& ec) const
345
    {
346
        T s;
347
        switch (event_type_)
348
        {
349
            case staj_event_type::byte_string_value:
350
                s = T(value_.byte_string_data_, length_);
351
                break;
352
            default:
353
                ec = conv_errc::not_byte_string_view;
354
                break;
355
        }
356
        return s;
357
    }
358
359
    template <typename T,typename Allocator>
360
    typename std::enable_if<ext_traits::is_array_like<T>::value &&
361
                            std::is_same<typename T::value_type,uint8_t>::value,T>::type
362
    get_(Allocator, std::error_code& ec) const
363
    {
364
        switch (event_type_)
365
        {
366
        case staj_event_type::byte_string_value:
367
            {
368
                value_converter<byte_string_view,T> converter;
369
                return converter.convert(byte_string_view(value_.byte_string_data_, length_), tag(), ec);
370
            }
371
        case staj_event_type::string_value:
372
            {
373
                value_converter<jsoncons::basic_string_view<CharT>,T> converter;
374
                return converter.convert(jsoncons::basic_string_view<CharT>(value_.string_data_, length_), tag(), ec);
375
            }
376
            default:
377
                ec = conv_errc::not_byte_string;
378
                return T{};
379
        }
380
    }
381
382
    template <typename IntegerType,typename Allocator>
383
    typename std::enable_if<ext_traits::is_integer<IntegerType>::value, IntegerType>::type
384
    get_(Allocator, std::error_code& ec) const
385
    {
386
        switch (event_type_)
387
        {
388
            case staj_event_type::string_value:
389
            {
390
                IntegerType val;
391
                auto result = jsoncons::utility::to_integer(value_.string_data_, length_, val);
392
                if (!result)
393
                {
394
                    ec = conv_errc::not_integer;
395
                    return IntegerType();
396
                }
397
                return val;
398
            }
399
            case staj_event_type::half_value:
400
                return static_cast<IntegerType>(value_.half_value_);
401
            case staj_event_type::double_value:
402
                return static_cast<IntegerType>(value_.double_value_);
403
            case staj_event_type::int64_value:
404
                return static_cast<IntegerType>(value_.int64_value_);
405
            case staj_event_type::uint64_value:
406
                return static_cast<IntegerType>(value_.uint64_value_);
407
            case staj_event_type::bool_value:
408
                return static_cast<IntegerType>(value_.bool_value_ ? 1 : 0);
409
            default:
410
                ec = conv_errc::not_integer;
411
                return IntegerType();
412
        }
413
    }
414
415
    template <typename T,typename Allocator>
416
    typename std::enable_if<std::is_floating_point<T>::value, T>::type
417
        get_(Allocator, std::error_code& ec) const
418
    {
419
        return static_cast<T>(as_double(ec));
420
    }
421
422
    template <typename T,typename Allocator>
423
    typename std::enable_if<ext_traits::is_bool<T>::value, T>::type
424
        get_(Allocator, std::error_code& ec) const
425
    {
426
        return as_bool(ec);
427
    }
428
429
    staj_event_type event_type() const noexcept { return event_type_; }
430
431
    semantic_tag tag() const noexcept { return tag_; }
432
433
    uint64_t ext_tag() const noexcept { return ext_tag_; }
434
435
private:
436
437
    double as_double(std::error_code& ec) const
438
    {
439
        switch (event_type_)
440
        {
441
            case staj_event_type::key:
442
            case staj_event_type::string_value:
443
            {
444
                double val{0};
445
                jsoncons::utility::decstr_to_double(value_.string_data_, length_, val);
446
                return val;
447
            }
448
            case staj_event_type::double_value:
449
                return value_.double_value_;
450
            case staj_event_type::int64_value:
451
                return static_cast<double>(value_.int64_value_);
452
            case staj_event_type::uint64_value:
453
                return static_cast<double>(value_.uint64_value_);
454
            case staj_event_type::half_value:
455
            {
456
                double x = binary::decode_half(value_.half_value_);
457
                return static_cast<double>(x);
458
            }
459
            default:
460
                ec = conv_errc::not_double;
461
                return double();
462
        }
463
    }
464
465
    bool as_bool(std::error_code& ec) const
466
    {
467
        switch (event_type_)
468
        {
469
            case staj_event_type::bool_value:
470
                return value_.bool_value_;
471
            case staj_event_type::double_value:
472
                return value_.double_value_ != 0.0;
473
            case staj_event_type::int64_value:
474
                return value_.int64_value_ != 0;
475
            case staj_event_type::uint64_value:
476
                return value_.uint64_value_ != 0;
477
            default:
478
                ec = conv_errc::not_bool;
479
                return bool();
480
        }
481
    }
482
public:
483
    void send_json_event(basic_json_visitor<CharT>& visitor,
484
        const ser_context& context,
485
        std::error_code& ec) const
486
    {
487
        switch (event_type())
488
        {
489
            case staj_event_type::begin_array:
490
                visitor.begin_array(tag(), context);
491
                break;
492
            case staj_event_type::end_array:
493
                visitor.end_array(context);
494
                break;
495
            case staj_event_type::begin_object:
496
                visitor.begin_object(tag(), context, ec);
497
                break;
498
            case staj_event_type::end_object:
499
                visitor.end_object(context, ec);
500
                break;
501
            case staj_event_type::key:
502
                visitor.key(string_view_type(value_.string_data_,length_), context);
503
                break;
504
            case staj_event_type::string_value:
505
                visitor.string_value(string_view_type(value_.string_data_,length_), tag(), context);
506
                break;
507
            case staj_event_type::byte_string_value:
508
                visitor.byte_string_value(byte_string_view(value_.byte_string_data_,length_), tag(), context);
509
                break;
510
            case staj_event_type::null_value:
511
                visitor.null_value(tag(), context);
512
                break;
513
            case staj_event_type::bool_value:
514
                visitor.bool_value(value_.bool_value_, tag(), context);
515
                break;
516
            case staj_event_type::int64_value:
517
                visitor.int64_value(value_.int64_value_, tag(), context);
518
                break;
519
            case staj_event_type::uint64_value:
520
                visitor.uint64_value(value_.uint64_value_, tag(), context);
521
                break;
522
            case staj_event_type::half_value:
523
                visitor.half_value(value_.half_value_, tag(), context);
524
                break;
525
            case staj_event_type::double_value:
526
                visitor.double_value(value_.double_value_, tag(), context);
527
                break;
528
            default:
529
                break;
530
        }
531
    }
532
    
533
    void send_value_event(basic_item_event_visitor<CharT>& visitor,
534
        const ser_context& context,
535
        std::error_code& ec) const
536
    {
537
        switch (event_type())
538
        {
539
            case staj_event_type::key:
540
                visitor.string_value(string_view_type(value_.string_data_,length_), tag(), context);
541
                break;
542
            case staj_event_type::begin_array:
543
                visitor.begin_array(tag(), context);
544
                break;
545
            case staj_event_type::end_array:
546
                visitor.end_array(context);
547
                break;
548
            case staj_event_type::begin_object:
549
                visitor.begin_object(tag(), context, ec);
550
                break;
551
            case staj_event_type::end_object:
552
                visitor.end_object(context, ec);
553
                break;
554
            case staj_event_type::string_value:
555
                visitor.string_value(string_view_type(value_.string_data_,length_), tag(), context);
556
                break;
557
            case staj_event_type::byte_string_value:
558
                visitor.byte_string_value(byte_string_view(value_.byte_string_data_,length_), tag(), context);
559
                break;
560
            case staj_event_type::null_value:
561
                visitor.null_value(tag(), context);
562
                break;
563
            case staj_event_type::bool_value:
564
                visitor.bool_value(value_.bool_value_, tag(), context);
565
                break;
566
            case staj_event_type::int64_value:
567
                visitor.int64_value(value_.int64_value_, tag(), context);
568
                break;
569
            case staj_event_type::uint64_value:
570
                visitor.uint64_value(value_.uint64_value_, tag(), context);
571
                break;
572
            case staj_event_type::half_value:
573
                visitor.half_value(value_.half_value_, tag(), context);
574
                break;
575
            case staj_event_type::double_value:
576
                visitor.double_value(value_.double_value_, tag(), context);
577
                break;
578
            default:
579
                break;
580
        }
581
    }
582
583
};
584
585
} // namespace jsoncons
586
587
#endif // JSONCONS_STAJ_EVENT_HPP
588