🔨 cleaner exception interface

parent ad47b0fb
...@@ -147,8 +147,7 @@ class binary_reader ...@@ -147,8 +147,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
// Integer 0x00..0x17 (0..23) // Integer 0x00..0x17 (0..23)
case 0x00: case 0x00:
...@@ -399,7 +398,7 @@ class binary_reader ...@@ -399,7 +398,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str())); return sax->parse_error(chars_read, ss.str(), parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
} }
} }
} }
...@@ -410,8 +409,7 @@ class binary_reader ...@@ -410,8 +409,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
// positive fixint // positive fixint
case 0x00: case 0x00:
...@@ -712,8 +710,7 @@ class binary_reader ...@@ -712,8 +710,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(112, chars_read, return sax->parse_error(chars_read, ss.str(), parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + ss.str()));
"error reading MessagePack; last byte: 0x" + ss.str()));
} }
} }
} }
...@@ -1189,8 +1186,7 @@ class binary_reader ...@@ -1189,8 +1186,7 @@ class binary_reader
switch (prefix) switch (prefix)
{ {
case std::char_traits<char>::eof(): // EOF case std::char_traits<char>::eof(): // EOF
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
case 'T': // true case 'T': // true
return sax->boolean(true); return sax->boolean(true);
...@@ -1223,8 +1219,7 @@ class binary_reader ...@@ -1223,8 +1219,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(113, chars_read, return sax->parse_error(chars_read, ss.str(), parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
"byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
} }
return sax->string(string_t(1, static_cast<char>(current))); return sax->string(string_t(1, static_cast<char>(current)));
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <nlohmann/detail/exceptions.hpp>
namespace nlohmann namespace nlohmann
{ {
...@@ -118,7 +120,7 @@ struct json_sax ...@@ -118,7 +120,7 @@ struct json_sax
*/ */
virtual bool parse_error(std::size_t position, virtual bool parse_error(std::size_t position,
const std::string& last_token, const std::string& last_token,
const std::string& error_msg) = 0; const detail::exception& ex) = 0;
virtual ~json_sax() = default; virtual ~json_sax() = default;
}; };
...@@ -224,19 +226,27 @@ class json_sax_dom_parser : public json_sax<BasicJsonType> ...@@ -224,19 +226,27 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true; return true;
} }
bool parse_error(std::size_t position, const std::string& token, bool parse_error(std::size_t, const std::string&,
const std::string& error_msg) override const detail::exception& ex) override
{ {
errored = true; errored = true;
if (allow_exceptions) if (allow_exceptions)
{ {
if (error_msg == "number overflow") // determine the proper exception type from the id
{ switch ((ex.id / 100) % 100)
JSON_THROW(BasicJsonType::out_of_range::create(406, "number overflow parsing '" + token + "'"));
}
else
{ {
JSON_THROW(BasicJsonType::parse_error::create(101, position, error_msg)); case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
default:
assert(false); // LCOV_EXCL_LINE
} }
} }
return false; return false;
...@@ -359,7 +369,7 @@ class json_sax_acceptor : public json_sax<BasicJsonType> ...@@ -359,7 +369,7 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
return true; return true;
} }
bool parse_error(std::size_t, const std::string&, const std::string&) override bool parse_error(std::size_t, const std::string&, const detail::exception&) override
{ {
return false; return false;
} }
......
...@@ -117,7 +117,7 @@ class parser ...@@ -117,7 +117,7 @@ class parser
{ {
sdp.parse_error(m_lexer.get_position(), sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_of_input)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
} }
// in case of an error, return discarded value // in case of an error, return discarded value
...@@ -456,7 +456,7 @@ class parser ...@@ -456,7 +456,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::value_string)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
} }
else else
{ {
...@@ -472,7 +472,7 @@ class parser ...@@ -472,7 +472,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::name_separator)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
} }
// parse value // parse value
...@@ -499,7 +499,8 @@ class parser ...@@ -499,7 +499,8 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_object)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
} }
} }
} }
...@@ -546,7 +547,7 @@ class parser ...@@ -546,7 +547,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_array)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
} }
} }
} }
...@@ -559,7 +560,7 @@ class parser ...@@ -559,7 +560,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
"number overflow"); out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
} }
else else
{ {
...@@ -602,14 +603,14 @@ class parser ...@@ -602,14 +603,14 @@ class parser
// using "uninitialized" to avoid "expected" message // using "uninitialized" to avoid "expected" message
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::uninitialized)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
} }
default: // the last token was unexpected default: // the last token was unexpected
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::literal_or_value)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
} }
} }
} }
......
...@@ -3138,6 +3138,9 @@ scan_number_done: ...@@ -3138,6 +3138,9 @@ scan_number_done:
#include <string> #include <string>
#include <vector> #include <vector>
// #include <nlohmann/detail/exceptions.hpp>
namespace nlohmann namespace nlohmann
{ {
...@@ -3252,7 +3255,7 @@ struct json_sax ...@@ -3252,7 +3255,7 @@ struct json_sax
*/ */
virtual bool parse_error(std::size_t position, virtual bool parse_error(std::size_t position,
const std::string& last_token, const std::string& last_token,
const std::string& error_msg) = 0; const detail::exception& ex) = 0;
virtual ~json_sax() = default; virtual ~json_sax() = default;
}; };
...@@ -3358,19 +3361,27 @@ class json_sax_dom_parser : public json_sax<BasicJsonType> ...@@ -3358,19 +3361,27 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true; return true;
} }
bool parse_error(std::size_t position, const std::string& token, bool parse_error(std::size_t, const std::string&,
const std::string& error_msg) override const detail::exception& ex) override
{ {
errored = true; errored = true;
if (allow_exceptions) if (allow_exceptions)
{ {
if (error_msg == "number overflow") // determine the proper exception type from the id
{ switch ((ex.id / 100) % 100)
JSON_THROW(BasicJsonType::out_of_range::create(406, "number overflow parsing '" + token + "'")); {
} case 1:
else JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
{ case 2:
JSON_THROW(BasicJsonType::parse_error::create(101, position, error_msg)); JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
default:
assert(false); // LCOV_EXCL_LINE
} }
} }
return false; return false;
...@@ -3493,7 +3504,7 @@ class json_sax_acceptor : public json_sax<BasicJsonType> ...@@ -3493,7 +3504,7 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
return true; return true;
} }
bool parse_error(std::size_t, const std::string&, const std::string&) override bool parse_error(std::size_t, const std::string&, const detail::exception&) override
{ {
return false; return false;
} }
...@@ -3611,7 +3622,7 @@ class parser ...@@ -3611,7 +3622,7 @@ class parser
{ {
sdp.parse_error(m_lexer.get_position(), sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_of_input)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
} }
// in case of an error, return discarded value // in case of an error, return discarded value
...@@ -3950,7 +3961,7 @@ class parser ...@@ -3950,7 +3961,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::value_string)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
} }
else else
{ {
...@@ -3966,7 +3977,7 @@ class parser ...@@ -3966,7 +3977,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::name_separator)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
} }
// parse value // parse value
...@@ -3993,7 +4004,8 @@ class parser ...@@ -3993,7 +4004,8 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_object)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
} }
} }
} }
...@@ -4040,7 +4052,7 @@ class parser ...@@ -4040,7 +4052,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::end_array)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
} }
} }
} }
...@@ -4053,7 +4065,7 @@ class parser ...@@ -4053,7 +4065,7 @@ class parser
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
"number overflow"); out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
} }
else else
{ {
...@@ -4096,14 +4108,14 @@ class parser ...@@ -4096,14 +4108,14 @@ class parser
// using "uninitialized" to avoid "expected" message // using "uninitialized" to avoid "expected" message
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::uninitialized)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
} }
default: // the last token was unexpected default: // the last token was unexpected
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
exception_message(token_type::literal_or_value)); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
} }
} }
} }
...@@ -5437,8 +5449,7 @@ class binary_reader ...@@ -5437,8 +5449,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
// Integer 0x00..0x17 (0..23) // Integer 0x00..0x17 (0..23)
case 0x00: case 0x00:
...@@ -5689,7 +5700,7 @@ class binary_reader ...@@ -5689,7 +5700,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str())); return sax->parse_error(chars_read, ss.str(), parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
} }
} }
} }
...@@ -5700,8 +5711,7 @@ class binary_reader ...@@ -5700,8 +5711,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
// positive fixint // positive fixint
case 0x00: case 0x00:
...@@ -6002,8 +6012,7 @@ class binary_reader ...@@ -6002,8 +6012,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(112, chars_read, return sax->parse_error(chars_read, ss.str(), parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + ss.str()));
"error reading MessagePack; last byte: 0x" + ss.str()));
} }
} }
} }
...@@ -6479,8 +6488,7 @@ class binary_reader ...@@ -6479,8 +6488,7 @@ class binary_reader
switch (prefix) switch (prefix)
{ {
case std::char_traits<char>::eof(): // EOF case std::char_traits<char>::eof(): // EOF
unexpect_eof(); return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
return sax->parse_error(chars_read, "<end of file>", "unexpected end of input");
case 'T': // true case 'T': // true
return sax->boolean(true); return sax->boolean(true);
...@@ -6513,8 +6521,7 @@ class binary_reader ...@@ -6513,8 +6521,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create(113, chars_read, return sax->parse_error(chars_read, ss.str(), parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
"byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
} }
return sax->string(string_t(1, static_cast<char>(current))); return sax->string(string_t(1, static_cast<char>(current)));
} }
......
...@@ -123,7 +123,7 @@ class SaxEventLogger : public nlohmann::json::json_sax_t ...@@ -123,7 +123,7 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
return true; return true;
} }
bool parse_error(std::size_t position, const std::string&, const std::string&) override bool parse_error(std::size_t position, const std::string&, const json::exception&) override
{ {
errored = true; errored = true;
events.push_back("parse_error(" + std::to_string(position) + ")"); events.push_back("parse_error(" + std::to_string(position) + ")");
......
...@@ -122,7 +122,7 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t ...@@ -122,7 +122,7 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
return true; return true;
} }
bool parse_error(std::size_t position, const std::string&, const std::string&) override bool parse_error(std::size_t position, const std::string&, const json::exception&) override
{ {
events.push_back("parse_error(" + std::to_string(position) + ")"); events.push_back("parse_error(" + std::to_string(position) + ")");
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment