From e5f84e1ebfa31855e4c6ba42c4ccf79ed2e9300e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 19 Aug 2026 22:50:21 +0200 Subject: [PATCH] refactor: split the strict and non-strict paths in parser Folding the release_lookahead() call into the existing strict check left the "in strict mode" comment on an else-if branch, and made the strict condition in sax_parse() redundant with the branch it followed. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/input/parser.hpp | 68 ++++++++++++++---------- single_include/nlohmann/json.hpp | 68 ++++++++++++++---------- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index 0b40fcc83..ee0de4616 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -99,20 +99,23 @@ class parser json_sax_dom_callback_parser sdp(result, callback, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); - if (!strict) + if (strict) + { + // in strict mode, input must be completely read + if (get_token() != token_type::end_of_input) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else { // the caller keeps using the input: position it right after // the value by leaving the character that terminated it m_lexer.release_lookahead(); } - // in strict mode, input must be completely read - else if (get_token() != token_type::end_of_input) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"), nullptr)); - } // in case of an error, return a discarded value if (sdp.is_errored()) @@ -133,18 +136,21 @@ class parser json_sax_dom_parser sdp(result, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); - if (!strict) + if (strict) + { + // in strict mode, input must be completely read + if (get_token() != token_type::end_of_input) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else { // see above m_lexer.release_lookahead(); } - // in strict mode, input must be completely read - else if (get_token() != token_type::end_of_input) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); - } // in case of an error, return a discarded value if (sdp.is_errored()) @@ -176,18 +182,24 @@ class parser (void)detail::is_sax_static_asserts {}; const bool result = sax_parse_internal(sax); - if (result && !strict) + if (result) { - // the caller keeps using the input: position it right after the - // value by leaving the character that terminated it - m_lexer.release_lookahead(); - } - // strict mode: next byte must be EOF - else if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + if (strict) + { + // strict mode: next byte must be EOF + if (get_token() != token_type::end_of_input) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else + { + // the caller keeps using the input: position it right after + // the value by leaving the character that terminated it + m_lexer.release_lookahead(); + } } return result; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 8b7d94f69..0cbf9a339 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -14115,20 +14115,23 @@ class parser json_sax_dom_callback_parser sdp(result, callback, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); - if (!strict) + if (strict) + { + // in strict mode, input must be completely read + if (get_token() != token_type::end_of_input) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else { // the caller keeps using the input: position it right after // the value by leaving the character that terminated it m_lexer.release_lookahead(); } - // in strict mode, input must be completely read - else if (get_token() != token_type::end_of_input) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"), nullptr)); - } // in case of an error, return a discarded value if (sdp.is_errored()) @@ -14149,18 +14152,21 @@ class parser json_sax_dom_parser sdp(result, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); - if (!strict) + if (strict) + { + // in strict mode, input must be completely read + if (get_token() != token_type::end_of_input) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else { // see above m_lexer.release_lookahead(); } - // in strict mode, input must be completely read - else if (get_token() != token_type::end_of_input) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); - } // in case of an error, return a discarded value if (sdp.is_errored()) @@ -14192,18 +14198,24 @@ class parser (void)detail::is_sax_static_asserts {}; const bool result = sax_parse_internal(sax); - if (result && !strict) + if (result) { - // the caller keeps using the input: position it right after the - // value by leaving the character that terminated it - m_lexer.release_lookahead(); - } - // strict mode: next byte must be EOF - else if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + if (strict) + { + // strict mode: next byte must be EOF + if (get_token() != token_type::end_of_input) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + } + else + { + // the caller keeps using the input: position it right after + // the value by leaving the character that terminated it + m_lexer.release_lookahead(); + } } return result;