X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmisc%2Fprops_io.cxx;h=160539ae73b41309c9f6d1fe88b9bdeada65976c;hb=5bab565cfe4c30d6cf08ecaba50af74d5e4f0c98;hp=122d6bffa0d307d20c3e044cbf558cda892f092c;hpb=e7b9e5559923d4ca2250113e1d834e8fb2dcfa7c;p=simgear.git diff --git a/simgear/misc/props_io.cxx b/simgear/misc/props_io.cxx index 122d6bff..160539ae 100644 --- a/simgear/misc/props_io.cxx +++ b/simgear/misc/props_io.cxx @@ -30,7 +30,7 @@ SG_USING_STD(string); SG_USING_STD(vector); SG_USING_STD(map); -#define DEFAULT_MODE (SGPropertyNode::READ|SGPropertyNode::WRITE|SGPropertyNode::ARCHIVE) +#define DEFAULT_MODE (SGPropertyNode::READ|SGPropertyNode::WRITE) @@ -43,7 +43,9 @@ class PropsVisitor : public XMLVisitor public: PropsVisitor (SGPropertyNode * root, const string &base) - : _ok(true), _root(root), _level(0), _base(base) {} + : _root(root), _level(0), _base(base), _hasException(false) {} + + virtual ~PropsVisitor () {} void startXML (); void endXML (); @@ -51,9 +53,13 @@ public: void endElement (const char * name); void data (const char * s, int length); 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 _hasException; } + sg_io_exception &getException () { return _exception; } + void setException (const sg_io_exception &exception) { + _exception = exception; + _hasException = true; + } private: @@ -84,12 +90,13 @@ private: _level--; } - bool _ok; string _data; SGPropertyNode * _root; int _level; vector _state_stack; string _base; + sg_io_exception _exception; + bool _hasException; }; void @@ -108,19 +115,23 @@ PropsVisitor::endXML () /** - * Check a yes/no flag that defaults to 'yes'. + * Check a yes/no flag, with default. */ static bool -checkFlag (const char * flag) +checkFlag (const char * flag, bool defaultState = true) { - if (flag == 0 || string(flag) == "y") + if (flag == 0) + return defaultState; + else if (string(flag) == "y") return true; else if (string(flag) == "n") return false; else { - SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized flag value '" << flag - << "', assuming 'y'"); - return true; + string message = "Unrecognized flag value '"; + message += flag; + message += '\''; + // FIXME: add location info + throw sg_io_exception(message, "SimGear Property Reader"); } } @@ -131,9 +142,10 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts) if (_level == 0) { if (string(name) != (string)"PropertyList") { - SG_LOG(SG_INPUT, SG_ALERT, "Root element name is " << - name << "; expected PropertyList"); - _ok = false; + string message = "Root element name is "; + message += name; + message += "; expected PropertyList"; + throw sg_io_exception(message, "SimGear Property Reader"); } push_state(_root, "", DEFAULT_MODE); } @@ -161,14 +173,20 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts) int mode = 0; attval = atts.getValue("read"); - if (checkFlag(attval)) + if (checkFlag(attval, true)) mode |= SGPropertyNode::READ; attval = atts.getValue("write"); - if (checkFlag(attval)) + if (checkFlag(attval, true)) mode |= SGPropertyNode::WRITE; attval = atts.getValue("archive"); - if (checkFlag(attval)) + if (checkFlag(attval, false)) mode |= SGPropertyNode::ARCHIVE; + attval = atts.getValue("trace-read"); + if (checkFlag(attval, false)) + mode |= SGPropertyNode::TRACE_READ; + attval = atts.getValue("trace-write"); + if (checkFlag(attval, false)) + mode |= SGPropertyNode::TRACE_WRITE; // Check for an alias. attval = atts.getValue("alias"); @@ -181,13 +199,11 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts) attval = atts.getValue("include"); if (attval != 0) { SGPath path(SGPath(_base).dir()); - cerr << "Base is " << _base << endl; - cerr << "Dir is " << SGPath(_base).dir() << endl; path.append(attval); - if (!readProperties(path.str(), node)) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to read include file " - << attval); - _ok = false; + try { + readProperties(path.str(), node); + } catch (sg_io_exception &e) { + setException(e); } } @@ -222,9 +238,11 @@ PropsVisitor::endElement (const char * name) } else if (st.type == "unspecified") { ret = st.node->setUnspecifiedValue(_data); } else { - SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized data type " << st.type - << " assuming 'unspecified'"); - ret = st.node->setUnspecifiedValue(_data); + string message = "Unrecognized data type '"; + message += st.type; + message += '\''; + // FIXME: add location information + throw sg_io_exception(message, "SimGear Property Reader"); } if (!ret) SG_LOG(SG_INPUT, SG_ALERT, "readProperties: Failed to set " @@ -254,14 +272,6 @@ PropsVisitor::warning (const char * message, int line, int 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; -} - //////////////////////////////////////////////////////////////////////// @@ -277,12 +287,14 @@ PropsVisitor::error (const char * message, int line, int column) * @param base A base path for resolving external include references. * @return true if the read succeeded, false otherwise. */ -bool +void readProperties (istream &input, SGPropertyNode * start_node, const string &base) { PropsVisitor visitor(start_node, base); - return readXML(input, visitor) && visitor.isOK(); + readXML(input, visitor, base); + if (visitor.hasException()) + throw visitor.getException(); } @@ -293,18 +305,13 @@ readProperties (istream &input, SGPropertyNode * start_node, * @param start_node The root node for reading properties. * @return true if the read succeeded, false otherwise. */ -bool +void readProperties (const string &file, SGPropertyNode * start_node) { - cerr << "Reading properties from " << file << endl; - ifstream input(file.c_str()); - if (input.good()) { - return readProperties(input, start_node, file); - } else { - SG_LOG(SG_INPUT, SG_ALERT, "Error reading property list from file " - << file); - return false; - } + PropsVisitor visitor(start_node, file); + readXML(file, visitor); + if (visitor.hasException()) + throw visitor.getException(); } @@ -382,17 +389,38 @@ writeAtts (ostream &output, const SGPropertyNode * node) int index = node->getIndex(); if (index != 0) - output << " n = \"" << index << '"'; + output << " n=\"" << index << '"'; +#if 0 if (!node->getAttribute(SGPropertyNode::READ)) output << " read=\"n\""; if (!node->getAttribute(SGPropertyNode::WRITE)) output << " write=\"n\""; - if (!node->getAttribute(SGPropertyNode::ARCHIVE)) - output << " archive=\"n\""; + if (node->getAttribute(SGPropertyNode::ARCHIVE)) + output << " archive=\"y\""; +#endif + +} + +/** + * Test whether a node is archivable or has archivable descendants. + */ +static bool +isArchivable (const SGPropertyNode * node) +{ + // FIXME: it's inefficient to do this all the time + if (node->getAttribute(SGPropertyNode::ARCHIVE)) + return true; + else { + int nChildren = node->nChildren(); + for (int i = 0; i < nChildren; i++) + if (isArchivable(node->getChild(i))) + return true; + } + return false; } @@ -402,7 +430,7 @@ writeNode (ostream &output, const SGPropertyNode * node, int indent) // Don't write the node or any of // its descendants unless it is // allowed to be archived. - if (!node->getAttribute(SGPropertyNode::ARCHIVE)) + if (!isArchivable(node)) return true; // Everything's OK, but we won't write. const string &name = node->getName(); @@ -411,7 +439,7 @@ writeNode (ostream &output, const SGPropertyNode * node, int indent) // If there is a literal value, // write it first. - if (node->hasValue()) { + if (node->hasValue() && node->getAttribute(SGPropertyNode::ARCHIVE)) { doIndent(output, indent); output << '<' << name; writeAtts(output, node); @@ -444,14 +472,7 @@ writeNode (ostream &output, const SGPropertyNode * node, int indent) } -/** - * 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 +void writeProperties (ostream &output, const SGPropertyNode * start_node) { int nChildren = start_node->nChildren(); @@ -464,28 +485,17 @@ writeProperties (ostream &output, const SGPropertyNode * start_node) } output << "" << endl; - - return true; } -/** - * 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 +void writeProperties (const string &file, const SGPropertyNode * start_node) { ofstream output(file.c_str()); if (output.good()) { - return writeProperties(output, start_node); + writeProperties(output, start_node); } else { - SG_LOG(SG_INPUT, SG_ALERT, "Cannot write properties to file " - << file); - return false; + throw sg_io_exception("Cannot open file", sg_location(file)); } } @@ -542,7 +552,9 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out) retval = false; break; default: - throw string("Unrecognized SGPropertyNode type"); + string message = "Unknown internal SGPropertyNode type"; + message += in->getType(); + throw sg_error(message, "SimGear Property Reader"); } }