Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:02:18

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