Files
simgear/simgear/structure/exception.cxx
T
Automatic Release Builder 733efd08dd Exceptions: optional callback for exception throws.
This is to allow recording an error+stacktrace whenever an exception
is thrown, since that’s the point when the stack is interesting.
2020-09-22 15:26:33 +01:00

357 lines
7.4 KiB
C++

// exception.cxx - implementation of SimGear base exceptions.
// Started Summer 2001 by David Megginson, david@megginson.com
// This code is released into the Public Domain.
//
// $Id$
#include <simgear_config.h>
#include "exception.hxx"
#include <stdio.h>
#include <cstring>
#include <sstream>
#include <simgear/misc/sg_path.hxx>
static ThrowCallback static_callback;
////////////////////////////////////////////////////////////////////////
// Implementation of sg_location class.
////////////////////////////////////////////////////////////////////////
sg_location::sg_location ()
: _line(-1),
_column(-1),
_byte(-1)
{
_path[0] = '\0';
}
sg_location::sg_location (const std::string& path, int line, int column)
: _line(line),
_column(column),
_byte(-1)
{
setPath(path.c_str());
}
sg_location::sg_location (const SGPath& path, int line, int column)
: _line(line),
_column(column),
_byte(-1)
{
setPath(path.utf8Str().c_str());
}
sg_location::sg_location (const char* path, int line, int column)
: _line(line),
_column(column),
_byte(-1)
{
setPath(path);
}
void sg_location::setPath(const char *path) {
if (path) {
strncpy(_path, path, max_path);
_path[max_path -1] = '\0';
} else {
_path[0] = '\0';
}
}
const char *sg_location::getPath() const { return _path; }
int sg_location::getLine() const { return _line; }
int
sg_location::getColumn () const
{
return _column;
}
int
sg_location::getByte () const
{
return _byte;
}
std::string
sg_location::asString () const
{
std::ostringstream out;
if (_path[0]) {
out << _path;
if (_line != -1 || _column != -1)
out << ",\n";
}
if (_line != -1) {
out << "line " << _line;
if (_column != -1)
out << ", ";
}
if (_column != -1) {
out << "column " << _column;
}
return out.str();
}
bool sg_location::isValid() const { return strlen(_path) > 0; }
////////////////////////////////////////////////////////////////////////
// Implementation of sg_throwable class.
////////////////////////////////////////////////////////////////////////
sg_throwable::sg_throwable ()
{
_message[0] = '\0';
_origin[0] = '\0';
}
sg_throwable::sg_throwable(const char *message, const char *origin,
const sg_location &loc) {
setMessage(message);
setOrigin(origin);
if (static_callback) {
static_callback(_message, _origin, loc);
}
}
sg_throwable::~sg_throwable ()
{
}
const char*
sg_throwable::getMessage () const
{
return _message;
}
const std::string
sg_throwable::getFormattedMessage () const
{
return std::string(getMessage());
}
void
sg_throwable::setMessage (const char* message)
{
strncpy(_message, message, MAX_TEXT_LEN);
_message[MAX_TEXT_LEN - 1] = '\0';
}
const char*
sg_throwable::getOrigin () const
{
return _origin;
}
void
sg_throwable::setOrigin (const char* origin)
{
if (origin) {
strncpy(_origin, origin, MAX_TEXT_LEN);
_origin[MAX_TEXT_LEN - 1] = '\0';
} else {
_origin[0] = '\0';
}
}
const char* sg_throwable::what() const noexcept
{
try {
return getMessage();
}
catch (...) {
return "";
}
}
////////////////////////////////////////////////////////////////////////
// Implementation of sg_error class.
////////////////////////////////////////////////////////////////////////
sg_error::sg_error ()
: sg_throwable ()
{
}
sg_error::sg_error (const char* message, const char *origin)
: sg_throwable(message, origin)
{
}
sg_error::sg_error(const std::string& message, const std::string& origin)
: sg_throwable(message.c_str(), origin.c_str())
{
}
sg_error::~sg_error ()
{
}
////////////////////////////////////////////////////////////////////////
// Implementation of sg_exception class.
////////////////////////////////////////////////////////////////////////
sg_exception::sg_exception ()
: sg_throwable ()
{
}
sg_exception::sg_exception(const char *message, const char *origin,
const sg_location &loc)
: sg_throwable(message, origin, loc) {}
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.
////////////////////////////////////////////////////////////////////////
sg_io_exception::sg_io_exception ()
: sg_exception()
{
}
sg_io_exception::sg_io_exception (const char* message, const char* origin)
: sg_exception(message, origin)
{
}
sg_io_exception::sg_io_exception(const char *message,
const sg_location &location,
const char *origin)
: sg_exception(message, origin, location), _location(location) {}
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.
////////////////////////////////////////////////////////////////////////
sg_format_exception::sg_format_exception ()
: sg_exception()
{
_text[0] = '\0';
}
sg_format_exception::sg_format_exception (const char* message,
const char* text,
const char* origin)
: sg_exception(message, origin)
{
setText(text);
}
sg_format_exception::sg_format_exception( const std::string& message,
const std::string& text,
const std::string& origin )
: sg_exception(message, origin)
{
setText(text.c_str());
}
sg_format_exception::~sg_format_exception ()
{
}
const char*
sg_format_exception::getText () const
{
return _text;
}
void
sg_format_exception::setText (const char* text)
{
if (text) {
strncpy(_text, text, MAX_TEXT_LEN);
_text[MAX_TEXT_LEN-1] = '\0';
} else {
_text[0] = '\0';
}
}
////////////////////////////////////////////////////////////////////////
// Implementation of sg_range_exception.
////////////////////////////////////////////////////////////////////////
sg_range_exception::sg_range_exception ()
: sg_exception()
{
}
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,
const std::string& origin)
: sg_exception(message, origin)
{
}
sg_range_exception::~sg_range_exception ()
{
}
////////////////////////////////////////////////////////////////////////
void setThrowCallback(ThrowCallback cb) { static_callback = cb; }
// end of exception.cxx