RflySimSDK v4.10
RflySimSDK说明文档
载入中...
搜索中...
未找到
json_sax.hpp
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9#pragma once
10
11#include <cstddef>
12#include <string> // string
13#include <type_traits> // enable_if_t
14#include <utility> // move
15#include <vector> // vector
16
17#include <nlohmann/detail/exceptions.hpp>
18#include <nlohmann/detail/input/lexer.hpp>
19#include <nlohmann/detail/macro_scope.hpp>
20#include <nlohmann/detail/string_concat.hpp>
21NLOHMANN_JSON_NAMESPACE_BEGIN
22
23/*!
24@brief SAX interface
25
26This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
27Each function is called in different situations while the input is parsed. The
28boolean return value informs the parser whether to continue processing the
29input.
30*/
31template<typename BasicJsonType>
32struct json_sax
33{
34 using number_integer_t = typename BasicJsonType::number_integer_t;
35 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
36 using number_float_t = typename BasicJsonType::number_float_t;
37 using string_t = typename BasicJsonType::string_t;
38 using binary_t = typename BasicJsonType::binary_t;
39
40 /*!
41 @brief a null value was read
42 @return whether parsing should proceed
43 */
44 virtual bool null() = 0;
45
46 /*!
47 @brief a boolean value was read
48 @param[in] val boolean value
49 @return whether parsing should proceed
50 */
51 virtual bool boolean(bool val) = 0;
52
53 /*!
54 @brief an integer number was read
55 @param[in] val integer value
56 @return whether parsing should proceed
57 */
58 virtual bool number_integer(number_integer_t val) = 0;
59
60 /*!
61 @brief an unsigned integer number was read
62 @param[in] val unsigned integer value
63 @return whether parsing should proceed
64 */
65 virtual bool number_unsigned(number_unsigned_t val) = 0;
66
67 /*!
68 @brief a floating-point number was read
69 @param[in] val floating-point value
70 @param[in] s raw token value
71 @return whether parsing should proceed
72 */
73 virtual bool number_float(number_float_t val, const string_t& s) = 0;
74
75 /*!
76 @brief a string value was read
77 @param[in] val string value
78 @return whether parsing should proceed
79 @note It is safe to move the passed string value.
80 */
81 virtual bool string(string_t& val) = 0;
82
83 /*!
84 @brief a binary value was read
85 @param[in] val binary value
86 @return whether parsing should proceed
87 @note It is safe to move the passed binary value.
88 */
89 virtual bool binary(binary_t& val) = 0;
90
91 /*!
92 @brief the beginning of an object was read
93 @param[in] elements number of object elements or -1 if unknown
94 @return whether parsing should proceed
95 @note binary formats may report the number of elements
96 */
97 virtual bool start_object(std::size_t elements) = 0;
98
99 /*!
100 @brief an object key was read
101 @param[in] val object key
102 @return whether parsing should proceed
103 @note It is safe to move the passed string.
104 */
105 virtual bool key(string_t& val) = 0;
106
107 /*!
108 @brief the end of an object was read
109 @return whether parsing should proceed
110 */
111 virtual bool end_object() = 0;
112
113 /*!
114 @brief the beginning of an array was read
115 @param[in] elements number of array elements or -1 if unknown
116 @return whether parsing should proceed
117 @note binary formats may report the number of elements
118 */
119 virtual bool start_array(std::size_t elements) = 0;
120
121 /*!
122 @brief the end of an array was read
123 @return whether parsing should proceed
124 */
125 virtual bool end_array() = 0;
126
127 /*!
128 @brief a parse error occurred
129 @param[in] position the position in the input where the error occurs
130 @param[in] last_token the last read token
131 @param[in] ex an exception object describing the error
132 @return whether parsing should proceed (must return false)
133 */
134 virtual bool parse_error(std::size_t position,
135 const std::string& last_token,
136 const detail::exception& ex) = 0;
137
138 json_sax() = default;
139 json_sax(const json_sax&) = default;
140 json_sax(json_sax&&) noexcept = default;
141 json_sax& operator=(const json_sax&) = default;
142 json_sax& operator=(json_sax&&) noexcept = default;
143 virtual ~json_sax() = default;
144};
145
146namespace detail
147{
148constexpr std::size_t unknown_size()
149{
150 return (std::numeric_limits<std::size_t>::max)();
151}
152
153/*!
154@brief SAX implementation to create a JSON value from SAX events
155
156This class implements the @ref json_sax interface and processes the SAX events
157to create a JSON value which makes it basically a DOM parser. The structure or
158hierarchy of the JSON value is managed by the stack `ref_stack` which contains
159a pointer to the respective array or object for each recursion depth.
160
161After successful parsing, the value that is passed by reference to the
162constructor contains the parsed value.
163
164@tparam BasicJsonType the JSON type
165*/
166template<typename BasicJsonType, typename InputAdapterType>
168{
169 public:
170 using number_integer_t = typename BasicJsonType::number_integer_t;
171 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
172 using number_float_t = typename BasicJsonType::number_float_t;
173 using string_t = typename BasicJsonType::string_t;
174 using binary_t = typename BasicJsonType::binary_t;
176
177 /*!
178 @param[in,out] r reference to a JSON value that is manipulated while
179 parsing
180 @param[in] allow_exceptions_ whether parse errors yield exceptions
181 */
182 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
183 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
184 {}
185
186 // make class move-only
188 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
189 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
190 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
191 ~json_sax_dom_parser() = default;
192
193 bool null()
194 {
195 handle_value(nullptr);
196 return true;
197 }
198
199 bool boolean(bool val)
200 {
201 handle_value(val);
202 return true;
203 }
204
205 bool number_integer(number_integer_t val)
206 {
207 handle_value(val);
208 return true;
209 }
210
211 bool number_unsigned(number_unsigned_t val)
212 {
213 handle_value(val);
214 return true;
215 }
216
217 bool number_float(number_float_t val, const string_t& /*unused*/)
218 {
219 handle_value(val);
220 return true;
221 }
222
223 bool string(string_t& val)
224 {
225 handle_value(val);
226 return true;
227 }
228
229 bool binary(binary_t& val)
230 {
231 handle_value(std::move(val));
232 return true;
233 }
234
235 bool start_object(std::size_t len)
236 {
237 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
238
239#if JSON_DIAGNOSTIC_POSITIONS
240 // Manually set the start position of the object here.
241 // Ensure this is after the call to handle_value to ensure correct start position.
242 if (m_lexer_ref)
243 {
244 // Lexer has read the first character of the object, so
245 // subtract 1 from the position to get the correct start position.
246 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
247 }
248#endif
249
250 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
251 {
252 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
253 }
254
255 return true;
256 }
257
258 bool key(string_t& val)
259 {
260 JSON_ASSERT(!ref_stack.empty());
261 JSON_ASSERT(ref_stack.back()->is_object());
262
263 // add null at the given key and store the reference for later
264 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
265 return true;
266 }
267
268 bool end_object()
269 {
270 JSON_ASSERT(!ref_stack.empty());
271 JSON_ASSERT(ref_stack.back()->is_object());
272
273#if JSON_DIAGNOSTIC_POSITIONS
274 if (m_lexer_ref)
275 {
276 // Lexer's position is past the closing brace, so set that as the end position.
277 ref_stack.back()->end_position = m_lexer_ref->get_position();
278 }
279#endif
280
281 ref_stack.back()->set_parents();
282 ref_stack.pop_back();
283 return true;
284 }
285
286 bool start_array(std::size_t len)
287 {
288 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
289
290#if JSON_DIAGNOSTIC_POSITIONS
291 // Manually set the start position of the array here.
292 // Ensure this is after the call to handle_value to ensure correct start position.
293 if (m_lexer_ref)
294 {
295 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
296 }
297#endif
298
299 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
300 {
301 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
302 }
303
304 return true;
305 }
306
307 bool end_array()
308 {
309 JSON_ASSERT(!ref_stack.empty());
310 JSON_ASSERT(ref_stack.back()->is_array());
311
312#if JSON_DIAGNOSTIC_POSITIONS
313 if (m_lexer_ref)
314 {
315 // Lexer's position is past the closing bracket, so set that as the end position.
316 ref_stack.back()->end_position = m_lexer_ref->get_position();
317 }
318#endif
319
320 ref_stack.back()->set_parents();
321 ref_stack.pop_back();
322 return true;
323 }
324
325 template<class Exception>
326 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
327 const Exception& ex)
328 {
329 errored = true;
330 static_cast<void>(ex);
331 if (allow_exceptions)
332 {
333 JSON_THROW(ex);
334 }
335 return false;
336 }
337
338 constexpr bool is_errored() const
339 {
340 return errored;
341 }
342
343 private:
344
345#if JSON_DIAGNOSTIC_POSITIONS
346 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
347 {
348 if (m_lexer_ref)
349 {
350 // Lexer has read past the current field value, so set the end position to the current position.
351 // The start position will be set below based on the length of the string representation
352 // of the value.
353 v.end_position = m_lexer_ref->get_position();
354
355 switch (v.type())
356 {
357 case value_t::boolean:
358 {
359 // 4 and 5 are the string length of "true" and "false"
360 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
361 break;
362 }
363
364 case value_t::null:
365 {
366 // 4 is the string length of "null"
367 v.start_position = v.end_position - 4;
368 break;
369 }
370
371 case value_t::string:
372 {
373 // include the length of the quotes, which is 2
374 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
375 break;
376 }
377
378 // As we handle the start and end positions for values created during parsing,
379 // we do not expect the following value type to be called. Regardless, set the positions
380 // in case this is created manually or through a different constructor. Exclude from lcov
381 // since the exact condition of this switch is esoteric.
382 // LCOV_EXCL_START
383 case value_t::discarded:
384 {
385 v.end_position = std::string::npos;
386 v.start_position = v.end_position;
387 break;
388 }
389 // LCOV_EXCL_STOP
390 case value_t::binary:
391 case value_t::number_integer:
392 case value_t::number_unsigned:
393 case value_t::number_float:
394 {
395 v.start_position = v.end_position - m_lexer_ref->get_string().size();
396 break;
397 }
398 case value_t::object:
399 case value_t::array:
400 {
401 // object and array are handled in start_object() and start_array() handlers
402 // skip setting the values here.
403 break;
404 }
405 default: // LCOV_EXCL_LINE
406 // Handle all possible types discretely, default handler should never be reached.
407 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
408 }
409 }
410 }
411#endif
412
413 /*!
414 @invariant If the ref stack is empty, then the passed value will be the new
415 root.
416 @invariant If the ref stack contains a value, then it is an array or an
417 object to which we can add elements
418 */
419 template<typename Value>
420 JSON_HEDLEY_RETURNS_NON_NULL
421 BasicJsonType* handle_value(Value&& v)
422 {
423 if (ref_stack.empty())
424 {
425 root = BasicJsonType(std::forward<Value>(v));
426
427#if JSON_DIAGNOSTIC_POSITIONS
428 handle_diagnostic_positions_for_json_value(root);
429#endif
430
431 return &root;
432 }
433
434 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
435
436 if (ref_stack.back()->is_array())
437 {
438 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
439
440#if JSON_DIAGNOSTIC_POSITIONS
441 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
442#endif
443
444 return &(ref_stack.back()->m_data.m_value.array->back());
445 }
446
447 JSON_ASSERT(ref_stack.back()->is_object());
448 JSON_ASSERT(object_element);
449 *object_element = BasicJsonType(std::forward<Value>(v));
450
451#if JSON_DIAGNOSTIC_POSITIONS
452 handle_diagnostic_positions_for_json_value(*object_element);
453#endif
454
455 return object_element;
456 }
457
458 /// the parsed JSON value
459 BasicJsonType& root;
460 /// stack to model hierarchy of values
461 std::vector<BasicJsonType*> ref_stack {};
462 /// helper to hold the reference for the next object element
463 BasicJsonType* object_element = nullptr;
464 /// whether a syntax error occurred
465 bool errored = false;
466 /// whether to throw exceptions in case of errors
467 const bool allow_exceptions = true;
468 /// the lexer reference to obtain the current position
469 lexer_t* m_lexer_ref = nullptr;
470};
471
472template<typename BasicJsonType, typename InputAdapterType>
473class json_sax_dom_callback_parser
474{
475 public:
476 using number_integer_t = typename BasicJsonType::number_integer_t;
477 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
478 using number_float_t = typename BasicJsonType::number_float_t;
479 using string_t = typename BasicJsonType::string_t;
480 using binary_t = typename BasicJsonType::binary_t;
481 using parser_callback_t = typename BasicJsonType::parser_callback_t;
482 using parse_event_t = typename BasicJsonType::parse_event_t;
484
485 json_sax_dom_callback_parser(BasicJsonType& r,
486 parser_callback_t cb,
487 const bool allow_exceptions_ = true,
488 lexer_t* lexer_ = nullptr)
489 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
490 {
491 keep_stack.push_back(true);
492 }
493
494 // make class move-only
495 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
496 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
497 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
498 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
499 ~json_sax_dom_callback_parser() = default;
500
501 bool null()
502 {
503 handle_value(nullptr);
504 return true;
505 }
506
507 bool boolean(bool val)
508 {
509 handle_value(val);
510 return true;
511 }
512
513 bool number_integer(number_integer_t val)
514 {
515 handle_value(val);
516 return true;
517 }
518
519 bool number_unsigned(number_unsigned_t val)
520 {
521 handle_value(val);
522 return true;
523 }
524
525 bool number_float(number_float_t val, const string_t& /*unused*/)
526 {
527 handle_value(val);
528 return true;
529 }
530
531 bool string(string_t& val)
532 {
533 handle_value(val);
534 return true;
535 }
536
537 bool binary(binary_t& val)
538 {
539 handle_value(std::move(val));
540 return true;
541 }
542
543 bool start_object(std::size_t len)
544 {
545 // check callback for object start
546 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
547 keep_stack.push_back(keep);
548
549 auto val = handle_value(BasicJsonType::value_t::object, true);
550 ref_stack.push_back(val.second);
551
552 if (ref_stack.back())
553 {
554
555#if JSON_DIAGNOSTIC_POSITIONS
556 // Manually set the start position of the object here.
557 // Ensure this is after the call to handle_value to ensure correct start position.
558 if (m_lexer_ref)
559 {
560 // Lexer has read the first character of the object, so
561 // subtract 1 from the position to get the correct start position.
562 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
563 }
564#endif
565
566 // check object limit
567 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
568 {
569 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
570 }
571 }
572 return true;
573 }
574
575 bool key(string_t& val)
576 {
577 BasicJsonType k = BasicJsonType(val);
578
579 // check callback for the key
580 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
581 key_keep_stack.push_back(keep);
582
583 // add discarded value at the given key and store the reference for later
584 if (keep && ref_stack.back())
585 {
586 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
587 }
588
589 return true;
590 }
591
592 bool end_object()
593 {
594 if (ref_stack.back())
595 {
596 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
597 {
598 // discard object
599 *ref_stack.back() = discarded;
600
601#if JSON_DIAGNOSTIC_POSITIONS
602 // Set start/end positions for discarded object.
603 handle_diagnostic_positions_for_json_value(*ref_stack.back());
604#endif
605 }
606 else
607 {
608
609#if JSON_DIAGNOSTIC_POSITIONS
610 if (m_lexer_ref)
611 {
612 // Lexer's position is past the closing brace, so set that as the end position.
613 ref_stack.back()->end_position = m_lexer_ref->get_position();
614 }
615#endif
616
617 ref_stack.back()->set_parents();
618 }
619 }
620
621 JSON_ASSERT(!ref_stack.empty());
622 JSON_ASSERT(!keep_stack.empty());
623 ref_stack.pop_back();
624 keep_stack.pop_back();
625
626 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
627 {
628 // remove discarded value
629 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
630 {
631 if (it->is_discarded())
632 {
633 ref_stack.back()->erase(it);
634 break;
635 }
636 }
637 }
638
639 return true;
640 }
641
642 bool start_array(std::size_t len)
643 {
644 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
645 keep_stack.push_back(keep);
646
647 auto val = handle_value(BasicJsonType::value_t::array, true);
648 ref_stack.push_back(val.second);
649
650 if (ref_stack.back())
651 {
652
653#if JSON_DIAGNOSTIC_POSITIONS
654 // Manually set the start position of the array here.
655 // Ensure this is after the call to handle_value to ensure correct start position.
656 if (m_lexer_ref)
657 {
658 // Lexer has read the first character of the array, so
659 // subtract 1 from the position to get the correct start position.
660 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
661 }
662#endif
663
664 // check array limit
665 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
666 {
667 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
668 }
669 }
670
671 return true;
672 }
673
674 bool end_array()
675 {
676 bool keep = true;
677
678 if (ref_stack.back())
679 {
680 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
681 if (keep)
682 {
683
684#if JSON_DIAGNOSTIC_POSITIONS
685 if (m_lexer_ref)
686 {
687 // Lexer's position is past the closing bracket, so set that as the end position.
688 ref_stack.back()->end_position = m_lexer_ref->get_position();
689 }
690#endif
691
692 ref_stack.back()->set_parents();
693 }
694 else
695 {
696 // discard array
697 *ref_stack.back() = discarded;
698
699#if JSON_DIAGNOSTIC_POSITIONS
700 // Set start/end positions for discarded array.
701 handle_diagnostic_positions_for_json_value(*ref_stack.back());
702#endif
703 }
704 }
705
706 JSON_ASSERT(!ref_stack.empty());
707 JSON_ASSERT(!keep_stack.empty());
708 ref_stack.pop_back();
709 keep_stack.pop_back();
710
711 // remove discarded value
712 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
713 {
714 ref_stack.back()->m_data.m_value.array->pop_back();
715 }
716
717 return true;
718 }
719
720 template<class Exception>
721 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
722 const Exception& ex)
723 {
724 errored = true;
725 static_cast<void>(ex);
726 if (allow_exceptions)
727 {
728 JSON_THROW(ex);
729 }
730 return false;
731 }
732
733 constexpr bool is_errored() const
734 {
735 return errored;
736 }
737
738 private:
739
740#if JSON_DIAGNOSTIC_POSITIONS
741 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
742 {
743 if (m_lexer_ref)
744 {
745 // Lexer has read past the current field value, so set the end position to the current position.
746 // The start position will be set below based on the length of the string representation
747 // of the value.
748 v.end_position = m_lexer_ref->get_position();
749
750 switch (v.type())
751 {
752 case value_t::boolean:
753 {
754 // 4 and 5 are the string length of "true" and "false"
755 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
756 break;
757 }
758
759 case value_t::null:
760 {
761 // 4 is the string length of "null"
762 v.start_position = v.end_position - 4;
763 break;
764 }
765
766 case value_t::string:
767 {
768 // include the length of the quotes, which is 2
769 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
770 break;
771 }
772
774 {
775 v.end_position = std::string::npos;
776 v.start_position = v.end_position;
777 break;
778 }
779
780 case value_t::binary:
784 {
785 v.start_position = v.end_position - m_lexer_ref->get_string().size();
786 break;
787 }
788
789 case value_t::object:
790 case value_t::array:
791 {
792 // object and array are handled in start_object() and start_array() handlers
793 // skip setting the values here.
794 break;
795 }
796 default: // LCOV_EXCL_LINE
797 // Handle all possible types discretely, default handler should never be reached.
798 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
799 }
800 }
801 }
802#endif
803
804 /*!
805 @param[in] v value to add to the JSON value we build during parsing
806 @param[in] skip_callback whether we should skip calling the callback
807 function; this is required after start_array() and
808 start_object() SAX events, because otherwise we would call the
809 callback function with an empty array or object, respectively.
810
811 @invariant If the ref stack is empty, then the passed value will be the new
812 root.
813 @invariant If the ref stack contains a value, then it is an array or an
814 object to which we can add elements
815
816 @return pair of boolean (whether value should be kept) and pointer (to the
817 passed value in the ref_stack hierarchy; nullptr if not kept)
818 */
819 template<typename Value>
820 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
821 {
822 JSON_ASSERT(!keep_stack.empty());
823
824 // do not handle this value if we know it would be added to a discarded
825 // container
826 if (!keep_stack.back())
827 {
828 return {false, nullptr};
829 }
830
831 // create value
832 auto value = BasicJsonType(std::forward<Value>(v));
833
834#if JSON_DIAGNOSTIC_POSITIONS
835 handle_diagnostic_positions_for_json_value(value);
836#endif
837
838 // check callback
839 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
840
841 // do not handle this value if we just learnt it shall be discarded
842 if (!keep)
843 {
844 return {false, nullptr};
845 }
846
847 if (ref_stack.empty())
848 {
849 root = std::move(value);
850 return {true, & root};
851 }
852
853 // skip this value if we already decided to skip the parent
854 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
855 if (!ref_stack.back())
856 {
857 return {false, nullptr};
858 }
859
860 // we now only expect arrays and objects
861 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
862
863 // array
864 if (ref_stack.back()->is_array())
865 {
866 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
867 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
868 }
869
870 // object
871 JSON_ASSERT(ref_stack.back()->is_object());
872 // check if we should store an element for the current key
873 JSON_ASSERT(!key_keep_stack.empty());
874 const bool store_element = key_keep_stack.back();
875 key_keep_stack.pop_back();
876
877 if (!store_element)
878 {
879 return {false, nullptr};
880 }
881
882 JSON_ASSERT(object_element);
883 *object_element = std::move(value);
884 return {true, object_element};
885 }
886
887 /// the parsed JSON value
888 BasicJsonType& root;
889 /// stack to model hierarchy of values
890 std::vector<BasicJsonType*> ref_stack {};
891 /// stack to manage which values to keep
892 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
893 /// stack to manage which object keys to keep
894 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
895 /// helper to hold the reference for the next object element
896 BasicJsonType* object_element = nullptr;
897 /// whether a syntax error occurred
898 bool errored = false;
899 /// callback function
900 const parser_callback_t callback = nullptr;
901 /// whether to throw exceptions in case of errors
902 const bool allow_exceptions = true;
903 /// a discarded value for the callback
904 BasicJsonType discarded = BasicJsonType::value_t::discarded;
905 /// the lexer reference to obtain the current position
906 lexer_t* m_lexer_ref = nullptr;
907};
908
909template<typename BasicJsonType>
911{
912 public:
913 using number_integer_t = typename BasicJsonType::number_integer_t;
914 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
915 using number_float_t = typename BasicJsonType::number_float_t;
916 using string_t = typename BasicJsonType::string_t;
917 using binary_t = typename BasicJsonType::binary_t;
918
919 bool null()
920 {
921 return true;
922 }
923
924 bool boolean(bool /*unused*/)
925 {
926 return true;
927 }
928
929 bool number_integer(number_integer_t /*unused*/)
930 {
931 return true;
932 }
933
934 bool number_unsigned(number_unsigned_t /*unused*/)
935 {
936 return true;
937 }
938
939 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
940 {
941 return true;
942 }
943
944 bool string(string_t& /*unused*/)
945 {
946 return true;
947 }
948
949 bool binary(binary_t& /*unused*/)
950 {
951 return true;
952 }
953
954 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
955 {
956 return true;
957 }
958
959 bool key(string_t& /*unused*/)
960 {
961 return true;
962 }
963
964 bool end_object()
965 {
966 return true;
967 }
968
969 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
970 {
971 return true;
972 }
973
974 bool end_array()
975 {
976 return true;
977 }
978
979 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
980 {
981 return false;
982 }
983};
984
985} // namespace detail
986NLOHMANN_JSON_NAMESPACE_END
general exception of the basic_json class
定义 exceptions.hpp:51
定义 json_sax.hpp:911
SAX implementation to create a JSON value from SAX events
定义 json_sax.hpp:168
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
定义 json_sax.hpp:182
lexical analysis
定义 lexer.hpp:113
detail namespace with internal helper functions
定义 from_json.hpp:43
@ value
the parser finished reading a JSON value
定义 parser.hpp:47
@ key
the parser read a key of a value in an object
定义 parser.hpp:45
@ array_end
the parser read ] and finished processing a JSON array
定义 parser.hpp:43
@ array_start
the parser read [ and started to process a JSON array
定义 parser.hpp:41
@ object_start
the parser read { and started to process a JSON object
定义 parser.hpp:37
@ object_end
the parser read } and finished processing a JSON object
定义 parser.hpp:39
@ null
null value
定义 value_t.hpp:55
@ number_integer
number value (signed integer)
定义 value_t.hpp:60
@ boolean
boolean value
定义 value_t.hpp:59
@ discarded
discarded by the parser callback function
定义 value_t.hpp:64
@ binary
binary array (ordered collection of bytes)
定义 value_t.hpp:63
@ object
object (unordered set of name/value pairs)
定义 value_t.hpp:56
@ string
string value
定义 value_t.hpp:58
@ number_float
number value (floating-point)
定义 value_t.hpp:62
@ number_unsigned
number value (unsigned integer)
定义 value_t.hpp:61
@ array
array (ordered collection of values)
定义 value_t.hpp:57
virtual bool string(string_t &val)=0
a string value was read
virtual bool null()=0
a null value was read
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_object()=0
the end of an object was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_array()=0
the end of an array was read
virtual bool key(string_t &val)=0
an object key was read