Coverage Report

Created: 2025-11-11 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons/json_reader.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_JSON_READER_HPP
8
#define JSONCONS_JSON_READER_HPP
9
10
#include <cstddef>
11
#include <functional>
12
#include <ios>
13
#include <memory> // std::allocator
14
#include <string>
15
#include <system_error>
16
#include <utility> // std::move
17
18
#include <jsoncons/config/compiler_support.hpp>
19
#include <jsoncons/json_exception.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/source.hpp>
26
#include <jsoncons/source_adaptor.hpp>
27
#include <jsoncons/utility/unicode_traits.hpp>
28
29
namespace jsoncons {
30
31
    // utf8_other_json_input_adapter
32
33
    template <typename CharT>
34
    class json_utf8_to_other_visitor_adaptor : public json_visitor
35
    {
36
    public:
37
        using json_visitor::string_view_type;
38
    private:
39
        basic_default_json_visitor<CharT> default_visitor_;
40
        basic_json_visitor<CharT>& other_visitor_;
41
        //std::function<bool(json_errc,const ser_context&)> err_handler_;
42
43
        // noncopyable and nonmoveable
44
        json_utf8_to_other_visitor_adaptor(const json_utf8_to_other_visitor_adaptor<CharT>&) = delete;
45
        json_utf8_to_other_visitor_adaptor<CharT>& operator=(const json_utf8_to_other_visitor_adaptor<CharT>&) = delete;
46
47
    public:
48
        json_utf8_to_other_visitor_adaptor()
49
            : other_visitor_(default_visitor_)
50
        {
51
        }
52
53
        json_utf8_to_other_visitor_adaptor(basic_json_visitor<CharT>& other_visitor/*,
54
                                              std::function<bool(json_errc,const ser_context&)> err_handler*/)
55
            : other_visitor_(other_visitor)/*,
56
              err_handler_(err_handler)*/
57
        {
58
        }
59
60
    private:
61
62
        void visit_flush() override
63
        {
64
            other_visitor_.flush();
65
        }
66
67
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(semantic_tag tag, const ser_context& context, std::error_code& ec) override
68
        {
69
            other_visitor_.begin_object(tag, context, ec);
70
            JSONCONS_VISITOR_RETURN;
71
        }
72
73
        JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context& context, std::error_code& ec) override
74
        {
75
            other_visitor_.end_object(context, ec);
76
            JSONCONS_VISITOR_RETURN;
77
        }
78
79
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(semantic_tag tag, const ser_context& context, std::error_code& ec) override
80
        {
81
            other_visitor_.begin_array(tag, context, ec);
82
            JSONCONS_VISITOR_RETURN;
83
        }
84
85
        JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context& context, std::error_code& ec) override
86
        {
87
            other_visitor_.end_array(context, ec);
88
            JSONCONS_VISITOR_RETURN;
89
        }
90
91
        JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context& context, std::error_code& ec) override
92
        {
93
            std::basic_string<CharT> target;
94
            auto result = unicode_traits::convert(
95
                name.data(), name.size(), target, 
96
                unicode_traits::conv_flags::strict);
97
            if (result.ec != unicode_traits::conv_errc())
98
            {
99
                JSONCONS_THROW(ser_error(result.ec,context.line(),context.column()));
100
            }
101
            other_visitor_.key(target, context, ec);
102
            JSONCONS_VISITOR_RETURN;
103
        }
104
105
        JSONCONS_VISITOR_RETURN_TYPE visit_string(const string_view_type& value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
106
        {
107
            std::basic_string<CharT> target;
108
            auto result = unicode_traits::convert(
109
                value.data(), value.size(), target, 
110
                unicode_traits::conv_flags::strict);
111
            if (result.ec != unicode_traits::conv_errc())
112
            {
113
                ec = result.ec;
114
                JSONCONS_VISITOR_RETURN;
115
            }
116
            other_visitor_.string_value(target, tag, context, ec);
117
            JSONCONS_VISITOR_RETURN;
118
        }
119
120
        JSONCONS_VISITOR_RETURN_TYPE visit_int64(int64_t value, 
121
            semantic_tag tag, 
122
            const ser_context& context,
123
            std::error_code& ec) override
124
        {
125
            other_visitor_.int64_value(value, tag, context, ec);
126
            JSONCONS_VISITOR_RETURN;
127
        }
128
129
        JSONCONS_VISITOR_RETURN_TYPE visit_uint64(uint64_t value, 
130
            semantic_tag tag, 
131
            const ser_context& context,
132
            std::error_code& ec) override
133
        {
134
            other_visitor_.uint64_value(value, tag, context, ec);
135
            JSONCONS_VISITOR_RETURN;
136
        }
137
138
        JSONCONS_VISITOR_RETURN_TYPE visit_half(uint16_t value, 
139
            semantic_tag tag,
140
            const ser_context& context,
141
            std::error_code& ec) override
142
        {
143
            other_visitor_.half_value(value, tag, context, ec);
144
            JSONCONS_VISITOR_RETURN;
145
        }
146
147
        JSONCONS_VISITOR_RETURN_TYPE visit_double(double value, 
148
            semantic_tag tag,
149
            const ser_context& context,
150
            std::error_code& ec) override
151
        {
152
            other_visitor_.double_value(value, tag, context, ec);
153
            JSONCONS_VISITOR_RETURN;
154
        }
155
156
        JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
157
        {
158
            other_visitor_.bool_value(value, tag, context, ec);
159
            JSONCONS_VISITOR_RETURN;
160
        }
161
162
        JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag tag, const ser_context& context, std::error_code& ec) override
163
        {
164
            other_visitor_.null_value(tag, context, ec);
165
            JSONCONS_VISITOR_RETURN;
166
        }
167
    };
168
169
    template <typename CharT,typename Source=jsoncons::stream_source<CharT>,typename TempAlloc =std::allocator<char>>
170
    class basic_json_reader 
171
    {
172
    public:
173
        using char_type = CharT;
174
        using source_type = Source;
175
        using string_view_type = jsoncons::basic_string_view<CharT>;
176
    private:
177
        using char_allocator_type = typename std::allocator_traits<TempAlloc>:: template rebind_alloc<CharT>;
178
179
        static constexpr size_t default_max_buffer_size = 16384;
180
181
        json_source_adaptor<Source> source_;
182
        basic_default_json_visitor<CharT> default_visitor_;
183
        basic_json_visitor<CharT>& visitor_;
184
        basic_json_parser<CharT,TempAlloc> parser_;
185
186
        // Noncopyable and nonmoveable
187
        basic_json_reader(const basic_json_reader&) = delete;
188
        basic_json_reader& operator=(const basic_json_reader&) = delete;
189
190
    public:
191
        template <typename Sourceable>
192
        explicit basic_json_reader(Sourceable&& source, const TempAlloc& temp_alloc = TempAlloc())
193
            : basic_json_reader(std::forward<Sourceable>(source),
194
                                default_visitor_,
195
                                basic_json_decode_options<CharT>(),
196
                                default_json_parsing(),
197
                                temp_alloc)
198
        {
199
        }
200
201
        template <typename Sourceable>
202
        basic_json_reader(Sourceable&& source, 
203
                          const basic_json_decode_options<CharT>& options, 
204
                          const TempAlloc& temp_alloc = TempAlloc())
205
            : basic_json_reader(std::forward<Sourceable>(source),
206
                                default_visitor_,
207
                                options,
208
                                options.err_handler(),
209
                                temp_alloc)
210
        {
211
        }
212
213
        template <typename Sourceable>
214
        basic_json_reader(Sourceable&& source,
215
                          std::function<bool(json_errc,const ser_context&)> err_handler, 
216
                          const TempAlloc& temp_alloc = TempAlloc())
217
            : basic_json_reader(std::forward<Sourceable>(source),
218
                                default_visitor_,
219
                                basic_json_decode_options<CharT>(),
220
                                err_handler,
221
                                temp_alloc)
222
        {
223
        }
224
225
        template <typename Sourceable>
226
        basic_json_reader(Sourceable&& source, 
227
                          const basic_json_decode_options<CharT>& options,
228
                          std::function<bool(json_errc,const ser_context&)> err_handler, 
229
                          const TempAlloc& temp_alloc = TempAlloc())
230
            : basic_json_reader(std::forward<Sourceable>(source),
231
                                default_visitor_,
232
                                options,
233
                                err_handler,
234
                                temp_alloc)
235
        {
236
        }
237
238
        template <typename Sourceable>
239
        basic_json_reader(Sourceable&& source, 
240
                          basic_json_visitor<CharT>& visitor, 
241
                          const TempAlloc& temp_alloc = TempAlloc())
242
8.62k
            : basic_json_reader(std::forward<Sourceable>(source),
243
8.62k
                                visitor,
244
8.62k
                                basic_json_decode_options<CharT>(),
245
8.62k
                                default_json_parsing(),
246
8.62k
                                temp_alloc)
247
8.62k
        {
248
8.62k
        }
249
250
        template <typename Sourceable>
251
        basic_json_reader(Sourceable&& source, 
252
                          basic_json_visitor<CharT>& visitor,
253
                          const basic_json_decode_options<CharT>& options, 
254
                          const TempAlloc& temp_alloc = TempAlloc())
255
            : basic_json_reader(std::forward<Sourceable>(source),
256
                                visitor,
257
                                options,
258
                                options.err_handler(),
259
                                temp_alloc)
260
        {
261
        }
262
263
        template <typename Sourceable>
264
        basic_json_reader(Sourceable&& source,
265
                          basic_json_visitor<CharT>& visitor,
266
                          std::function<bool(json_errc,const ser_context&)> err_handler, 
267
                          const TempAlloc& temp_alloc = TempAlloc())
268
            : basic_json_reader(std::forward<Sourceable>(source),
269
                                visitor,
270
                                basic_json_decode_options<CharT>(),
271
                                err_handler,
272
                                temp_alloc)
273
        {
274
        }
275
276
        template <typename Sourceable>
277
        basic_json_reader(Sourceable&& source,
278
                          basic_json_visitor<CharT>& visitor, 
279
                          const basic_json_decode_options<CharT>& options,
280
                          std::function<bool(json_errc,const ser_context&)> err_handler, 
281
                          const TempAlloc& temp_alloc = TempAlloc())
282
8.62k
           : source_(std::forward<Sourceable>(source)),
283
8.62k
             visitor_(visitor),
284
8.62k
             parser_(options,err_handler,temp_alloc)
285
8.62k
        {
286
8.62k
        }
287
288
        void read_next()
289
        {
290
            std::error_code ec;
291
            read_next(ec);
292
            if (JSONCONS_UNLIKELY(ec))
293
            {
294
                JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
295
            }
296
        }
297
298
        void read_next(std::error_code& ec)
299
8.62k
        {
300
8.62k
            if (source_.is_error())
301
0
            {
302
0
                ec = json_errc::source_error;
303
0
                return;
304
0
            }        
305
8.62k
            parser_.reset();
306
27.2k
            while (!parser_.stopped())
307
24.6k
            {
308
24.6k
                if (parser_.source_exhausted())
309
24.6k
                {
310
24.6k
                    auto s = source_.read_buffer(ec);
311
24.6k
                    if (JSONCONS_UNLIKELY(ec)) return;
312
24.6k
                    if (s.size() > 0)
313
16.2k
                    {
314
16.2k
                        parser_.update(s.data(),s.size());
315
16.2k
                    }
316
24.6k
                }
317
24.6k
                bool eof = parser_.source_exhausted();
318
24.6k
                parser_.parse_some(visitor_, ec);
319
24.6k
                if (JSONCONS_UNLIKELY(ec)) return;
320
19.8k
                if (eof)
321
5.54k
                {
322
5.54k
                    if (parser_.enter())
323
33
                    {
324
33
                        break;
325
33
                    }
326
5.51k
                    else if (!parser_.accept())
327
1.18k
                    {
328
1.18k
                        ec = json_errc::unexpected_eof;
329
1.18k
                        return;
330
1.18k
                    }
331
5.54k
                }
332
19.8k
            }
333
            
334
2.62k
            parser_.skip_whitespace();
335
3.86k
            while (!source_.eof())
336
1.30k
            {
337
1.30k
                parser_.skip_whitespace();
338
1.30k
                if (parser_.source_exhausted())
339
1.24k
                {
340
1.24k
                    auto s = source_.read_buffer(ec);
341
1.24k
                    if (JSONCONS_UNLIKELY(ec)) return;
342
1.24k
                    if (s.size() > 0)
343
1.19k
                    {
344
1.19k
                        parser_.update(s.data(),s.size());
345
1.19k
                    }
346
1.24k
                }
347
65
                else
348
65
                {
349
65
                    break;
350
65
                }
351
1.30k
            }
352
2.62k
        }
353
354
        void check_done()
355
        {
356
            std::error_code ec;
357
            check_done(ec);
358
            if (JSONCONS_UNLIKELY(ec))
359
            {
360
                JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
361
            }
362
        }
363
364
        std::size_t line() const
365
        {
366
            return parser_.line();
367
        }
368
369
        std::size_t column() const
370
        {
371
            return parser_.column();
372
        }
373
374
        void check_done(std::error_code& ec)
375
2.62k
        {
376
2.62k
            if (source_.is_error())
377
0
            {
378
0
                ec = json_errc::source_error;
379
0
                return;
380
0
            }   
381
2.62k
            if (source_.eof())
382
2.56k
            {
383
2.56k
                parser_.check_done(ec);
384
2.56k
                if (JSONCONS_UNLIKELY(ec)) return;
385
2.56k
            }
386
65
            else
387
65
            {
388
65
                do
389
65
                {
390
65
                    if (parser_.source_exhausted())
391
0
                    {
392
0
                        auto s = source_.read_buffer(ec);
393
0
                        if (JSONCONS_UNLIKELY(ec)) return;
394
0
                        if (s.size() > 0)
395
0
                        {
396
0
                            parser_.update(s.data(),s.size());
397
0
                        }
398
0
                    }
399
65
                    if (!parser_.source_exhausted())
400
65
                    {
401
65
                        parser_.check_done(ec);
402
65
                        if (JSONCONS_UNLIKELY(ec)) return;
403
65
                    }
404
65
                }
405
65
                while (!eof());
406
65
            }
407
2.62k
        }
408
409
        bool eof() const
410
0
        {
411
0
            return parser_.source_exhausted() && source_.eof();
412
0
        }
413
414
        void read()
415
        {
416
            read_next();
417
            check_done();
418
        }
419
420
        void read(std::error_code& ec)
421
8.62k
        {
422
8.62k
            read_next(ec);
423
8.62k
            if (!ec)
424
2.62k
            {
425
2.62k
                check_done(ec);
426
2.62k
            }
427
8.62k
        }
428
    };
429
430
    using json_string_reader = basic_json_reader<char,string_source<char>>;
431
    using wjson_string_reader = basic_json_reader<wchar_t,string_source<wchar_t>>;
432
    using json_stream_reader = basic_json_reader<char,stream_source<char>>;
433
    using wjson_stream_reader = basic_json_reader<wchar_t,stream_source<wchar_t>>;
434
435
}
436
437
#endif
438