LCOV - code coverage report
Current view: top level - home/lbartoletti/qgis/external/nlohmann/detail/input - json_sax.hpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 191 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

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

Generated by: LCOV version 1.14