Much better error-checking when loading scenarios
- First of all, the program no longer crashes after an error. - A lot more constraints are now checked for, such as required elements; even some constraints not expressed in the schema - Special node parsing now has actually useful error messages - Map data parsing now has error messages for the few invalid cases - Fix the XML utility exception classes originally used only by the dialog engine; they're now correctly caught and properly report the error - Fix loading of special shop entries - Fix accepting any character as the separator in dice constants - Verify that the monster ability type is on the right ability tag, that the extra element is present only if needed for general abilities, and that the missile and range elements are present for non-touch general abilities - Use "infinite" for quantity in special shop items, instead of 0 - Tweak ticpp to fill out file/line/col information for _all_ exceptions, not just parse errors - Raise error (ie, set stream failbit) when failing to convert an enumerator, instead of silently returning a default value (they do still return a default value though, if you don't bother to check stream state) - Fix status effect enumerator not being correctly saved/loaded
This commit is contained in:
@@ -1421,21 +1421,21 @@ xBadNode::xBadNode(std::string t, int r, int c, std::string dlg) throw() :
|
||||
msg(NULL),
|
||||
dlg(dlg) {}
|
||||
|
||||
const char* xBadNode::what() throw() {
|
||||
const char* xBadNode::what() const throw() {
|
||||
if(msg == NULL){
|
||||
char* s = new (nothrow) char[200];
|
||||
if(s == NULL){
|
||||
std::cerr << "Allocation of memory for error message failed, bailing out..." << std::endl;
|
||||
abort();
|
||||
}
|
||||
sprintf(s,"XML Parse Error: Unknown element %s encountered (dialog %s, line %d, column %d).",type.c_str(),dlg.c_str(),row,col);
|
||||
sprintf(s,"XML Parse Error: Unknown element %s encountered (file %s, line %d, column %d).",type.c_str(),dlg.c_str(),row,col);
|
||||
msg = s;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
xBadNode::~xBadNode() throw(){
|
||||
if(msg != NULL) delete msg;
|
||||
if(msg != NULL) delete[] msg;
|
||||
}
|
||||
|
||||
xBadAttr::xBadAttr(std::string t, std::string n, int r, int c, std::string dlg) throw() :
|
||||
@@ -1446,21 +1446,21 @@ xBadAttr::xBadAttr(std::string t, std::string n, int r, int c, std::string dlg)
|
||||
msg(NULL),
|
||||
dlg(dlg) {}
|
||||
|
||||
const char* xBadAttr::what() throw() {
|
||||
const char* xBadAttr::what() const throw() {
|
||||
if(msg == NULL){
|
||||
char* s = new (nothrow) char[200];
|
||||
if(s == NULL){
|
||||
std::cerr << "Allocation of memory for error message failed, bailing out..." << std::endl;
|
||||
abort();
|
||||
}
|
||||
sprintf(s,"XML Parse Error: Unknown attribute %s encountered on element %s (dialog %s, line %d, column %d).",name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
sprintf(s,"XML Parse Error: Unknown attribute %s encountered on element %s (file %s, line %d, column %d).",name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
msg = s;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
xBadAttr::~xBadAttr() throw(){
|
||||
if(msg != NULL) delete msg;
|
||||
if(msg != NULL) delete[] msg;
|
||||
}
|
||||
|
||||
xMissingAttr::xMissingAttr(std::string t, std::string n, int r, int c, std::string dlg) throw() :
|
||||
@@ -1471,21 +1471,46 @@ xMissingAttr::xMissingAttr(std::string t, std::string n, int r, int c, std::stri
|
||||
msg(NULL),
|
||||
dlg(dlg) {}
|
||||
|
||||
const char* xMissingAttr::what() throw() {
|
||||
const char* xMissingAttr::what() const throw() {
|
||||
if(msg == NULL){
|
||||
char* s = new (nothrow) char[200];
|
||||
if(s == NULL){
|
||||
std::cerr << "Allocation of memory for error message failed, bailing out..." << std::endl;
|
||||
abort();
|
||||
}
|
||||
sprintf(s,"XML Parse Error: Required attribute %s missing on element %s (dialog %s, line %d, column %d).",name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
sprintf(s,"XML Parse Error: Required attribute %s missing on element %s (file %s, line %d, column %d).",name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
msg = s;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
xMissingAttr::~xMissingAttr() throw(){
|
||||
if(msg != NULL) delete msg;
|
||||
if(msg != NULL) delete[] msg;
|
||||
}
|
||||
|
||||
xMissingElem::xMissingElem(std::string p, std::string t, int r, int c, std::string dlg) throw() :
|
||||
parent(p),
|
||||
name(t),
|
||||
row(r),
|
||||
col(c),
|
||||
msg(NULL),
|
||||
dlg(dlg) {}
|
||||
|
||||
const char* xMissingElem::what() const throw() {
|
||||
if(msg == NULL){
|
||||
char* s = new (nothrow) char[200];
|
||||
if(s == NULL){
|
||||
std::cerr << "Allocation of memory for error message failed, bailing out..." << std::endl;
|
||||
abort();
|
||||
}
|
||||
sprintf(s,"XML Parse Error: Required element %s missing in element %s (file %s, line %d, column %d).",name.c_str(),parent.c_str(),dlg.c_str(),row,col);
|
||||
msg = s;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
xMissingElem::~xMissingElem() throw(){
|
||||
if(msg != NULL) delete[] msg;
|
||||
}
|
||||
|
||||
xBadVal::xBadVal(std::string t, std::string n, std::string v, int r, int c, std::string dlg) throw() :
|
||||
@@ -1497,21 +1522,21 @@ xBadVal::xBadVal(std::string t, std::string n, std::string v, int r, int c, std:
|
||||
msg(NULL),
|
||||
dlg(dlg) {}
|
||||
|
||||
const char* xBadVal::what() throw() {
|
||||
const char* xBadVal::what() const throw() {
|
||||
if(msg == NULL){
|
||||
char* s = new (nothrow) char[200];
|
||||
if(s == NULL){
|
||||
std::cerr << "Allocation of memory for error message failed, bailing out..." << std::endl;
|
||||
abort();
|
||||
}
|
||||
sprintf(s,"XML Parse Error: Invalid value %s for attribute %s encountered on element %s (dialog %s, line %d, column %d).",val.c_str(),name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
sprintf(s,"XML Parse Error: Invalid value %s for attribute %s encountered on element %s (file %s, line %d, column %d).",val.c_str(),name.c_str(),type.c_str(),dlg.c_str(),row,col);
|
||||
msg = s;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
xBadVal::~xBadVal() throw(){
|
||||
if(msg != NULL) delete msg;
|
||||
if(msg != NULL) delete[] msg;
|
||||
}
|
||||
|
||||
bool cDialog::doAnimations = false;
|
||||
|
@@ -204,10 +204,10 @@ private:
|
||||
};
|
||||
|
||||
/// Thrown when an invalid element is found while parsing an XML dialog definition.
|
||||
class xBadNode : std::exception {
|
||||
class xBadNode : public std::exception {
|
||||
std::string type, dlg;
|
||||
int row, col;
|
||||
const char* msg;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param t The tag name of the invalid element.
|
||||
@@ -217,14 +217,14 @@ public:
|
||||
xBadNode(std::string t, int r, int c, std::string dlg) throw();
|
||||
~xBadNode() throw();
|
||||
/// @return The error message.
|
||||
const char* what() throw();
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
/// Thrown when an invalid attribute is found while parsing an XML dialog definition.
|
||||
class xBadAttr : std::exception {
|
||||
class xBadAttr : public std::exception {
|
||||
std::string type, name, dlg;
|
||||
int row, col;
|
||||
const char* msg;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param t The tag name of the element with the invalid attribute.
|
||||
@@ -235,14 +235,14 @@ public:
|
||||
xBadAttr(std::string t,std::string n, int r, int c, std::string dlg) throw();
|
||||
~xBadAttr() throw();
|
||||
/// @return The error message.
|
||||
const char* what() throw();
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
/// Thrown when an element is missing a required attribute while parsing an XML dialog definition.
|
||||
class xMissingAttr : std::exception {
|
||||
class xMissingAttr : public std::exception {
|
||||
std::string type, name, dlg;
|
||||
int row, col;
|
||||
const char* msg;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param t The tag name of the element with the missing attribute.
|
||||
@@ -253,14 +253,32 @@ public:
|
||||
xMissingAttr(std::string t,std::string n, int r, int c, std::string dlg) throw();
|
||||
~xMissingAttr() throw();
|
||||
/// @return The error message.
|
||||
const char* what() throw();
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
/// Thrown when a required element is missing while parsing an XML dialog definition.
|
||||
class xMissingElem : public std::exception {
|
||||
std::string parent, name, dlg;
|
||||
int row, col;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param p The tag name of the parent element.
|
||||
/// @param t The tag name of the missing element.
|
||||
/// @param r The line number of the element in the source.
|
||||
/// @param c The column number of the element in the source.
|
||||
/// @param dlg The name of the file in which the element occurred.
|
||||
xMissingElem(std::string p, std::string t, int r, int c, std::string dlg) throw();
|
||||
~xMissingElem() throw();
|
||||
/// @return The error message.
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
/// Thrown when an invalid value is found anywhere within an element's or attribute's content.
|
||||
class xBadVal : std::exception {
|
||||
class xBadVal : public std::exception {
|
||||
std::string type, name, val, dlg;
|
||||
int row, col;
|
||||
const char* msg;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// A magic value to indicate errors in an element's content, rather than an attribute's content.
|
||||
static const char*const CONTENT;
|
||||
@@ -275,7 +293,7 @@ public:
|
||||
xBadVal(std::string t,std::string n,std::string v, int r, int c, std::string dlg) throw();
|
||||
~xBadVal() throw();
|
||||
/// @return The error message.
|
||||
const char* what() throw();
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -263,6 +263,12 @@ namespace ticpp
|
||||
<< "\nLine: " << doc->ErrorRow()
|
||||
<< "\nColumn: " << doc->ErrorCol();
|
||||
}
|
||||
else
|
||||
{
|
||||
full_message << "\nFile: " << (strlen( doc->Value() ) > 0 ? doc->Value() : "<unnamed-file>")
|
||||
<< "\nLine: " << node->Row()
|
||||
<< "\nColumn: " << node->Column();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user