From 99687f367de9d7f399a27e4881d9a3488e6aa90a Mon Sep 17 00:00:00 2001 From: Florian Albrechtskirchinger Date: Fri, 4 Mar 2022 08:42:57 +0100 Subject: [PATCH 1/2] Provide exception overloads without context parameter Provide overloads for static exception create() member functions without const BasicJsonType &context parameter. --- include/nlohmann/detail/exceptions.hpp | 58 +++++++++++++++--- single_include/nlohmann/json.hpp | 82 ++++++++++++++++++++------ 2 files changed, 114 insertions(+), 26 deletions(-) diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index b4b1804963..962bae0b31 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -124,21 +124,26 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + return create(id_, pos, what_arg, {}); + } + template static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + exception::diagnostics(context) + what_arg; - return {id_, pos.chars_read_total, w.c_str()}; + return create(id_, pos, what_arg, exception::diagnostics(context)); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + return create(id_, byte_, what_arg, {}); } template static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + exception::diagnostics(context) + what_arg; - return {id_, byte_, w.c_str()}; + return create(id_, byte_, what_arg, exception::diagnostics(context)); } /*! @@ -156,6 +161,21 @@ class parse_error : public exception parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_) {} + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const std::string& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + context + what_arg; + return {id_, pos.chars_read_total, w.c_str()}; + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const std::string& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + context + what_arg; + return {id_, byte_, w.c_str()}; + } + static std::string position_string(const position_t& pos) { return " at line " + std::to_string(pos.lines_read + 1) + @@ -168,6 +188,12 @@ class parse_error : public exception class invalid_iterator : public exception { public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return {id_, w.c_str()}; + } + template static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -186,6 +212,12 @@ class invalid_iterator : public exception class type_error : public exception { public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return {id_, w.c_str()}; + } + template static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -203,6 +235,12 @@ class type_error : public exception class out_of_range : public exception { public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return {id_, w.c_str()}; + } + template static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -220,6 +258,12 @@ class out_of_range : public exception class other_error : public exception { public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return {id_, w.c_str()}; + } + template static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e40e3b05bd..76948c22cb 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2918,21 +2918,26 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + return create(id_, pos, what_arg, {}); + } + template static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + exception::diagnostics(context) + what_arg; - return {id_, pos.chars_read_total, w.c_str()}; + return create(id_, pos, what_arg, exception::diagnostics(context)); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + return create(id_, byte_, what_arg, {}); } template static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + exception::diagnostics(context) + what_arg; - return {id_, byte_, w.c_str()}; + return create(id_, byte_, what_arg, exception::diagnostics(context)); } /*! @@ -2950,6 +2955,21 @@ class parse_error : public exception parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_) {} + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const std::string& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + context + what_arg; + return {id_, pos.chars_read_total, w.c_str()}; + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const std::string& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + context + what_arg; + return {id_, byte_, w.c_str()}; + } + static std::string position_string(const position_t& pos) { return " at line " + std::to_string(pos.lines_read + 1) + @@ -2962,6 +2982,12 @@ class parse_error : public exception class invalid_iterator : public exception { public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return {id_, w.c_str()}; + } + template static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -2980,6 +3006,12 @@ class invalid_iterator : public exception class type_error : public exception { public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return {id_, w.c_str()}; + } + template static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -2997,6 +3029,12 @@ class type_error : public exception class out_of_range : public exception { public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return {id_, w.c_str()}; + } + template static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -3014,6 +3052,12 @@ class out_of_range : public exception class other_error : public exception { public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return {id_, w.c_str()}; + } + template static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) { @@ -12364,7 +12408,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } reference_tokens.pop_back(); @@ -12376,7 +12420,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } return reference_tokens.back(); @@ -12421,13 +12465,13 @@ class json_pointer // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); } std::size_t processed_chars = 0; @@ -12438,20 +12482,20 @@ class json_pointer } JSON_CATCH(std::out_of_range&) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // check if the string was completely read if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE } return static_cast(res); @@ -12462,7 +12506,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -12879,7 +12923,7 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'")); } // extract the reference tokens: @@ -12914,7 +12958,7 @@ class json_pointer (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); } } @@ -16552,7 +16596,7 @@ class serializer { case error_handler_t::strict: { - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0), BasicJsonType())); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0))); } case error_handler_t::ignore: @@ -16644,7 +16688,7 @@ class serializer { case error_handler_t::strict: { - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)), BasicJsonType())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)))); } case error_handler_t::ignore: From 698ccc44bbd7784101d1b10c94fb9c79e80ca2ff Mon Sep 17 00:00:00 2001 From: Florian Albrechtskirchinger Date: Fri, 4 Mar 2022 08:50:23 +0100 Subject: [PATCH 2/2] Remove exception context where unnecessary --- include/nlohmann/detail/json_pointer.hpp | 20 +++++++++---------- include/nlohmann/detail/output/serializer.hpp | 4 ++-- include/nlohmann/json.hpp | 6 +++--- single_include/nlohmann/json.hpp | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index caed67c9e7..f855a1989e 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -118,7 +118,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } reference_tokens.pop_back(); @@ -130,7 +130,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } return reference_tokens.back(); @@ -175,13 +175,13 @@ class json_pointer // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); } std::size_t processed_chars = 0; @@ -192,20 +192,20 @@ class json_pointer } JSON_CATCH(std::out_of_range&) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // check if the string was completely read if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE } return static_cast(res); @@ -216,7 +216,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -633,7 +633,7 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'")); } // extract the reference tokens: @@ -668,7 +668,7 @@ class json_pointer (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); } } diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index e475ef959d..5b24f03077 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -500,7 +500,7 @@ class serializer { case error_handler_t::strict: { - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0), BasicJsonType())); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0))); } case error_handler_t::ignore: @@ -592,7 +592,7 @@ class serializer { case error_handler_t::strict: { - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)), BasicJsonType())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)))); } case error_handler_t::ignore: diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index a79be2dbd2..2bca40ca8b 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -520,7 +520,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5")); // LCOV_EXCL_LINE } break; } @@ -918,7 +918,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // if object is wanted but impossible, throw an exception if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) { - JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); } } @@ -1030,7 +1030,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); } // copy type from first iterator diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 76948c22cb..645e6a2f5c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -17744,7 +17744,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5")); // LCOV_EXCL_LINE } break; } @@ -18142,7 +18142,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // if object is wanted but impossible, throw an exception if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) { - JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); } } @@ -18254,7 +18254,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); } // copy type from first iterator