Skip to content

Commit

Permalink
Refactor DFHack exception classes
Browse files Browse the repository at this point in the history
Move implementations out of MiscUtils.cpp to Error.cpp and make what() return a
more useful description
  • Loading branch information
lethosor committed Feb 6, 2018
1 parent c92227f commit c1e2633
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 99 deletions.
1 change: 1 addition & 0 deletions library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ SET(MAIN_SOURCES
Core.cpp
ColorText.cpp
DataDefs.cpp
Error.cpp
VTableInterpose.cpp
LuaWrapper.cpp
LuaTypes.cpp
Expand Down
44 changes: 44 additions & 0 deletions library/Error.cpp
Original file line number Diff line number Diff line change
@@ -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))
{}
29 changes: 4 additions & 25 deletions library/LuaTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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());
Expand Down
12 changes: 0 additions & 12 deletions library/MiscUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
97 changes: 35 additions & 62 deletions library/include/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
};
}
}
Expand Down
18 changes: 18 additions & 0 deletions library/include/MiscUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c1e2633

Please sign in to comment.