1 | // __ _____ _____ _____ |
---|---|
2 | // __| | __| | | | JSON for Modern C++ |
3 | // | | |__ | | | | | | version 3.11.2 |
4 | // |_____|_____|_____|_|___| https://github.com/nlohmann/json |
5 | // |
6 | // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> |
7 | // SPDX-License-Identifier: MIT |
8 | |
9 | #pragma once |
10 | |
11 | #include <cstddef> |
12 | #include <string> // string |
13 | #include <utility> // move |
14 | #include <vector> // vector |
15 | |
16 | #include <nlohmann/detail/exceptions.hpp> |
17 | #include <nlohmann/detail/macro_scope.hpp> |
18 | #include <nlohmann/detail/string_concat.hpp> |
19 | |
20 | NLOHMANN_JSON_NAMESPACE_BEGIN |
21 | |
22 | /*! |
23 | @brief SAX interface |
24 | |
25 | This class describes the SAX interface used by @ref nlohmann::json::sax_parse. |
26 | Each function is called in different situations while the input is parsed. The |
27 | boolean return value informs the parser whether to continue processing the |
28 | input. |
29 | */ |
30 | template<typename BasicJsonType> |
31 | struct json_sax |
32 | { |
33 | using number_integer_t = typename BasicJsonType::number_integer_t; |
34 | using number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
35 | using number_float_t = typename BasicJsonType::number_float_t; |
36 | using string_t = typename BasicJsonType::string_t; |
37 | using binary_t = typename BasicJsonType::binary_t; |
38 | |
39 | /*! |
40 | @brief a null value was read |
41 | @return whether parsing should proceed |
42 | */ |
43 | virtual bool null() = 0; |
44 | |
45 | /*! |
46 | @brief a boolean value was read |
47 | @param[in] val boolean value |
48 | @return whether parsing should proceed |
49 | */ |
50 | virtual bool boolean(bool val) = 0; |
51 | |
52 | /*! |
53 | @brief an integer number was read |
54 | @param[in] val integer value |
55 | @return whether parsing should proceed |
56 | */ |
57 | virtual bool number_integer(number_integer_t val) = 0; |
58 | |
59 | /*! |
60 | @brief an unsigned integer number was read |
61 | @param[in] val unsigned integer value |
62 | @return whether parsing should proceed |
63 | */ |
64 | virtual bool number_unsigned(number_unsigned_t val) = 0; |
65 | |
66 | /*! |
67 | @brief a floating-point number was read |
68 | @param[in] val floating-point value |
69 | @param[in] s raw token value |
70 | @return whether parsing should proceed |
71 | */ |
72 | virtual bool number_float(number_float_t val, const string_t& s) = 0; |
73 | |
74 | /*! |
75 | @brief a string value was read |
76 | @param[in] val string value |
77 | @return whether parsing should proceed |
78 | @note It is safe to move the passed string value. |
79 | */ |
80 | virtual bool string(string_t& val) = 0; |
81 | |
82 | /*! |
83 | @brief a binary value was read |
84 | @param[in] val binary value |
85 | @return whether parsing should proceed |
86 | @note It is safe to move the passed binary value. |
87 | */ |
88 | virtual bool binary(binary_t& val) = 0; |
89 | |
90 | /*! |
91 | @brief the beginning of an object was read |
92 | @param[in] elements number of object elements or -1 if unknown |
93 | @return whether parsing should proceed |
94 | @note binary formats may report the number of elements |
95 | */ |
96 | virtual bool start_object(std::size_t elements) = 0; |
97 | |
98 | /*! |
99 | @brief an object key was read |
100 | @param[in] val object key |
101 | @return whether parsing should proceed |
102 | @note It is safe to move the passed string. |
103 | */ |
104 | virtual bool key(string_t& val) = 0; |
105 | |
106 | /*! |
107 | @brief the end of an object was read |
108 | @return whether parsing should proceed |
109 | */ |
110 | virtual bool end_object() = 0; |
111 | |
112 | /*! |
113 | @brief the beginning of an array was read |
114 | @param[in] elements number of array elements or -1 if unknown |
115 | @return whether parsing should proceed |
116 | @note binary formats may report the number of elements |
117 | */ |
118 | virtual bool start_array(std::size_t elements) = 0; |
119 | |
120 | /*! |
121 | @brief the end of an array was read |
122 | @return whether parsing should proceed |
123 | */ |
124 | virtual bool end_array() = 0; |
125 | |
126 | /*! |
127 | @brief a parse error occurred |
128 | @param[in] position the position in the input where the error occurs |
129 | @param[in] last_token the last read token |
130 | @param[in] ex an exception object describing the error |
131 | @return whether parsing should proceed (must return false) |
132 | */ |
133 | virtual bool parse_error(std::size_t position, |
134 | const std::string& last_token, |
135 | const detail::exception& ex) = 0; |
136 | |
137 | json_sax() = default; |
138 | json_sax(const json_sax&) = default; |
139 | json_sax(json_sax&&) noexcept = default; |
140 | json_sax& operator=(const json_sax&) = default; |
141 | json_sax& operator=(json_sax&&) noexcept = default; |
142 | virtual ~json_sax() = default; |
143 | }; |
144 | |
145 | |
146 | namespace detail |
147 | { |
148 | /*! |
149 | @brief SAX implementation to create a JSON value from SAX events |
150 | |
151 | This class implements the @ref json_sax interface and processes the SAX events |
152 | to create a JSON value which makes it basically a DOM parser. The structure or |
153 | hierarchy of the JSON value is managed by the stack `ref_stack` which contains |
154 | a pointer to the respective array or object for each recursion depth. |
155 | |
156 | After successful parsing, the value that is passed by reference to the |
157 | constructor contains the parsed value. |
158 | |
159 | @tparam BasicJsonType the JSON type |
160 | */ |
161 | template<typename BasicJsonType> |
162 | class json_sax_dom_parser |
163 | { |
164 | public: |
165 | using number_integer_t = typename BasicJsonType::number_integer_t; |
166 | using number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
167 | using number_float_t = typename BasicJsonType::number_float_t; |
168 | using string_t = typename BasicJsonType::string_t; |
169 | using binary_t = typename BasicJsonType::binary_t; |
170 | |
171 | /*! |
172 | @param[in,out] r reference to a JSON value that is manipulated while |
173 | parsing |
174 | @param[in] allow_exceptions_ whether parse errors yield exceptions |
175 | */ |
176 | explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) |
177 | : root(r), allow_exceptions(allow_exceptions_) |
178 | {} |
179 | |
180 | // make class move-only |
181 | json_sax_dom_parser(const json_sax_dom_parser&) = delete; |
182 | json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) |
183 | json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; |
184 | json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) |
185 | ~json_sax_dom_parser() = default; |
186 | |
187 | bool null() |
188 | { |
189 | handle_value(nullptr); |
190 | return true; |
191 | } |
192 | |
193 | bool boolean(bool val) |
194 | { |
195 | handle_value(val); |
196 | return true; |
197 | } |
198 | |
199 | bool number_integer(number_integer_t val) |
200 | { |
201 | handle_value(val); |
202 | return true; |
203 | } |
204 | |
205 | bool number_unsigned(number_unsigned_t val) |
206 | { |
207 | handle_value(val); |
208 | return true; |
209 | } |
210 | |
211 | bool number_float(number_float_t val, const string_t& /*unused*/) |
212 | { |
213 | handle_value(val); |
214 | return true; |
215 | } |
216 | |
217 | bool string(string_t& val) |
218 | { |
219 | handle_value(val); |
220 | return true; |
221 | } |
222 | |
223 | bool binary(binary_t& val) |
224 | { |
225 | handle_value(std::move(val)); |
226 | return true; |
227 | } |
228 | |
229 | bool start_object(std::size_t len) |
230 | { |
231 | ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); |
232 | |
233 | if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) |
234 | { |
235 | JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); |
236 | } |
237 | |
238 | return true; |
239 | } |
240 | |
241 | bool key(string_t& val) |
242 | { |
243 | JSON_ASSERT(!ref_stack.empty()); |
244 | JSON_ASSERT(ref_stack.back()->is_object()); |
245 | |
246 | // add null at given key and store the reference for later |
247 | object_element = &(ref_stack.back()->m_value.object->operator[](val)); |
248 | return true; |
249 | } |
250 | |
251 | bool end_object() |
252 | { |
253 | JSON_ASSERT(!ref_stack.empty()); |
254 | JSON_ASSERT(ref_stack.back()->is_object()); |
255 | |
256 | ref_stack.back()->set_parents(); |
257 | ref_stack.pop_back(); |
258 | return true; |
259 | } |
260 | |
261 | bool start_array(std::size_t len) |
262 | { |
263 | ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); |
264 | |
265 | if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) |
266 | { |
267 | JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); |
268 | } |
269 | |
270 | return true; |
271 | } |
272 | |
273 | bool end_array() |
274 | { |
275 | JSON_ASSERT(!ref_stack.empty()); |
276 | JSON_ASSERT(ref_stack.back()->is_array()); |
277 | |
278 | ref_stack.back()->set_parents(); |
279 | ref_stack.pop_back(); |
280 | return true; |
281 | } |
282 | |
283 | template<class Exception> |
284 | bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, |
285 | const Exception& ex) |
286 | { |
287 | errored = true; |
288 | static_cast<void>(ex); |
289 | if (allow_exceptions) |
290 | { |
291 | JSON_THROW(ex); |
292 | } |
293 | return false; |
294 | } |
295 | |
296 | constexpr bool is_errored() const |
297 | { |
298 | return errored; |
299 | } |
300 | |
301 | private: |
302 | /*! |
303 | @invariant If the ref stack is empty, then the passed value will be the new |
304 | root. |
305 | @invariant If the ref stack contains a value, then it is an array or an |
306 | object to which we can add elements |
307 | */ |
308 | template<typename Value> |
309 | JSON_HEDLEY_RETURNS_NON_NULL |
310 | BasicJsonType* handle_value(Value&& v) |
311 | { |
312 | if (ref_stack.empty()) |
313 | { |
314 | root = BasicJsonType(std::forward<Value>(v)); |
315 | return &root; |
316 | } |
317 | |
318 | JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); |
319 | |
320 | if (ref_stack.back()->is_array()) |
321 | { |
322 | ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v)); |
323 | return &(ref_stack.back()->m_value.array->back()); |
324 | } |
325 | |
326 | JSON_ASSERT(ref_stack.back()->is_object()); |
327 | JSON_ASSERT(object_element); |
328 | *object_element = BasicJsonType(std::forward<Value>(v)); |
329 | return object_element; |
330 | } |
331 | |
332 | /// the parsed JSON value |
333 | BasicJsonType& root; |
334 | /// stack to model hierarchy of values |
335 | std::vector<BasicJsonType*> ref_stack {}; |
336 | /// helper to hold the reference for the next object element |
337 | BasicJsonType* object_element = nullptr; |
338 | /// whether a syntax error occurred |
339 | bool errored = false; |
340 | /// whether to throw exceptions in case of errors |
341 | const bool allow_exceptions = true; |
342 | }; |
343 | |
344 | template<typename BasicJsonType> |
345 | class json_sax_dom_callback_parser |
346 | { |
347 | public: |
348 | using number_integer_t = typename BasicJsonType::number_integer_t; |
349 | using number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
350 | using number_float_t = typename BasicJsonType::number_float_t; |
351 | using string_t = typename BasicJsonType::string_t; |
352 | using binary_t = typename BasicJsonType::binary_t; |
353 | using parser_callback_t = typename BasicJsonType::parser_callback_t; |
354 | using parse_event_t = typename BasicJsonType::parse_event_t; |
355 | |
356 | json_sax_dom_callback_parser(BasicJsonType& r, |
357 | const parser_callback_t cb, |
358 | const bool allow_exceptions_ = true) |
359 | : root(r), callback(cb), allow_exceptions(allow_exceptions_) |
360 | { |
361 | keep_stack.push_back(x: true); |
362 | } |
363 | |
364 | // make class move-only |
365 | json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; |
366 | json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) |
367 | json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; |
368 | json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) |
369 | ~json_sax_dom_callback_parser() = default; |
370 | |
371 | bool null() |
372 | { |
373 | handle_value(nullptr); |
374 | return true; |
375 | } |
376 | |
377 | bool boolean(bool val) |
378 | { |
379 | handle_value(val); |
380 | return true; |
381 | } |
382 | |
383 | bool number_integer(number_integer_t val) |
384 | { |
385 | handle_value(val); |
386 | return true; |
387 | } |
388 | |
389 | bool number_unsigned(number_unsigned_t val) |
390 | { |
391 | handle_value(val); |
392 | return true; |
393 | } |
394 | |
395 | bool number_float(number_float_t val, const string_t& /*unused*/) |
396 | { |
397 | handle_value(val); |
398 | return true; |
399 | } |
400 | |
401 | bool string(string_t& val) |
402 | { |
403 | handle_value(val); |
404 | return true; |
405 | } |
406 | |
407 | bool binary(binary_t& val) |
408 | { |
409 | handle_value(std::move(val)); |
410 | return true; |
411 | } |
412 | |
413 | bool start_object(std::size_t len) |
414 | { |
415 | // check callback for object start |
416 | const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); |
417 | keep_stack.push_back(x: keep); |
418 | |
419 | auto val = handle_value(BasicJsonType::value_t::object, true); |
420 | ref_stack.push_back(val.second); |
421 | |
422 | // check object limit |
423 | if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) |
424 | { |
425 | JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); |
426 | } |
427 | |
428 | return true; |
429 | } |
430 | |
431 | bool key(string_t& val) |
432 | { |
433 | BasicJsonType k = BasicJsonType(val); |
434 | |
435 | // check callback for key |
436 | const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); |
437 | key_keep_stack.push_back(x: keep); |
438 | |
439 | // add discarded value at given key and store the reference for later |
440 | if (keep && ref_stack.back()) |
441 | { |
442 | object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); |
443 | } |
444 | |
445 | return true; |
446 | } |
447 | |
448 | bool end_object() |
449 | { |
450 | if (ref_stack.back()) |
451 | { |
452 | if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) |
453 | { |
454 | // discard object |
455 | *ref_stack.back() = discarded; |
456 | } |
457 | else |
458 | { |
459 | ref_stack.back()->set_parents(); |
460 | } |
461 | } |
462 | |
463 | JSON_ASSERT(!ref_stack.empty()); |
464 | JSON_ASSERT(!keep_stack.empty()); |
465 | ref_stack.pop_back(); |
466 | keep_stack.pop_back(); |
467 | |
468 | if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) |
469 | { |
470 | // remove discarded value |
471 | for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) |
472 | { |
473 | if (it->is_discarded()) |
474 | { |
475 | ref_stack.back()->erase(it); |
476 | break; |
477 | } |
478 | } |
479 | } |
480 | |
481 | return true; |
482 | } |
483 | |
484 | bool start_array(std::size_t len) |
485 | { |
486 | const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); |
487 | keep_stack.push_back(x: keep); |
488 | |
489 | auto val = handle_value(BasicJsonType::value_t::array, true); |
490 | ref_stack.push_back(val.second); |
491 | |
492 | // check array limit |
493 | if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) |
494 | { |
495 | JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); |
496 | } |
497 | |
498 | return true; |
499 | } |
500 | |
501 | bool end_array() |
502 | { |
503 | bool keep = true; |
504 | |
505 | if (ref_stack.back()) |
506 | { |
507 | keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); |
508 | if (keep) |
509 | { |
510 | ref_stack.back()->set_parents(); |
511 | } |
512 | else |
513 | { |
514 | // discard array |
515 | *ref_stack.back() = discarded; |
516 | } |
517 | } |
518 | |
519 | JSON_ASSERT(!ref_stack.empty()); |
520 | JSON_ASSERT(!keep_stack.empty()); |
521 | ref_stack.pop_back(); |
522 | keep_stack.pop_back(); |
523 | |
524 | // remove discarded value |
525 | if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) |
526 | { |
527 | ref_stack.back()->m_value.array->pop_back(); |
528 | } |
529 | |
530 | return true; |
531 | } |
532 | |
533 | template<class Exception> |
534 | bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, |
535 | const Exception& ex) |
536 | { |
537 | errored = true; |
538 | static_cast<void>(ex); |
539 | if (allow_exceptions) |
540 | { |
541 | JSON_THROW(ex); |
542 | } |
543 | return false; |
544 | } |
545 | |
546 | constexpr bool is_errored() const |
547 | { |
548 | return errored; |
549 | } |
550 | |
551 | private: |
552 | /*! |
553 | @param[in] v value to add to the JSON value we build during parsing |
554 | @param[in] skip_callback whether we should skip calling the callback |
555 | function; this is required after start_array() and |
556 | start_object() SAX events, because otherwise we would call the |
557 | callback function with an empty array or object, respectively. |
558 | |
559 | @invariant If the ref stack is empty, then the passed value will be the new |
560 | root. |
561 | @invariant If the ref stack contains a value, then it is an array or an |
562 | object to which we can add elements |
563 | |
564 | @return pair of boolean (whether value should be kept) and pointer (to the |
565 | passed value in the ref_stack hierarchy; nullptr if not kept) |
566 | */ |
567 | template<typename Value> |
568 | std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) |
569 | { |
570 | JSON_ASSERT(!keep_stack.empty()); |
571 | |
572 | // do not handle this value if we know it would be added to a discarded |
573 | // container |
574 | if (!keep_stack.back()) |
575 | { |
576 | return {false, nullptr}; |
577 | } |
578 | |
579 | // create value |
580 | auto value = BasicJsonType(std::forward<Value>(v)); |
581 | |
582 | // check callback |
583 | const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); |
584 | |
585 | // do not handle this value if we just learnt it shall be discarded |
586 | if (!keep) |
587 | { |
588 | return {false, nullptr}; |
589 | } |
590 | |
591 | if (ref_stack.empty()) |
592 | { |
593 | root = std::move(value); |
594 | return {true, &root}; |
595 | } |
596 | |
597 | // skip this value if we already decided to skip the parent |
598 | // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) |
599 | if (!ref_stack.back()) |
600 | { |
601 | return {false, nullptr}; |
602 | } |
603 | |
604 | // we now only expect arrays and objects |
605 | JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); |
606 | |
607 | // array |
608 | if (ref_stack.back()->is_array()) |
609 | { |
610 | ref_stack.back()->m_value.array->emplace_back(std::move(value)); |
611 | return {true, &(ref_stack.back()->m_value.array->back())}; |
612 | } |
613 | |
614 | // object |
615 | JSON_ASSERT(ref_stack.back()->is_object()); |
616 | // check if we should store an element for the current key |
617 | JSON_ASSERT(!key_keep_stack.empty()); |
618 | const bool store_element = key_keep_stack.back(); |
619 | key_keep_stack.pop_back(); |
620 | |
621 | if (!store_element) |
622 | { |
623 | return {false, nullptr}; |
624 | } |
625 | |
626 | JSON_ASSERT(object_element); |
627 | *object_element = std::move(value); |
628 | return {true, object_element}; |
629 | } |
630 | |
631 | /// the parsed JSON value |
632 | BasicJsonType& root; |
633 | /// stack to model hierarchy of values |
634 | std::vector<BasicJsonType*> ref_stack {}; |
635 | /// stack to manage which values to keep |
636 | std::vector<bool> keep_stack {}; |
637 | /// stack to manage which object keys to keep |
638 | std::vector<bool> key_keep_stack {}; |
639 | /// helper to hold the reference for the next object element |
640 | BasicJsonType* object_element = nullptr; |
641 | /// whether a syntax error occurred |
642 | bool errored = false; |
643 | /// callback function |
644 | const parser_callback_t callback = nullptr; |
645 | /// whether to throw exceptions in case of errors |
646 | const bool allow_exceptions = true; |
647 | /// a discarded value for the callback |
648 | BasicJsonType discarded = BasicJsonType::value_t::discarded; |
649 | }; |
650 | |
651 | template<typename BasicJsonType> |
652 | class json_sax_acceptor |
653 | { |
654 | public: |
655 | using number_integer_t = typename BasicJsonType::number_integer_t; |
656 | using number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
657 | using number_float_t = typename BasicJsonType::number_float_t; |
658 | using string_t = typename BasicJsonType::string_t; |
659 | using binary_t = typename BasicJsonType::binary_t; |
660 | |
661 | bool null() |
662 | { |
663 | return true; |
664 | } |
665 | |
666 | bool boolean(bool /*unused*/) |
667 | { |
668 | return true; |
669 | } |
670 | |
671 | bool number_integer(number_integer_t /*unused*/) |
672 | { |
673 | return true; |
674 | } |
675 | |
676 | bool number_unsigned(number_unsigned_t /*unused*/) |
677 | { |
678 | return true; |
679 | } |
680 | |
681 | bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) |
682 | { |
683 | return true; |
684 | } |
685 | |
686 | bool string(string_t& /*unused*/) |
687 | { |
688 | return true; |
689 | } |
690 | |
691 | bool binary(binary_t& /*unused*/) |
692 | { |
693 | return true; |
694 | } |
695 | |
696 | bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) |
697 | { |
698 | return true; |
699 | } |
700 | |
701 | bool key(string_t& /*unused*/) |
702 | { |
703 | return true; |
704 | } |
705 | |
706 | bool end_object() |
707 | { |
708 | return true; |
709 | } |
710 | |
711 | bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) |
712 | { |
713 | return true; |
714 | } |
715 | |
716 | bool end_array() |
717 | { |
718 | return true; |
719 | } |
720 | |
721 | bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) |
722 | { |
723 | return false; |
724 | } |
725 | }; |
726 | |
727 | } // namespace detail |
728 | NLOHMANN_JSON_NAMESPACE_END |
729 |
Definitions
- json_sax
- json_sax
- json_sax
- json_sax
- operator=
- operator=
- ~json_sax
- json_sax_dom_parser
- json_sax_dom_parser
- json_sax_dom_parser
- json_sax_dom_parser
- operator=
- operator=
- ~json_sax_dom_parser
- null
- boolean
- number_integer
- number_unsigned
- number_float
- string
- binary
- start_object
- key
- end_object
- start_array
- end_array
- parse_error
- is_errored
- handle_value
- json_sax_dom_callback_parser
- json_sax_dom_callback_parser
- json_sax_dom_callback_parser
- json_sax_dom_callback_parser
- operator=
- operator=
- ~json_sax_dom_callback_parser
- null
- boolean
- number_integer
- number_unsigned
- number_float
- string
- binary
- start_object
- key
- end_object
- start_array
- end_array
- parse_error
- is_errored
- handle_value
- json_sax_acceptor
- null
- boolean
- number_integer
- number_unsigned
- number_float
- string
- binary
- start_object
- key
- end_object
- start_array
- end_array
Learn more about Flutter for embedded and desktop on industrialflutter.com