/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 | | |