Add sg_location to all exceptions, add report flag

Move sg_location member up to the base clase, since it’s potentially
useful in more types.

Allow suppression of the report callback when the exception is thrown
This commit is contained in:
James Turner 2021-02-19 17:38:03 +00:00 committed by James Turner
parent fe96298be5
commit 0ddd3e7f2f
2 changed files with 173 additions and 216 deletions

View File

@ -19,66 +19,65 @@ static ThrowCallback static_callback;
// Implementation of sg_location class. // Implementation of sg_location class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_location::sg_location () sg_location::sg_location() noexcept
: _line(-1), : _line(-1),
_column(-1), _column(-1),
_byte(-1) _byte(-1)
{ {
_path[0] = '\0'; _path[0] = '\0';
} }
sg_location::sg_location (const std::string& path, int line, int column) sg_location::sg_location(const std::string& path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path.c_str()); setPath(path.c_str());
} }
sg_location::sg_location (const SGPath& path, int line, int column) sg_location::sg_location(const SGPath& path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path.utf8Str().c_str()); setPath(path.utf8Str().c_str());
} }
sg_location::sg_location (const char* path, int line, int column) sg_location::sg_location(const char* path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path); setPath(path);
} }
void sg_location::setPath(const char *path) { void sg_location::setPath(const char* path) noexcept
if (path) { {
strncpy(_path, path, max_path); if (path) {
_path[max_path -1] = '\0'; strncpy(_path, path, max_path);
} else { _path[max_path - 1] = '\0';
_path[0] = '\0'; } else {
} _path[0] = '\0';
}
} }
const char *sg_location::getPath() const { return _path; } const char* sg_location::getPath() const noexcept { return _path; }
int sg_location::getLine() const { return _line; } int sg_location::getLine() const noexcept { return _line; }
int int sg_location::getColumn() const noexcept
sg_location::getColumn () const
{ {
return _column; return _column;
} }
int int sg_location::getByte() const noexcept
sg_location::getByte () const
{ {
return _byte; return _byte;
} }
std::string std::string
sg_location::asString () const sg_location::asString() const noexcept
{ {
std::ostringstream out; std::ostringstream out;
if (_path[0]) { if (_path[0]) {
@ -97,46 +96,48 @@ sg_location::asString () const
return out.str(); return out.str();
} }
bool sg_location::isValid() const { return strlen(_path) > 0; } bool sg_location::isValid() const noexcept { return strlen(_path) > 0; }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_throwable class. // Implementation of sg_throwable class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_throwable::sg_throwable () sg_throwable::sg_throwable() noexcept
{ {
_message[0] = '\0'; _message[0] = '\0';
_origin[0] = '\0'; _origin[0] = '\0';
} }
sg_throwable::sg_throwable(const char *message, const char *origin, sg_throwable::sg_throwable(const char* message, const char* origin,
const sg_location &loc) { const sg_location& loc, bool report) noexcept : _location(loc)
setMessage(message);
setOrigin(origin);
if (static_callback) {
static_callback(_message, _origin, loc);
}
}
sg_throwable::~sg_throwable ()
{ {
setMessage(message);
setOrigin(origin);
if (static_callback && report) {
static_callback(_message, _origin, loc);
}
} }
const char* const char*
sg_throwable::getMessage () const sg_throwable::getMessage() const noexcept
{ {
return _message; return _message;
} }
const std::string std::string
sg_throwable::getFormattedMessage () const sg_throwable::getFormattedMessage() const noexcept
{ {
return std::string(getMessage()); std::string ret = getMessage();
const std::string loc = getLocation().asString();
if (loc.length()) {
ret += "\n at ";
ret += loc;
}
return ret;
} }
void void sg_throwable::setMessage(const char* message) noexcept
sg_throwable::setMessage (const char* message)
{ {
strncpy(_message, message, MAX_TEXT_LEN); strncpy(_message, message, MAX_TEXT_LEN);
_message[MAX_TEXT_LEN - 1] = '\0'; _message[MAX_TEXT_LEN - 1] = '\0';
@ -144,13 +145,12 @@ sg_throwable::setMessage (const char* message)
} }
const char* const char*
sg_throwable::getOrigin () const sg_throwable::getOrigin() const noexcept
{ {
return _origin; return _origin;
} }
void void sg_throwable::setOrigin(const char* origin) noexcept
sg_throwable::setOrigin (const char* origin)
{ {
if (origin) { if (origin) {
strncpy(_origin, origin, MAX_TEXT_LEN); strncpy(_origin, origin, MAX_TEXT_LEN);
@ -170,27 +170,27 @@ const char* sg_throwable::what() const noexcept
} }
} }
sg_location sg_throwable::getLocation() const noexcept
{
return _location;
}
void sg_throwable::setLocation(const sg_location& location) noexcept
{
_location = location;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_error class. // Implementation of sg_error class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_error::sg_error () sg_error::sg_error(const char* message, const char* origin, bool report) noexcept
: sg_throwable () : sg_throwable(message, origin, {}, report)
{ {
} }
sg_error::sg_error (const char* message, const char *origin) sg_error::sg_error(const std::string& message, const std::string& origin, bool report) noexcept
: sg_throwable(message, origin) : sg_throwable(message.c_str(), origin.c_str(), {}, report)
{
}
sg_error::sg_error(const std::string& message, const std::string& origin)
: sg_throwable(message.c_str(), origin.c_str())
{
}
sg_error::~sg_error ()
{ {
} }
@ -198,121 +198,81 @@ sg_error::~sg_error ()
// Implementation of sg_exception class. // Implementation of sg_exception class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_exception::sg_exception () sg_exception::sg_exception(const char* message, const char* origin,
: sg_throwable () const sg_location& loc, bool report) noexcept
{ : sg_throwable(message, origin, loc, report) {}
}
sg_exception::sg_exception(const char *message, const char *origin, sg_exception::sg_exception(const std::string& message,
const sg_location &loc) const std::string& origin, const sg_location& loc,
: sg_throwable(message, origin, loc) {} bool report) noexcept
: sg_throwable(message.c_str(), origin.c_str(), loc, report) {}
sg_exception::sg_exception(const std::string &message,
const std::string &origin, const sg_location &loc)
: sg_throwable(message.c_str(), origin.c_str(), loc) {}
sg_exception::~sg_exception ()
{
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_io_exception. // Implementation of sg_io_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_io_exception::sg_io_exception () sg_io_exception::sg_io_exception(const char* message, const char* origin, bool report)
: sg_exception() : sg_exception(message, origin, {}, report)
{ {
} }
sg_io_exception::sg_io_exception (const char* message, const char* origin) sg_io_exception::sg_io_exception(const char* message,
: sg_exception(message, origin) const sg_location& location,
const char* origin,
bool report)
: sg_exception(message, origin, location, report) {}
sg_io_exception::sg_io_exception(const std::string& message,
const std::string& origin,
bool report)
: sg_exception(message, origin, {}, report)
{ {
} }
sg_io_exception::sg_io_exception(const char *message, sg_io_exception::sg_io_exception(const std::string& message,
const sg_location &location, const sg_location& location,
const char *origin) const std::string& origin,
: sg_exception(message, origin, location), _location(location) {} bool report)
: sg_exception(message, origin, location, report) {}
sg_io_exception::sg_io_exception( const std::string& message,
const std::string& origin )
: sg_exception(message, origin)
{
}
sg_io_exception::sg_io_exception(const std::string &message,
const sg_location &location,
const std::string &origin)
: sg_exception(message, origin, location), _location(location) {}
sg_io_exception::~sg_io_exception ()
{
}
const std::string
sg_io_exception::getFormattedMessage () const
{
std::string ret = getMessage();
std::string loc = getLocation().asString();
if (loc.length()) {
ret += "\n at ";
ret += loc;
}
return ret;
}
const sg_location &
sg_io_exception::getLocation () const
{
return _location;
}
void
sg_io_exception::setLocation (const sg_location &location)
{
_location = location;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_format_exception. // Implementation of sg_format_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_format_exception::sg_format_exception () sg_format_exception::sg_format_exception() noexcept
: sg_exception() : sg_exception()
{ {
_text[0] = '\0'; _text[0] = '\0';
} }
sg_format_exception::sg_format_exception (const char* message, sg_format_exception::sg_format_exception(const char* message,
const char* text, const char* text,
const char* origin) const char* origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
setText(text); setText(text);
} }
sg_format_exception::sg_format_exception( const std::string& message, sg_format_exception::sg_format_exception(const std::string& message,
const std::string& text, const std::string& text,
const std::string& origin ) const std::string& origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
setText(text.c_str()); setText(text.c_str());
} }
sg_format_exception::~sg_format_exception ()
{
}
const char* const char*
sg_format_exception::getText () const sg_format_exception::getText() const noexcept
{ {
return _text; return _text;
} }
void void sg_format_exception::setText(const char* text) noexcept
sg_format_exception::setText (const char* text)
{ {
if (text) { if (text) {
strncpy(_text, text, MAX_TEXT_LEN); strncpy(_text, text, MAX_TEXT_LEN);
@ -328,26 +288,19 @@ sg_format_exception::setText (const char* text)
// Implementation of sg_range_exception. // Implementation of sg_range_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_range_exception::sg_range_exception () sg_range_exception::sg_range_exception(const char* message,
: sg_exception() const char* origin, bool report)
{ : sg_exception(message, origin, {}, report)
}
sg_range_exception::sg_range_exception (const char* message,
const char* origin)
: sg_exception(message, origin)
{ {
} }
sg_range_exception::sg_range_exception(const std::string& message, sg_range_exception::sg_range_exception(const std::string& message,
const std::string& origin) const std::string& origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
} }
sg_range_exception::~sg_range_exception ()
{
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////

View File

@ -28,23 +28,23 @@ class sg_location
{ {
public: public:
enum {max_path = 1024}; enum {max_path = 1024};
sg_location (); sg_location() noexcept;
sg_location(const std::string& path, int line = -1, int column = -1); sg_location(const std::string& path, int line = -1, int column = -1) noexcept;
sg_location(const SGPath& path, int line = -1, int column = -1); sg_location(const SGPath& path, int line = -1, int column = -1) noexcept;
explicit sg_location(const char* path, int line = -1, int column = -1); explicit sg_location(const char* path, int line = -1, int column = -1) noexcept;
~sg_location() = default; ~sg_location() = default;
const char *getPath() const; const char* getPath() const noexcept;
int getLine() const; int getLine() const noexcept;
int getColumn() const; int getColumn() const noexcept;
int getByte() const; int getByte() const noexcept;
std::string asString() const; std::string asString() const noexcept;
bool isValid() const; bool isValid() const noexcept;
private: private:
void setPath(const char *p); void setPath(const char* p) noexcept;
char _path[max_path]; char _path[max_path];
int _line; int _line;
@ -60,20 +60,26 @@ class sg_throwable : public std::exception
{ {
public: public:
enum {MAX_TEXT_LEN = 1024}; enum {MAX_TEXT_LEN = 1024};
sg_throwable (); sg_throwable() noexcept;
sg_throwable(const char *message, const char *origin = 0, sg_throwable(const char* message, const char* origin = 0,
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
virtual ~sg_throwable (); virtual ~sg_throwable() noexcept = default;
virtual const char* getMessage () const;
virtual const std::string getFormattedMessage () const; virtual const char* getMessage() const noexcept;
virtual void setMessage (const char* message); std::string getFormattedMessage() const noexcept;
virtual const char* getOrigin () const; virtual void setMessage(const char* message) noexcept;
virtual void setOrigin (const char *origin); virtual const char* getOrigin() const noexcept;
virtual void setOrigin(const char* origin) noexcept;
virtual const char* what() const noexcept; virtual const char* what() const noexcept;
private:
sg_location getLocation() const noexcept;
void setLocation(const sg_location& location) noexcept;
private:
char _message[MAX_TEXT_LEN]; char _message[MAX_TEXT_LEN];
char _origin[MAX_TEXT_LEN]; char _origin[MAX_TEXT_LEN];
sg_location _location;
}; };
@ -90,10 +96,10 @@ private:
class sg_error : public sg_throwable class sg_error : public sg_throwable
{ {
public: public:
sg_error (); sg_error() noexcept = default;
sg_error (const char* message, const char* origin = 0); sg_error(const char* message, const char* origin = 0, bool report = true) noexcept;
sg_error(const std::string &message, const std::string &origin = {}); sg_error(const std::string& message, const std::string& origin = {}, bool report = true) noexcept;
virtual ~sg_error (); virtual ~sg_error() noexcept = default;
}; };
@ -114,12 +120,12 @@ public:
class sg_exception : public sg_throwable class sg_exception : public sg_throwable
{ {
public: public:
sg_exception (); sg_exception() noexcept = default;
sg_exception(const char *message, const char *origin = 0, sg_exception(const char* message, const char* origin = 0,
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
sg_exception(const std::string &message, const std::string & = {}, sg_exception(const std::string& message, const std::string& = {},
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
virtual ~sg_exception (); virtual ~sg_exception() noexcept = default;
}; };
@ -137,20 +143,15 @@ public:
class sg_io_exception : public sg_exception class sg_io_exception : public sg_exception
{ {
public: public:
sg_io_exception (); sg_io_exception() noexcept = default;
sg_io_exception (const char* message, const char* origin = 0); sg_io_exception(const char* message, const char* origin = 0, bool report = true);
sg_io_exception (const char* message, const sg_location &location, sg_io_exception(const char* message, const sg_location& location,
const char* origin = 0); const char* origin = 0, bool report = true);
sg_io_exception (const std::string &message, const std::string &origin = ""); sg_io_exception(const std::string& message, const std::string& origin = {}, bool report = true);
sg_io_exception (const std::string &message, const sg_location &location, sg_io_exception(const std::string& message, const sg_location& location,
const std::string &origin = ""); const std::string& origin = {}, bool report = true);
virtual ~sg_io_exception (); virtual ~sg_io_exception() noexcept = default;
virtual const std::string getFormattedMessage () const;
virtual const sg_location &getLocation () const;
virtual void setLocation (const sg_location &location);
private:
sg_location _location;
}; };
@ -168,14 +169,15 @@ private:
class sg_format_exception : public sg_exception class sg_format_exception : public sg_exception
{ {
public: public:
sg_format_exception (); sg_format_exception() noexcept;
sg_format_exception (const char* message, const char* text, sg_format_exception(const char* message, const char* text,
const char* origin = 0); const char* origin = 0, bool report = true);
sg_format_exception (const std::string& message, const std::string& text, sg_format_exception(const std::string& message, const std::string& text,
const std::string& origin = ""); const std::string& origin = {}, bool report = true);
virtual ~sg_format_exception ();
virtual const char* getText () const; const char* getText() const noexcept;
virtual void setText (const char* text); void setText(const char* text) noexcept;
private: private:
char _text[MAX_TEXT_LEN]; char _text[MAX_TEXT_LEN];
}; };
@ -193,12 +195,14 @@ private:
class sg_range_exception : public sg_exception class sg_range_exception : public sg_exception
{ {
public: public:
sg_range_exception (); sg_range_exception() noexcept = default;
sg_range_exception (const char* message, sg_range_exception(const char* message,
const char* origin = 0); const char* origin = 0,
sg_range_exception (const std::string& message, bool report = true);
const std::string& origin = ""); sg_range_exception(const std::string& message,
virtual ~sg_range_exception (); const std::string& origin = {},
bool report = true);
virtual ~sg_range_exception() noexcept = default;
}; };
using ThrowCallback = std::function<void( using ThrowCallback = std::function<void(