Refactor DFHack exception classes

Move implementations out of MiscUtils.cpp to Error.cpp and make what() return a
more useful description
develop
lethosor 2018-02-05 19:18:35 -05:00
parent c92227f007
commit c1e2633e17
6 changed files with 102 additions and 99 deletions

@ -57,6 +57,7 @@ SET(MAIN_SOURCES
Core.cpp
ColorText.cpp
DataDefs.cpp
Error.cpp
VTableInterpose.cpp
LuaWrapper.cpp
LuaTypes.cpp

@ -0,0 +1,44 @@
#include "Error.h"
#include "MiscUtils.h"
using namespace DFHack::Error;
inline const char *safe_str(const char *s)
{
return s ? s : "(NULL)";
}
NullPointer::NullPointer(const char *varname)
:All(stl_concat("NULL pointer: ", safe_str(varname))),
varname(varname)
{}
InvalidArgument::InvalidArgument(const char *expr)
:All(stl_concat("Invalid argument; expected: ", safe_str(expr))),
expr(expr)
{}
VTableMissing::VTableMissing(const char *name)
:All(stl_concat("Missing vtable address: ", safe_str(name))),
name(name)
{}
SymbolsXmlParse::SymbolsXmlParse(const char* desc, int id, int row, int col)
:AllSymbols(stl_concat("error ", id, ": ", desc, ", at row ", row, " col ", col)),
desc(safe_str(desc)), id(id), row(row), col(col)
{}
SymbolsXmlBadAttribute::SymbolsXmlBadAttribute(const char *attr)
:AllSymbols(stl_concat("attribute is either missing or invalid: ", safe_str(attr))),
attr(safe_str(attr))
{}
SymbolsXmlNoRoot::SymbolsXmlNoRoot()
:AllSymbols("no root element")
{}
SymbolsXmlUnderspecifiedEntry::SymbolsXmlUnderspecifiedEntry(const char *where)
:AllSymbols(stl_concat("Underspecified symbol file entry, each entry needs to set both the name attribute and have a value. parent: ",
safe_str(where))),
where(safe_str(where))
{}

@ -1076,20 +1076,8 @@ int LuaWrapper::method_wrapper_core(lua_State *state, function_identity_base *id
try {
id->invoke(state, 1);
}
catch (Error::NullPointer &e) {
const char *vn = e.varname();
std::string tmp = stl_sprintf("NULL pointer: %s", vn ? vn : "?");
field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke");
}
catch (Error::InvalidArgument &e) {
const char *vn = e.expr();
std::string tmp = stl_sprintf("Invalid argument; expected: %s", vn ? vn : "?");
field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke");
}
catch (Error::VTableMissing &e) {
const char *cn = e.name();
std::string tmp = stl_sprintf("Missing vtable address: %s", cn ? cn : "?");
field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke");
catch (Error::All &e) {
field_error(state, UPVAL_METHOD_NAME, e.what(), "invoke");
}
catch (std::exception &e) {
std::string tmp = stl_sprintf("C++ exception: %s", e.what());
@ -1107,17 +1095,8 @@ int Lua::CallWithCatch(lua_State *state, int (*fn)(lua_State*), const char *cont
try {
return fn(state);
}
catch (Error::NullPointer &e) {
const char *vn = e.varname();
return luaL_error(state, "%s: NULL pointer: %s", context, vn ? vn : "?");
}
catch (Error::InvalidArgument &e) {
const char *vn = e.expr();
return luaL_error(state, "%s: Invalid argument; expected: %s", context, vn ? vn : "?");
}
catch (Error::VTableMissing &e) {
const char *cn = e.name();
return luaL_error(state, "%s: Missing vtable address: %s", context, cn ? cn : "?");
catch (Error::All &e) {
return luaL_error(state, "%s: %s", context, e.what());
}
catch (std::exception &e) {
return luaL_error(state, "%s: C++ exception: %s", context, e.what());

@ -41,18 +41,6 @@ distribution.
#include <sstream>
#include <map>
const char *DFHack::Error::NullPointer::what() const throw() {
return "DFHack::Error::NullPointer";
}
const char *DFHack::Error::InvalidArgument::what() const throw() {
return "DFHack::Error::InvalidArgument";
}
const char *DFHack::Error::VTableMissing::what() const throw() {
return "DFHack::Error::VTableMissing";
}
std::string stl_sprintf(const char *fmt, ...) {
va_list lst;
va_start(lst, fmt);

@ -41,118 +41,91 @@ namespace DFHack
#ifdef _MSC_VER
#pragma push
/**
* C4275 is - The warning officially is non dll-interface class 'std::exception' used as base for
* C4275 - The warning officially is non dll-interface class 'std::exception' used as base for
* dll-interface class
*
* Basically, its saying that you might have an ABI problem if you mismatch compilers. We don't
* Basically, it's saying that you might have an ABI problem if you mismatch compilers. We don't
* care since we build all of DFhack at once against whatever Toady is using
*/
#pragma warning(disable: 4275)
#endif
class DFHACK_EXPORT All : public std::exception{};
class DFHACK_EXPORT All : public std::exception
{
public:
const std::string full;
All(const std::string &full)
:full(full)
{}
virtual const char *what() const noexcept
{
return full.c_str();
}
virtual ~All() noexcept {}
};
#ifdef _MSC_VER
#pragma pop
#endif
class DFHACK_EXPORT NullPointer : public All {
const char *varname_;
public:
NullPointer(const char *varname_ = NULL) : varname_(varname_) {}
const char *varname() const { return varname_; }
virtual const char *what() const throw();
const char *const varname;
NullPointer(const char *varname = NULL);
};
#define CHECK_NULL_POINTER(var) \
{ if (var == NULL) throw DFHack::Error::NullPointer(#var); }
class DFHACK_EXPORT InvalidArgument : public All {
const char *expr_;
public:
InvalidArgument(const char *expr_ = NULL) : expr_(expr_) {}
const char *expr() const { return expr_; }
virtual const char *what() const throw();
const char *const expr;
InvalidArgument(const char *expr = NULL);
};
#define CHECK_INVALID_ARGUMENT(expr) \
{ if (!(expr)) throw DFHack::Error::InvalidArgument(#expr); }
class DFHACK_EXPORT VTableMissing : public All {
const char *name_;
public:
VTableMissing(const char *name_ = NULL) : name_(name_) {}
const char *name() const { return name_; }
virtual const char *what() const throw();
const char *const name;
VTableMissing(const char *name = NULL);
};
class DFHACK_EXPORT AllSymbols : public All{};
class DFHACK_EXPORT AllSymbols : public All
{
public:
AllSymbols(const std::string &full)
:All(full)
{}
};
// Syntax errors and whatnot, the xml can't be read
class DFHACK_EXPORT SymbolsXmlParse : public AllSymbols
{
public:
SymbolsXmlParse(const char* _desc, int _id, int _row, int _col)
:desc(_desc), id(_id), row(_row), col(_col)
{
std::stringstream s;
s << "error " << id << ": " << desc << ", at row " << row << " col " << col;
full = s.str();
}
std::string full;
SymbolsXmlParse(const char* desc, int id, int row, int col);
const std::string desc;
const int id;
const int row;
const int col;
virtual ~SymbolsXmlParse() throw(){};
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT SymbolsXmlBadAttribute : public All
class DFHACK_EXPORT SymbolsXmlBadAttribute : public AllSymbols
{
public:
SymbolsXmlBadAttribute(const char* _attr) : attr(_attr)
{
std::stringstream s;
s << "attribute is either missing or invalid: " << attr;
full = s.str();
}
std::string full;
SymbolsXmlBadAttribute(const char* attr);
std::string attr;
virtual ~SymbolsXmlBadAttribute() throw(){};
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT SymbolsXmlNoRoot : public All
class DFHACK_EXPORT SymbolsXmlNoRoot : public AllSymbols
{
public:
SymbolsXmlNoRoot() {}
virtual ~SymbolsXmlNoRoot() throw(){};
virtual const char* what() const throw()
{
return "Symbol file is missing root element.";
}
SymbolsXmlNoRoot();
};
class DFHACK_EXPORT SymbolsXmlUnderspecifiedEntry : public All
class DFHACK_EXPORT SymbolsXmlUnderspecifiedEntry : public AllSymbols
{
public:
SymbolsXmlUnderspecifiedEntry(const char * _where) : where(_where)
{
std::stringstream s;
s << "Underspecified symbol file entry, each entry needs to set both the name attribute and have a value. parent: " << where;
full = s.str();
}
virtual ~SymbolsXmlUnderspecifiedEntry() throw(){};
SymbolsXmlUnderspecifiedEntry(const char *where);
std::string where;
std::string full;
virtual const char* what() const throw()
{
return full.c_str();
}
};
}
}

@ -349,6 +349,24 @@ DFHACK_EXPORT uint64_t GetTimeMs64();
DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...);
DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args);
// https://stackoverflow.com/questions/27375089/what-is-the-easiest-way-to-print-a-variadic-parameter-pack-using-stdostream
template<typename... Args>
inline std::string stl_concat(Args... args)
{
std::ostringstream os;
(void)(int[]){0, (void(os << std::forward<Args>(args)), 0)...};
return os.str();
}
template<typename... Args>
inline std::string stl_concat(const std::string &sep, Args... args)
{
std::ostringstream os;
(void)(int[]){0, (void(os << sep << std::forward<Args>(args)), 0)...};
return os.str();
}
// Conversion between CP437 and UTF-8
DFHACK_EXPORT std::string UTF2DF(const std::string &in);
DFHACK_EXPORT std::string DF2UTF(const std::string &in);