From 25198154badf979b9ddef2882147c3ac7256ebea Mon Sep 17 00:00:00 2001 From: Moritz Bruder Date: Sat, 24 Feb 2018 12:55:08 +0100 Subject: [PATCH] Improve exception error messages * Inherit exceptions from std::runtime_error * Refactor error message functions * Refactor path construction functions * Add path to error messages --- lib/libconfig.h++ | 53 ++++++----- lib/libconfigcpp.c++ | 208 ++++++++++++++++++++++++++----------------- 2 files changed, 157 insertions(+), 104 deletions(-) diff --git a/lib/libconfig.h++ b/lib/libconfig.h++ index 548ce17..b55d238 100644 --- a/lib/libconfig.h++ +++ b/lib/libconfig.h++ @@ -24,7 +24,7 @@ #define __libconfig_hpp #include -#include +#include #include #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) @@ -54,7 +54,15 @@ struct config_setting_t; // fwd decl namespace libconfig { -class LIBCONFIGXX_API ConfigException : public std::exception { }; +struct LIBCONFIGXX_API ConfigException : public std::runtime_error +{ + ConfigException(std::string const &message); + + ConfigException(ConfigException const &other); + ConfigException& operator=(ConfigException const &other); + + virtual ~ConfigException() LIBCONFIGXX_NOEXCEPT; +}; class Setting; // fwd decl class SettingIterator; @@ -62,25 +70,26 @@ class SettingConstIterator; class LIBCONFIGXX_API SettingException : public ConfigException { - public: - SettingException(const Setting &setting); - SettingException(const Setting &setting, int idx); - SettingException(const Setting &setting, const char *name); - SettingException(const char *path); + protected: + + SettingException(char const *messagePrefix, const Setting &setting); + SettingException(char const *messagePrefix, const Setting &setting, int idx); + SettingException(char const *messagePrefix, const Setting &setting, const char *name); + SettingException(char const *messagePrefix, std::string path); + + public: SettingException(const SettingException &other); SettingException& operator=(const SettingException &other); virtual ~SettingException() LIBCONFIGXX_NOEXCEPT; - const char *getPath() const; - - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; + std::string const & getPath() const; private: - char *_path; + std::string _path; }; class LIBCONFIGXX_API SettingTypeException : public SettingException @@ -91,7 +100,9 @@ class LIBCONFIGXX_API SettingTypeException : public SettingException SettingTypeException(const Setting &setting, int idx); SettingTypeException(const Setting &setting, const char *name); - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; + private: + + static const char * const ERROR_PREFIX; }; class LIBCONFIGXX_API SettingRangeException : public SettingException @@ -102,7 +113,9 @@ class LIBCONFIGXX_API SettingRangeException : public SettingException SettingRangeException(const Setting &setting, int idx); SettingRangeException(const Setting &setting, const char *name); - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; + private: + + static const char * const ERROR_PREFIX; }; class LIBCONFIGXX_API SettingNotFoundException : public SettingException @@ -113,7 +126,9 @@ class LIBCONFIGXX_API SettingNotFoundException : public SettingException SettingNotFoundException(const Setting &setting, int idx); SettingNotFoundException(const Setting &setting, const char *name); - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; + private: + + static const char * const ERROR_PREFIX; }; class LIBCONFIGXX_API SettingNameException : public SettingException @@ -121,15 +136,11 @@ class LIBCONFIGXX_API SettingNameException : public SettingException public: SettingNameException(const Setting &setting, const char *name); - - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; }; -class LIBCONFIGXX_API FileIOException : public ConfigException +struct LIBCONFIGXX_API FileIOException : public ConfigException { - public: - - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; + FileIOException(); }; class LIBCONFIGXX_API ParseException : public ConfigException @@ -151,8 +162,6 @@ class LIBCONFIGXX_API ParseException : public ConfigException inline const char *getError() const { return(_error); } - virtual const char *what() const LIBCONFIGXX_NOEXCEPT; - private: const char *_file; diff --git a/lib/libconfigcpp.c++ b/lib/libconfigcpp.c++ index 038f162..7db0397 100644 --- a/lib/libconfigcpp.c++ +++ b/lib/libconfigcpp.c++ @@ -58,8 +58,55 @@ static void __fatal_error_func(const char *message) // --------------------------------------------------------------------------- +ConfigException::ConfigException(std::string const &errorMessage) + : std::runtime_error(errorMessage) +{ +} + +// --------------------------------------------------------------------------- + +ConfigException::ConfigException(ConfigException const &other) + : std::runtime_error(other.what()) +{ +} + +// --------------------------------------------------------------------------- + +ConfigException& ConfigException::operator=(ConfigException const &other) +{ + std::runtime_error::operator=(other); + return(*this); +} + +// --------------------------------------------------------------------------- + +ConfigException::~ConfigException() LIBCONFIGXX_NOEXCEPT +{ +} + +// --------------------------------------------------------------------------- + +static std::string __makeParseExceptionErrorString(const char *file, + int line, + const char *error) +{ + std::stringstream sstr; + + sstr << "Failed parsing: "; + + if (file != 0) + sstr << file << ", "; + + sstr << "at line " << line << ": " << error; + + return sstr.str(); +} + +// --------------------------------------------------------------------------- + ParseException::ParseException(const char *file, int line, const char *error) - : _file(file ? ::strdup(file) : NULL), _line(line), _error(error) + : ConfigException(__makeParseExceptionErrorString(file, line, error)), + _file(file ? ::strdup(file) : NULL), _line(line), _error(error) { } @@ -82,13 +129,6 @@ ParseException::~ParseException() LIBCONFIGXX_NOEXCEPT // --------------------------------------------------------------------------- -const char *ParseException::what() const LIBCONFIGXX_NOEXCEPT -{ - return("ParseException"); -} - -// --------------------------------------------------------------------------- - static int __toTypeCode(Setting::Type type) { int typecode; @@ -136,67 +176,100 @@ static int __toTypeCode(Setting::Type type) // --------------------------------------------------------------------------- -static void __constructPath(const Setting &setting, - std::stringstream &path) +static void __writeSettingPath(const Setting &setting, std::ostream &o) { // head recursion to print path from root to target - if(! setting.isRoot()) { - __constructPath(setting.getParent(), path); - if(path.tellp() > 0) - path << '.'; + const Setting &parent_setting = setting.getParent(); + __writeSettingPath(parent_setting, o); + if (! parent_setting.isRoot()) + o << '.'; const char *name = setting.getName(); + if(name) - path << name; + o << name; else - path << '[' << setting.getIndex() << ']'; + o << '[' << setting.getIndex() << ']'; } } // --------------------------------------------------------------------------- -SettingException::SettingException(const Setting &setting) +static std::string __constructSettingPath(const Setting &setting) { - std::stringstream sstr; - __constructPath(setting, sstr); + std::stringstream ss; + __writeSettingPath(setting, ss); + return ss.str(); +} - _path = ::strdup(sstr.str().c_str()); +// --------------------------------------------------------------------------- + +static std::string __constructSettingPath(const Setting &setting, int idx) +{ + std::stringstream ss; + __writeSettingPath(setting, ss); + ss << ".[" << idx << ']'; + return ss.str(); } // --------------------------------------------------------------------------- -SettingException::SettingException(const Setting &setting, int idx) +static std::string __constructSettingPath(const Setting &setting, const char *name) { - std::stringstream sstr; - __constructPath(setting, sstr); - sstr << ".[" << idx << "]"; + std::stringstream ss; + __writeSettingPath(setting, ss); + ss << '.' << name; + return ss.str(); +} - _path = ::strdup(sstr.str().c_str()); +// --------------------------------------------------------------------------- + +static std::string __constructErrorMessage(char const *messagePrefix, std::string const &path) +{ + std::stringstream ss; + ss << messagePrefix << ": " << path; + return ss.str(); } // --------------------------------------------------------------------------- -SettingException::SettingException(const Setting &setting, const char *name) +SettingException::SettingException(char const *messagePrefix, std::string path) + : ConfigException(__constructErrorMessage(messagePrefix, path)) + , _path(std::move(path)) { - std::stringstream sstr; - __constructPath(setting, sstr); - sstr << '.' << name; +} - _path = ::strdup(sstr.str().c_str()); +// --------------------------------------------------------------------------- + +SettingException::SettingException(char const *messagePrefix, + const Setting &setting) + : SettingException(messagePrefix, __constructSettingPath(setting)) +{ +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(char const *messagePrefix, + const Setting &setting, + int idx) + : SettingException(messagePrefix, __constructSettingPath(setting, idx)) +{ } // --------------------------------------------------------------------------- -SettingException::SettingException(const char *path) +SettingException::SettingException(char const *messagePrefix, + const Setting &setting, + const char *name) + : SettingException(messagePrefix, __constructSettingPath(setting, name)) { - _path = ::strdup(path); } // --------------------------------------------------------------------------- -const char *SettingException::getPath() const +std::string const &SettingException::getPath() const { return(_path); } @@ -205,45 +278,40 @@ const char *SettingException::getPath() const SettingException::SettingException(const SettingException &other) : ConfigException(other) + , _path(other._path) { - _path = ::strdup(other._path); } // --------------------------------------------------------------------------- SettingException &SettingException::operator=(const SettingException &other) { - ::free(_path); - _path = ::strdup(other._path); + ConfigException::operator=(other); + _path = other._path; return(*this); } // --------------------------------------------------------------------------- -const char *SettingException::what() const LIBCONFIGXX_NOEXCEPT +SettingException::~SettingException() LIBCONFIGXX_NOEXCEPT { - return("SettingException"); } // --------------------------------------------------------------------------- -SettingException::~SettingException() LIBCONFIGXX_NOEXCEPT -{ - ::free(_path); -} +const char * const SettingTypeException::ERROR_PREFIX = "Unexpected setting type"; // --------------------------------------------------------------------------- - SettingTypeException::SettingTypeException(const Setting &setting) - : SettingException(setting) + : SettingException(ERROR_PREFIX, setting) { } // --------------------------------------------------------------------------- SettingTypeException::SettingTypeException(const Setting &setting, int idx) - : SettingException(setting, idx) + : SettingException(ERROR_PREFIX, setting, idx) { } @@ -251,28 +319,25 @@ SettingTypeException::SettingTypeException(const Setting &setting, int idx) SettingTypeException::SettingTypeException(const Setting &setting, const char *name) - : SettingException(setting, name) + : SettingException(ERROR_PREFIX, setting, name) { } // --------------------------------------------------------------------------- -const char *SettingTypeException::what() const LIBCONFIGXX_NOEXCEPT -{ - return("SettingTypeException"); -} +const char * const SettingRangeException::ERROR_PREFIX = "Value of setting is out of range"; // --------------------------------------------------------------------------- SettingRangeException::SettingRangeException(const Setting &setting) - : SettingException(setting) + : SettingException(ERROR_PREFIX, setting) { } // --------------------------------------------------------------------------- SettingRangeException::SettingRangeException(const Setting &setting, int idx) - : SettingException(setting, idx) + : SettingException(ERROR_PREFIX, setting, idx) { } @@ -280,22 +345,19 @@ SettingRangeException::SettingRangeException(const Setting &setting, int idx) SettingRangeException::SettingRangeException(const Setting &setting, const char *name) - : SettingException(setting, name) + : SettingException(ERROR_PREFIX, setting, name) { } // --------------------------------------------------------------------------- -const char *SettingRangeException::what() const LIBCONFIGXX_NOEXCEPT -{ - return("SettingRangeException"); -} +const char * const SettingNotFoundException::ERROR_PREFIX = "Setting not found"; // --------------------------------------------------------------------------- SettingNotFoundException::SettingNotFoundException(const Setting &setting, int idx) - : SettingException(setting, idx) + : SettingException(ERROR_PREFIX, setting, idx) { } @@ -303,44 +365,30 @@ SettingNotFoundException::SettingNotFoundException(const Setting &setting, SettingNotFoundException::SettingNotFoundException(const Setting &setting, const char *name) - : SettingException(setting, name) + : SettingException(ERROR_PREFIX, setting, name) { } // --------------------------------------------------------------------------- SettingNotFoundException::SettingNotFoundException(const char *path) - : SettingException(path) + : SettingException(ERROR_PREFIX, path) { } // --------------------------------------------------------------------------- -const char *SettingNotFoundException::what() const LIBCONFIGXX_NOEXCEPT -{ - return("SettingNotFoundException"); -} - -// --------------------------------------------------------------------------- - SettingNameException::SettingNameException(const Setting &setting, const char *name) - : SettingException(setting, name) + : SettingException("Failed adding setting", setting, name) { } // --------------------------------------------------------------------------- -const char *SettingNameException::what() const LIBCONFIGXX_NOEXCEPT +FileIOException::FileIOException() + : ConfigException("File input/output error occured.") { - return("SettingNameException"); -} - -// --------------------------------------------------------------------------- - -const char *FileIOException::what() const LIBCONFIGXX_NOEXCEPT -{ - return("FileIOException"); } // --------------------------------------------------------------------------- @@ -1098,11 +1146,7 @@ const char * Setting::getName() const std::string Setting::getPath() const { - std::stringstream path; - - __constructPath(*this, path); - - return(path.str()); + return __constructSettingPath(*this); } // ---------------------------------------------------------------------------