json_sax.hpp 30 KB

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