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