- modified both readProperties functions to return void, and modified

file-name variant to invoke new readXML function
- readProperties and writeProperties will now throw exceptions if there
  are file I/O problems
- replace error messages with exceptions
- tunnel sg_io_exception through from nested property read, since
  the C-based Expat code cannot handle exceptions
This commit is contained in:
curt
2001-07-19 02:33:38 +00:00
parent 66ebe6e690
commit 6f7fe4b481
+41 -62
View File
@@ -43,7 +43,9 @@ class PropsVisitor : public XMLVisitor
public: public:
PropsVisitor (SGPropertyNode * root, const string &base) PropsVisitor (SGPropertyNode * root, const string &base)
: _ok(true), _root(root), _level(0), _base(base) {} : _root(root), _level(0), _base(base), _exception(0) {}
virtual ~PropsVisitor () { delete _exception; }
void startXML (); void startXML ();
void endXML (); void endXML ();
@@ -51,9 +53,9 @@ public:
void endElement (const char * name); void endElement (const char * name);
void data (const char * s, int length); void data (const char * s, int length);
void warning (const char * message, int line, int column); void warning (const char * message, int line, int column);
void error (const char * message, int line, int column);
bool isOK () const { return _ok; } bool hasException () const { return (_exception != 0); }
const sg_io_exception * getException () const { return _exception; }
private: private:
@@ -84,12 +86,12 @@ private:
_level--; _level--;
} }
bool _ok;
string _data; string _data;
SGPropertyNode * _root; SGPropertyNode * _root;
int _level; int _level;
vector<State> _state_stack; vector<State> _state_stack;
string _base; string _base;
sg_io_exception * _exception;
}; };
void void
@@ -120,9 +122,11 @@ checkFlag (const char * flag, bool defaultState = true)
else if (string(flag) == "n") else if (string(flag) == "n")
return false; return false;
else { else {
SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized flag value '" << flag string message = "Unrecognized flag value '";
<< "', assuming yes"); message += flag;
return true; message += '\'';
// FIXME: add location info
throw sg_io_exception(message, "SimGear Property Reader");
} }
} }
@@ -133,9 +137,10 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
if (_level == 0) { if (_level == 0) {
if (string(name) != (string)"PropertyList") { if (string(name) != (string)"PropertyList") {
SG_LOG(SG_INPUT, SG_ALERT, "Root element name is " << string message = "Root element name is ";
name << "; expected PropertyList"); message += name;
_ok = false; message += "; expected PropertyList";
throw sg_io_exception(message, "SimGear Property Reader");
} }
push_state(_root, "", DEFAULT_MODE); push_state(_root, "", DEFAULT_MODE);
} }
@@ -183,13 +188,12 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
attval = atts.getValue("include"); attval = atts.getValue("include");
if (attval != 0) { if (attval != 0) {
SGPath path(SGPath(_base).dir()); SGPath path(SGPath(_base).dir());
cerr << "Base is " << _base << endl;
cerr << "Dir is " << SGPath(_base).dir() << endl;
path.append(attval); path.append(attval);
if (!readProperties(path.str(), node)) { try {
SG_LOG(SG_INPUT, SG_ALERT, "Failed to read include file " readProperties(path.str(), node);
<< attval); } catch (const sg_io_exception &t) {
_ok = false; cerr << "Caught exception\n";
_exception = t.clone();
} }
} }
@@ -224,9 +228,11 @@ PropsVisitor::endElement (const char * name)
} else if (st.type == "unspecified") { } else if (st.type == "unspecified") {
ret = st.node->setUnspecifiedValue(_data); ret = st.node->setUnspecifiedValue(_data);
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized data type " << st.type string message = "Unrecognized data type '";
<< " assuming 'unspecified'"); message += st.type;
ret = st.node->setUnspecifiedValue(_data); message += '\'';
// FIXME: add location information
throw sg_io_exception(message, "SimGear Property Reader");
} }
if (!ret) if (!ret)
SG_LOG(SG_INPUT, SG_ALERT, "readProperties: Failed to set " SG_LOG(SG_INPUT, SG_ALERT, "readProperties: Failed to set "
@@ -256,14 +262,6 @@ PropsVisitor::warning (const char * message, int line, int column)
<< message << " at line " << line << ", column " << column); << message << " at line " << line << ", column " << column);
} }
void
PropsVisitor::error (const char * message, int line, int column)
{
SG_LOG(SG_INPUT, SG_ALERT, "readProperties: FATAL: " <<
message << " at line " << line << ", column " << column);
_ok = false;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@@ -279,12 +277,14 @@ PropsVisitor::error (const char * message, int line, int column)
* @param base A base path for resolving external include references. * @param base A base path for resolving external include references.
* @return true if the read succeeded, false otherwise. * @return true if the read succeeded, false otherwise.
*/ */
bool void
readProperties (istream &input, SGPropertyNode * start_node, readProperties (istream &input, SGPropertyNode * start_node,
const string &base) const string &base)
{ {
PropsVisitor visitor(start_node, base); PropsVisitor visitor(start_node, base);
return readXML(input, visitor) && visitor.isOK(); readXML(input, visitor, base);
if (visitor.hasException())
throw *(visitor.getException());
} }
@@ -295,18 +295,13 @@ readProperties (istream &input, SGPropertyNode * start_node,
* @param start_node The root node for reading properties. * @param start_node The root node for reading properties.
* @return true if the read succeeded, false otherwise. * @return true if the read succeeded, false otherwise.
*/ */
bool void
readProperties (const string &file, SGPropertyNode * start_node) readProperties (const string &file, SGPropertyNode * start_node)
{ {
cerr << "Reading properties from " << file << endl; PropsVisitor visitor(start_node, file);
ifstream input(file.c_str()); readXML(file, visitor);
if (input.good()) { if (visitor.hasException())
return readProperties(input, start_node, file); throw *(visitor.getException());
} else {
SG_LOG(SG_INPUT, SG_ALERT, "Error reading property list from file "
<< file);
return false;
}
} }
@@ -467,14 +462,7 @@ writeNode (ostream &output, const SGPropertyNode * node, int indent)
} }
/** void
* Write a property tree to an output stream in XML format.
*
* @param output The output stream.
* @param start_node The root node to write.
* @return true if the write succeeded, false otherwise.
*/
bool
writeProperties (ostream &output, const SGPropertyNode * start_node) writeProperties (ostream &output, const SGPropertyNode * start_node)
{ {
int nChildren = start_node->nChildren(); int nChildren = start_node->nChildren();
@@ -487,28 +475,17 @@ writeProperties (ostream &output, const SGPropertyNode * start_node)
} }
output << "</PropertyList>" << endl; output << "</PropertyList>" << endl;
return true;
} }
/** void
* Write a property tree to a file in XML format.
*
* @param file The destination file.
* @param start_node The root node to write.
* @return true if the write succeeded, false otherwise.
*/
bool
writeProperties (const string &file, const SGPropertyNode * start_node) writeProperties (const string &file, const SGPropertyNode * start_node)
{ {
ofstream output(file.c_str()); ofstream output(file.c_str());
if (output.good()) { if (output.good()) {
return writeProperties(output, start_node); writeProperties(output, start_node);
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "Cannot write properties to file " throw sg_io_exception("Cannot open file", sg_location(file));
<< file);
return false;
} }
} }
@@ -565,7 +542,9 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
retval = false; retval = false;
break; break;
default: default:
throw string("Unrecognized SGPropertyNode type"); string message = "Unknown internal SGPropertyNode type";
message += in->getType();
throw sg_error(message, "SimGear Property Reader");
} }
} }