diff --git a/CMakeLists.txt b/CMakeLists.txt index 0404787c..d3b82cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,6 +175,7 @@ set (wsjt_qt_CXXSRCS DXLabSuiteCommanderTransceiver.cpp NetworkMessage.cpp Message.cpp + MessageError.cpp MessageClient.cpp MessageServer.cpp TCPClient.cpp diff --git a/MessageClient.cpp b/MessageClient.cpp index ba3cc2d4..66971009 100644 --- a/MessageClient.cpp +++ b/MessageClient.cpp @@ -10,6 +10,7 @@ #include #include "DriftingDateTime.h" +#include "MessageError.hpp" #include "pimpl_impl.hpp" #include "moc_MessageClient.cpp" @@ -28,14 +29,15 @@ namespace namespace { - // Exception thrown on JSON parsing errors. + // Exception thrown on message parsing errors. - struct parse_error : public std::runtime_error + struct parse_error : public std::system_error { - explicit parse_error(QString const & what) - : std::runtime_error(QString {"json parse error: %1"} - .arg(what) - .toStdString()) + using std::system_error::system_error; + + explicit parse_error(QJsonParseError const & parse) + : parse_error(MessageError::Code::json_parsing_error, + parse.errorString().toStdString()) {} }; @@ -45,11 +47,13 @@ namespace Message parse_message(QByteArray const & datagram) { + using MessageError::Code; + QJsonParseError parse; QJsonDocument document = QJsonDocument::fromJson(datagram, &parse); - if (parse.error) throw parse_error(parse.errorString()); - if (!document.isObject()) throw parse_error("json is not an object"); + if (parse.error) throw parse_error(parse); + if (!document.isObject()) throw parse_error(Code::json_not_an_object); Message message; diff --git a/MessageError.cpp b/MessageError.cpp new file mode 100644 index 00000000..d316f3d2 --- /dev/null +++ b/MessageError.cpp @@ -0,0 +1,51 @@ +#include "MessageError.hpp" + +/******************************************************************************/ +// Private Implementation +/******************************************************************************/ + +#pragma mark Private Implementation + +namespace +{ + const struct final : public std::error_category + { + const char * + name() const noexcept override + { + return "message"; + } + + std::string + message(int const ev) const override + { + using MessageError::Code; + + switch (static_cast(ev)) + { + case Code::json_parsing_error: return "json parsing error"; + case Code::json_not_an_object: return "json not an object"; + + default: return "message error"; + } + } + } + Category; +} + +/******************************************************************************/ +// Private Implementation +/******************************************************************************/ + +#pragma mark - Implementation + +namespace MessageError +{ + std::error_category const & + category() noexcept + { + return Category; + } +} + +/******************************************************************************/ diff --git a/MessageError.hpp b/MessageError.hpp new file mode 100644 index 00000000..8c6a45f5 --- /dev/null +++ b/MessageError.hpp @@ -0,0 +1,41 @@ +#ifndef MESSAGE_ERROR_HPP__ +#define MESSAGE_ERROR_HPP__ + +#include + +namespace MessageError +{ + enum class Code + { + json_parsing_error = -1001, + json_not_an_object = -1002 + }; + + std::error_category const & category() noexcept; +} + +namespace std +{ + template<> + struct is_error_code_enum : public true_type{}; + + template<> + struct is_error_condition_enum : public true_type{}; +} + +namespace MessageError +{ + inline std::error_code + make_error_code(Code const e) noexcept + { + return {static_cast(e), category()}; + } + + inline std::error_condition + make_error_condition(Code const e) noexcept + { + return {static_cast(e), category()}; + } +} + +#endif