Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/nlohmann/detail/input/json_sax.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.11.3
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 #pragma once
0010 
0011 #include <cstddef>
0012 #include <string> // string
0013 #include <utility> // move
0014 #include <vector> // vector
0015 
0016 #include <nlohmann/detail/exceptions.hpp>
0017 #include <nlohmann/detail/macro_scope.hpp>
0018 #include <nlohmann/detail/string_concat.hpp>
0019 
0020 NLOHMANN_JSON_NAMESPACE_BEGIN
0021 
0022 /*!
0023 @brief SAX interface
0024 
0025 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
0026 Each function is called in different situations while the input is parsed. The
0027 boolean return value informs the parser whether to continue processing the
0028 input.
0029 */
0030 template<typename BasicJsonType>
0031 struct json_sax
0032 {
0033     using number_integer_t = typename BasicJsonType::number_integer_t;
0034     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0035     using number_float_t = typename BasicJsonType::number_float_t;
0036     using string_t = typename BasicJsonType::string_t;
0037     using binary_t = typename BasicJsonType::binary_t;
0038 
0039     /*!
0040     @brief a null value was read
0041     @return whether parsing should proceed
0042     */
0043     virtual bool null() = 0;
0044 
0045     /*!
0046     @brief a boolean value was read
0047     @param[in] val  boolean value
0048     @return whether parsing should proceed
0049     */
0050     virtual bool boolean(bool val) = 0;
0051 
0052     /*!
0053     @brief an integer number was read
0054     @param[in] val  integer value
0055     @return whether parsing should proceed
0056     */
0057     virtual bool number_integer(number_integer_t val) = 0;
0058 
0059     /*!
0060     @brief an unsigned integer number was read
0061     @param[in] val  unsigned integer value
0062     @return whether parsing should proceed
0063     */
0064     virtual bool number_unsigned(number_unsigned_t val) = 0;
0065 
0066     /*!
0067     @brief a floating-point number was read
0068     @param[in] val  floating-point value
0069     @param[in] s    raw token value
0070     @return whether parsing should proceed
0071     */
0072     virtual bool number_float(number_float_t val, const string_t& s) = 0;
0073 
0074     /*!
0075     @brief a string value was read
0076     @param[in] val  string value
0077     @return whether parsing should proceed
0078     @note It is safe to move the passed string value.
0079     */
0080     virtual bool string(string_t& val) = 0;
0081 
0082     /*!
0083     @brief a binary value was read
0084     @param[in] val  binary value
0085     @return whether parsing should proceed
0086     @note It is safe to move the passed binary value.
0087     */
0088     virtual bool binary(binary_t& val) = 0;
0089 
0090     /*!
0091     @brief the beginning of an object was read
0092     @param[in] elements  number of object elements or -1 if unknown
0093     @return whether parsing should proceed
0094     @note binary formats may report the number of elements
0095     */
0096     virtual bool start_object(std::size_t elements) = 0;
0097 
0098     /*!
0099     @brief an object key was read
0100     @param[in] val  object key
0101     @return whether parsing should proceed
0102     @note It is safe to move the passed string.
0103     */
0104     virtual bool key(string_t& val) = 0;
0105 
0106     /*!
0107     @brief the end of an object was read
0108     @return whether parsing should proceed
0109     */
0110     virtual bool end_object() = 0;
0111 
0112     /*!
0113     @brief the beginning of an array was read
0114     @param[in] elements  number of array elements or -1 if unknown
0115     @return whether parsing should proceed
0116     @note binary formats may report the number of elements
0117     */
0118     virtual bool start_array(std::size_t elements) = 0;
0119 
0120     /*!
0121     @brief the end of an array was read
0122     @return whether parsing should proceed
0123     */
0124     virtual bool end_array() = 0;
0125 
0126     /*!
0127     @brief a parse error occurred
0128     @param[in] position    the position in the input where the error occurs
0129     @param[in] last_token  the last read token
0130     @param[in] ex          an exception object describing the error
0131     @return whether parsing should proceed (must return false)
0132     */
0133     virtual bool parse_error(std::size_t position,
0134                              const std::string& last_token,
0135                              const detail::exception& ex) = 0;
0136 
0137     json_sax() = default;
0138     json_sax(const json_sax&) = default;
0139     json_sax(json_sax&&) noexcept = default;
0140     json_sax& operator=(const json_sax&) = default;
0141     json_sax& operator=(json_sax&&) noexcept = default;
0142     virtual ~json_sax() = default;
0143 };
0144 
0145 namespace detail
0146 {
0147 /*!
0148 @brief SAX implementation to create a JSON value from SAX events
0149 
0150 This class implements the @ref json_sax interface and processes the SAX events
0151 to create a JSON value which makes it basically a DOM parser. The structure or
0152 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
0153 a pointer to the respective array or object for each recursion depth.
0154 
0155 After successful parsing, the value that is passed by reference to the
0156 constructor contains the parsed value.
0157 
0158 @tparam BasicJsonType  the JSON type
0159 */
0160 template<typename BasicJsonType>
0161 class json_sax_dom_parser
0162 {
0163   public:
0164     using number_integer_t = typename BasicJsonType::number_integer_t;
0165     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0166     using number_float_t = typename BasicJsonType::number_float_t;
0167     using string_t = typename BasicJsonType::string_t;
0168     using binary_t = typename BasicJsonType::binary_t;
0169 
0170     /*!
0171     @param[in,out] r  reference to a JSON value that is manipulated while
0172                        parsing
0173     @param[in] allow_exceptions_  whether parse errors yield exceptions
0174     */
0175     explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
0176         : root(r), allow_exceptions(allow_exceptions_)
0177     {}
0178 
0179     // make class move-only
0180     json_sax_dom_parser(const json_sax_dom_parser&) = delete;
0181     json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0182     json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
0183     json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0184     ~json_sax_dom_parser() = default;
0185 
0186     bool null()
0187     {
0188         handle_value(nullptr);
0189         return true;
0190     }
0191 
0192     bool boolean(bool val)
0193     {
0194         handle_value(val);
0195         return true;
0196     }
0197 
0198     bool number_integer(number_integer_t val)
0199     {
0200         handle_value(val);
0201         return true;
0202     }
0203 
0204     bool number_unsigned(number_unsigned_t val)
0205     {
0206         handle_value(val);
0207         return true;
0208     }
0209 
0210     bool number_float(number_float_t val, const string_t& /*unused*/)
0211     {
0212         handle_value(val);
0213         return true;
0214     }
0215 
0216     bool string(string_t& val)
0217     {
0218         handle_value(val);
0219         return true;
0220     }
0221 
0222     bool binary(binary_t& val)
0223     {
0224         handle_value(std::move(val));
0225         return true;
0226     }
0227 
0228     bool start_object(std::size_t len)
0229     {
0230         ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
0231 
0232         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
0233         {
0234             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
0235         }
0236 
0237         return true;
0238     }
0239 
0240     bool key(string_t& val)
0241     {
0242         JSON_ASSERT(!ref_stack.empty());
0243         JSON_ASSERT(ref_stack.back()->is_object());
0244 
0245         // add null at given key and store the reference for later
0246         object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
0247         return true;
0248     }
0249 
0250     bool end_object()
0251     {
0252         JSON_ASSERT(!ref_stack.empty());
0253         JSON_ASSERT(ref_stack.back()->is_object());
0254 
0255         ref_stack.back()->set_parents();
0256         ref_stack.pop_back();
0257         return true;
0258     }
0259 
0260     bool start_array(std::size_t len)
0261     {
0262         ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
0263 
0264         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
0265         {
0266             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
0267         }
0268 
0269         return true;
0270     }
0271 
0272     bool end_array()
0273     {
0274         JSON_ASSERT(!ref_stack.empty());
0275         JSON_ASSERT(ref_stack.back()->is_array());
0276 
0277         ref_stack.back()->set_parents();
0278         ref_stack.pop_back();
0279         return true;
0280     }
0281 
0282     template<class Exception>
0283     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
0284                      const Exception& ex)
0285     {
0286         errored = true;
0287         static_cast<void>(ex);
0288         if (allow_exceptions)
0289         {
0290             JSON_THROW(ex);
0291         }
0292         return false;
0293     }
0294 
0295     constexpr bool is_errored() const
0296     {
0297         return errored;
0298     }
0299 
0300   private:
0301     /*!
0302     @invariant If the ref stack is empty, then the passed value will be the new
0303                root.
0304     @invariant If the ref stack contains a value, then it is an array or an
0305                object to which we can add elements
0306     */
0307     template<typename Value>
0308     JSON_HEDLEY_RETURNS_NON_NULL
0309     BasicJsonType* handle_value(Value&& v)
0310     {
0311         if (ref_stack.empty())
0312         {
0313             root = BasicJsonType(std::forward<Value>(v));
0314             return &root;
0315         }
0316 
0317         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
0318 
0319         if (ref_stack.back()->is_array())
0320         {
0321             ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
0322             return &(ref_stack.back()->m_data.m_value.array->back());
0323         }
0324 
0325         JSON_ASSERT(ref_stack.back()->is_object());
0326         JSON_ASSERT(object_element);
0327         *object_element = BasicJsonType(std::forward<Value>(v));
0328         return object_element;
0329     }
0330 
0331     /// the parsed JSON value
0332     BasicJsonType& root;
0333     /// stack to model hierarchy of values
0334     std::vector<BasicJsonType*> ref_stack {};
0335     /// helper to hold the reference for the next object element
0336     BasicJsonType* object_element = nullptr;
0337     /// whether a syntax error occurred
0338     bool errored = false;
0339     /// whether to throw exceptions in case of errors
0340     const bool allow_exceptions = true;
0341 };
0342 
0343 template<typename BasicJsonType>
0344 class json_sax_dom_callback_parser
0345 {
0346   public:
0347     using number_integer_t = typename BasicJsonType::number_integer_t;
0348     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0349     using number_float_t = typename BasicJsonType::number_float_t;
0350     using string_t = typename BasicJsonType::string_t;
0351     using binary_t = typename BasicJsonType::binary_t;
0352     using parser_callback_t = typename BasicJsonType::parser_callback_t;
0353     using parse_event_t = typename BasicJsonType::parse_event_t;
0354 
0355     json_sax_dom_callback_parser(BasicJsonType& r,
0356                                  const parser_callback_t cb,
0357                                  const bool allow_exceptions_ = true)
0358         : root(r), callback(cb), allow_exceptions(allow_exceptions_)
0359     {
0360         keep_stack.push_back(true);
0361     }
0362 
0363     // make class move-only
0364     json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
0365     json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0366     json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
0367     json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0368     ~json_sax_dom_callback_parser() = default;
0369 
0370     bool null()
0371     {
0372         handle_value(nullptr);
0373         return true;
0374     }
0375 
0376     bool boolean(bool val)
0377     {
0378         handle_value(val);
0379         return true;
0380     }
0381 
0382     bool number_integer(number_integer_t val)
0383     {
0384         handle_value(val);
0385         return true;
0386     }
0387 
0388     bool number_unsigned(number_unsigned_t val)
0389     {
0390         handle_value(val);
0391         return true;
0392     }
0393 
0394     bool number_float(number_float_t val, const string_t& /*unused*/)
0395     {
0396         handle_value(val);
0397         return true;
0398     }
0399 
0400     bool string(string_t& val)
0401     {
0402         handle_value(val);
0403         return true;
0404     }
0405 
0406     bool binary(binary_t& val)
0407     {
0408         handle_value(std::move(val));
0409         return true;
0410     }
0411 
0412     bool start_object(std::size_t len)
0413     {
0414         // check callback for object start
0415         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
0416         keep_stack.push_back(keep);
0417 
0418         auto val = handle_value(BasicJsonType::value_t::object, true);
0419         ref_stack.push_back(val.second);
0420 
0421         // check object limit
0422         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
0423         {
0424             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
0425         }
0426 
0427         return true;
0428     }
0429 
0430     bool key(string_t& val)
0431     {
0432         BasicJsonType k = BasicJsonType(val);
0433 
0434         // check callback for key
0435         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
0436         key_keep_stack.push_back(keep);
0437 
0438         // add discarded value at given key and store the reference for later
0439         if (keep && ref_stack.back())
0440         {
0441             object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
0442         }
0443 
0444         return true;
0445     }
0446 
0447     bool end_object()
0448     {
0449         if (ref_stack.back())
0450         {
0451             if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
0452             {
0453                 // discard object
0454                 *ref_stack.back() = discarded;
0455             }
0456             else
0457             {
0458                 ref_stack.back()->set_parents();
0459             }
0460         }
0461 
0462         JSON_ASSERT(!ref_stack.empty());
0463         JSON_ASSERT(!keep_stack.empty());
0464         ref_stack.pop_back();
0465         keep_stack.pop_back();
0466 
0467         if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
0468         {
0469             // remove discarded value
0470             for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
0471             {
0472                 if (it->is_discarded())
0473                 {
0474                     ref_stack.back()->erase(it);
0475                     break;
0476                 }
0477             }
0478         }
0479 
0480         return true;
0481     }
0482 
0483     bool start_array(std::size_t len)
0484     {
0485         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
0486         keep_stack.push_back(keep);
0487 
0488         auto val = handle_value(BasicJsonType::value_t::array, true);
0489         ref_stack.push_back(val.second);
0490 
0491         // check array limit
0492         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
0493         {
0494             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
0495         }
0496 
0497         return true;
0498     }
0499 
0500     bool end_array()
0501     {
0502         bool keep = true;
0503 
0504         if (ref_stack.back())
0505         {
0506             keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
0507             if (keep)
0508             {
0509                 ref_stack.back()->set_parents();
0510             }
0511             else
0512             {
0513                 // discard array
0514                 *ref_stack.back() = discarded;
0515             }
0516         }
0517 
0518         JSON_ASSERT(!ref_stack.empty());
0519         JSON_ASSERT(!keep_stack.empty());
0520         ref_stack.pop_back();
0521         keep_stack.pop_back();
0522 
0523         // remove discarded value
0524         if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
0525         {
0526             ref_stack.back()->m_data.m_value.array->pop_back();
0527         }
0528 
0529         return true;
0530     }
0531 
0532     template<class Exception>
0533     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
0534                      const Exception& ex)
0535     {
0536         errored = true;
0537         static_cast<void>(ex);
0538         if (allow_exceptions)
0539         {
0540             JSON_THROW(ex);
0541         }
0542         return false;
0543     }
0544 
0545     constexpr bool is_errored() const
0546     {
0547         return errored;
0548     }
0549 
0550   private:
0551     /*!
0552     @param[in] v  value to add to the JSON value we build during parsing
0553     @param[in] skip_callback  whether we should skip calling the callback
0554                function; this is required after start_array() and
0555                start_object() SAX events, because otherwise we would call the
0556                callback function with an empty array or object, respectively.
0557 
0558     @invariant If the ref stack is empty, then the passed value will be the new
0559                root.
0560     @invariant If the ref stack contains a value, then it is an array or an
0561                object to which we can add elements
0562 
0563     @return pair of boolean (whether value should be kept) and pointer (to the
0564             passed value in the ref_stack hierarchy; nullptr if not kept)
0565     */
0566     template<typename Value>
0567     std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
0568     {
0569         JSON_ASSERT(!keep_stack.empty());
0570 
0571         // do not handle this value if we know it would be added to a discarded
0572         // container
0573         if (!keep_stack.back())
0574         {
0575             return {false, nullptr};
0576         }
0577 
0578         // create value
0579         auto value = BasicJsonType(std::forward<Value>(v));
0580 
0581         // check callback
0582         const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0583 
0584         // do not handle this value if we just learnt it shall be discarded
0585         if (!keep)
0586         {
0587             return {false, nullptr};
0588         }
0589 
0590         if (ref_stack.empty())
0591         {
0592             root = std::move(value);
0593             return {true, & root};
0594         }
0595 
0596         // skip this value if we already decided to skip the parent
0597         // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0598         if (!ref_stack.back())
0599         {
0600             return {false, nullptr};
0601         }
0602 
0603         // we now only expect arrays and objects
0604         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
0605 
0606         // array
0607         if (ref_stack.back()->is_array())
0608         {
0609             ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
0610             return {true, & (ref_stack.back()->m_data.m_value.array->back())};
0611         }
0612 
0613         // object
0614         JSON_ASSERT(ref_stack.back()->is_object());
0615         // check if we should store an element for the current key
0616         JSON_ASSERT(!key_keep_stack.empty());
0617         const bool store_element = key_keep_stack.back();
0618         key_keep_stack.pop_back();
0619 
0620         if (!store_element)
0621         {
0622             return {false, nullptr};
0623         }
0624 
0625         JSON_ASSERT(object_element);
0626         *object_element = std::move(value);
0627         return {true, object_element};
0628     }
0629 
0630     /// the parsed JSON value
0631     BasicJsonType& root;
0632     /// stack to model hierarchy of values
0633     std::vector<BasicJsonType*> ref_stack {};
0634     /// stack to manage which values to keep
0635     std::vector<bool> keep_stack {};
0636     /// stack to manage which object keys to keep
0637     std::vector<bool> key_keep_stack {};
0638     /// helper to hold the reference for the next object element
0639     BasicJsonType* object_element = nullptr;
0640     /// whether a syntax error occurred
0641     bool errored = false;
0642     /// callback function
0643     const parser_callback_t callback = nullptr;
0644     /// whether to throw exceptions in case of errors
0645     const bool allow_exceptions = true;
0646     /// a discarded value for the callback
0647     BasicJsonType discarded = BasicJsonType::value_t::discarded;
0648 };
0649 
0650 template<typename BasicJsonType>
0651 class json_sax_acceptor
0652 {
0653   public:
0654     using number_integer_t = typename BasicJsonType::number_integer_t;
0655     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0656     using number_float_t = typename BasicJsonType::number_float_t;
0657     using string_t = typename BasicJsonType::string_t;
0658     using binary_t = typename BasicJsonType::binary_t;
0659 
0660     bool null()
0661     {
0662         return true;
0663     }
0664 
0665     bool boolean(bool /*unused*/)
0666     {
0667         return true;
0668     }
0669 
0670     bool number_integer(number_integer_t /*unused*/)
0671     {
0672         return true;
0673     }
0674 
0675     bool number_unsigned(number_unsigned_t /*unused*/)
0676     {
0677         return true;
0678     }
0679 
0680     bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
0681     {
0682         return true;
0683     }
0684 
0685     bool string(string_t& /*unused*/)
0686     {
0687         return true;
0688     }
0689 
0690     bool binary(binary_t& /*unused*/)
0691     {
0692         return true;
0693     }
0694 
0695     bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
0696     {
0697         return true;
0698     }
0699 
0700     bool key(string_t& /*unused*/)
0701     {
0702         return true;
0703     }
0704 
0705     bool end_object()
0706     {
0707         return true;
0708     }
0709 
0710     bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
0711     {
0712         return true;
0713     }
0714 
0715     bool end_array()
0716     {
0717         return true;
0718     }
0719 
0720     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
0721     {
0722         return false;
0723     }
0724 };
0725 
0726 }  // namespace detail
0727 NLOHMANN_JSON_NAMESPACE_END