]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/props_io.cxx
- new FSF addresses
[simgear.git] / simgear / props / props_io.cxx
index 92781ea6e3b5a8bfcf80affa4f4b4f5a36893689..45886a6cd4614e95f75ceccd84d85a6845c9988b 100644 (file)
@@ -1,3 +1,16 @@
+/**
+ * \file props_io.cxx
+ * Started Fall 2000 by David Megginson, david@megginson.com
+ * This code is released into the Public Domain.
+ *
+ * See props.html for documentation [replace with URL when available].
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #include <simgear/compiler.h>
 
@@ -37,8 +50,8 @@ class PropsVisitor : public XMLVisitor
 {
 public:
 
-  PropsVisitor (SGPropertyNode * root, const string &base)
-    : _root(root), _level(0), _base(base), _hasException(false) {}
+  PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0)
+    : _default_mode(default_mode), _root(root), _level(0), _base(base), _hasException(false) {}
 
   virtual ~PropsVisitor () {}
 
@@ -85,6 +98,7 @@ private:
     _level--;
   }
 
+  int _default_mode;
   string _data;
   SGPropertyNode * _root;
   int _level;
@@ -117,9 +131,9 @@ checkFlag (const char * flag, bool defaultState = true)
 {
   if (flag == 0)
     return defaultState;
-  else if (flag == "y")
+  else if (!strcmp(flag, "y"))
     return true;
-  else if (flag == "n")
+  else if (!strcmp(flag, "n"))
     return false;
   else {
     string message = "Unrecognized flag value '";
@@ -133,11 +147,10 @@ checkFlag (const char * flag, bool defaultState = true)
 void
 PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
 {
-  State &st = state();
   const char * attval;
 
   if (_level == 0) {
-    if (name != "PropertyList") {
+    if (strcmp(name, "PropertyList")) {
       string message = "Root element name is ";
       message += name;
       message += "; expected PropertyList";
@@ -160,6 +173,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
   }
 
   else {
+    State &st = state();
                                // Get the index.
     attval = atts.getValue("n");
     int index = 0;
@@ -177,7 +191,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
                                // Get the access-mode attributes,
                                // but don't set yet (in case they
                                // prevent us from recording the value).
-    int mode = 0;
+    int mode = _default_mode;
 
     attval = atts.getValue("read");
     if (checkFlag(attval, true))
@@ -194,6 +208,9 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
     attval = atts.getValue("trace-write");
     if (checkFlag(attval, false))
       mode |= SGPropertyNode::TRACE_WRITE;
+    attval = atts.getValue("userarchive");
+    if (checkFlag(attval, false))
+      mode |= SGPropertyNode::USERARCHIVE;
 
                                // Check for an alias.
     attval = atts.getValue("alias");
@@ -214,7 +231,10 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
       }
     }
 
-    push_state(node, atts.getValue("type"), mode);
+    const char *type = atts.getValue("type");
+    if (type)
+      node->clearValue();
+    push_state(node, type, mode);
   }
 }
 
@@ -296,9 +316,9 @@ PropsVisitor::warning (const char * message, int line, int column)
  */
 void
 readProperties (istream &input, SGPropertyNode * start_node,
-               const string &base)
+               const string &base, int default_mode)
 {
-  PropsVisitor visitor(start_node, base);
+  PropsVisitor visitor(start_node, base, default_mode);
   readXML(input, visitor, base);
   if (visitor.hasException())
     throw visitor.getException();
@@ -313,15 +333,33 @@ readProperties (istream &input, SGPropertyNode * start_node,
  * @return true if the read succeeded, false otherwise.
  */
 void
-readProperties (const string &file, SGPropertyNode * start_node)
+readProperties (const string &file, SGPropertyNode * start_node,
+                int default_mode)
 {
-  PropsVisitor visitor(start_node, file);
+  PropsVisitor visitor(start_node, file, default_mode);
   readXML(file, visitor);
   if (visitor.hasException())
     throw visitor.getException();
 }
 
 
+/**
+ * Read properties from an in-memory buffer.
+ *
+ * @param buf A character buffer containing the xml data.
+ * @param size The size/length of the buffer in bytes
+ * @param start_node The root node for reading properties.
+ * @return true if the read succeeded, false otherwise.
+ */
+void readProperties (const char *buf, const int size,
+                     SGPropertyNode * start_node, int default_mode)
+{
+  PropsVisitor visitor(start_node, "", default_mode);
+  readXML(buf, size, visitor);
+  if (visitor.hasException())
+    throw visitor.getException();
+}
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // Property list writer.
@@ -419,15 +457,15 @@ writeAtts (ostream &output, const SGPropertyNode * node)
  * Test whether a node is archivable or has archivable descendants.
  */
 static bool
-isArchivable (const SGPropertyNode * node)
+isArchivable (const SGPropertyNode * node, SGPropertyNode::Attribute archive_flag)
 {
   // FIXME: it's inefficient to do this all the time
-  if (node->getAttribute(SGPropertyNode::ARCHIVE))
+  if (node->getAttribute(archive_flag))
     return true;
   else {
     int nChildren = node->nChildren();
     for (int i = 0; i < nChildren; i++)
-      if (isArchivable(node->getChild(i)))
+      if (isArchivable(node->getChild(i), archive_flag))
        return true;
   }
   return false;
@@ -436,12 +474,12 @@ isArchivable (const SGPropertyNode * node)
 
 static bool
 writeNode (ostream &output, const SGPropertyNode * node,
-          bool write_all, int indent)
+           bool write_all, int indent, SGPropertyNode::Attribute archive_flag)
 {
                                // Don't write the node or any of
                                // its descendants unless it is
                                // allowed to be archived.
-  if (!write_all && !isArchivable(node))
+  if (!write_all && !isArchivable(node, archive_flag))
     return true;               // Everything's OK, but we won't write.
 
   const string name = node->getName();
@@ -449,7 +487,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
 
                                // If there is a literal value,
                                // write it first.
-  if (node->hasValue() && (write_all || node->getAttribute(SGPropertyNode::ARCHIVE))) {
+  if (node->hasValue() && (write_all || node->getAttribute(archive_flag))) {
     doIndent(output, indent);
     output << '<' << name;
     writeAtts(output, node);
@@ -466,13 +504,13 @@ writeNode (ostream &output, const SGPropertyNode * node,
   }
 
                                // If there are children, write them next.
-  if (nChildren > 0 || node->isAlias()) {
+  if (nChildren > 0) {
     doIndent(output, indent);
     output << '<' << name;
     writeAtts(output, node);
     output << '>' << endl;
     for (int i = 0; i < nChildren; i++)
-      writeNode(output, node->getChild(i), write_all, indent + INDENT_STEP);
+      writeNode(output, node->getChild(i), write_all, indent + INDENT_STEP, archive_flag);
     doIndent(output, indent);
     output << "</" << name << '>' << endl;
   }
@@ -483,7 +521,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
 
 void
 writeProperties (ostream &output, const SGPropertyNode * start_node,
-                bool write_all)
+                 bool write_all, SGPropertyNode::Attribute archive_flag)
 {
   int nChildren = start_node->nChildren();
 
@@ -491,7 +529,7 @@ writeProperties (ostream &output, const SGPropertyNode * start_node,
   output << "<PropertyList>" << endl;
 
   for (int i = 0; i < nChildren; i++) {
-    writeNode(output, start_node->getChild(i), write_all, INDENT_STEP);
+    writeNode(output, start_node->getChild(i), write_all, INDENT_STEP, archive_flag);
   }
 
   output << "</PropertyList>" << endl;
@@ -500,11 +538,11 @@ writeProperties (ostream &output, const SGPropertyNode * start_node,
 
 void
 writeProperties (const string &file, const SGPropertyNode * start_node,
-                bool write_all)
+                 bool write_all, SGPropertyNode::Attribute archive_flag)
 {
   ofstream output(file.c_str());
   if (output.good()) {
-    writeProperties(output, start_node, write_all);
+    writeProperties(output, start_node, write_all, archive_flag);
   } else {
     throw sg_io_exception("Cannot open file", sg_location(file));
   }
@@ -563,12 +601,17 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
        retval = false;
       break;
     default:
+      if (in->isAlias())
+       break;
       string message = "Unknown internal SGPropertyNode type";
       message += in->getType();
       throw sg_error(message, "SimGear Property Reader");
     }
   }
 
+                               // copy the attributes.
+  out->setAttributes( in->getAttributes() );
+
                                // Next, copy the children.
   int nChildren = in->nChildren();
   for (int i = 0; i < nChildren; i++) {