#define DEFAULT_MODE (SGPropertyNode::READ|SGPropertyNode::WRITE)
+// Name of special node containing unused attributes
+const std::string ATTR = "_attr_";
+
////////////////////////////////////////////////////////////////////////
// Property list visitor, for XML parsing.
{
int n_children = node->nChildren();
return n_children > 1
- || (n_children == 1 && node->getChild(0)->getNameString() != "_attr_");
+ || (n_children == 1 && node->getChild(0)->getNameString() != ATTR);
}
SGPropertyNode * node;
string type;
{
// Store all additional attributes in a special node named _attr_
if( !attr_node )
- attr_node = node->getChild("_attr_", 0, true);
+ attr_node = node->getChild(ATTR, 0, true);
attr_node->setUnspecifiedValue(att_name.c_str(), val.c_str());
}
SGPropertyNode *dst = parent.node->getChild(name, index, true);
copyProperties(src, dst);
}
- parent.node->removeChild(st.node->getName(), st.node->getIndex(), false);
+ parent.node->removeChild(st.node->getName(), st.node->getIndex());
}
pop_state();
}
static void
-writeAtts (ostream &output, const SGPropertyNode * node, bool forceindex)
+writeAtts( std::ostream &output,
+ const SGPropertyNode* node,
+ bool forceindex,
+ const SGPropertyNode* attr = NULL )
{
int index = node->getIndex();
if (index != 0 || forceindex)
output << " n=\"" << index << '"';
+ if( attr )
+ for(int i = 0; i < attr->nChildren(); ++i)
+ {
+ output << ' ' << attr->getChild(i)->getName() << "=\"";
+
+ const std::string data = attr->getChild(i)->getStringValue();
+ for(int j = 0; j < (int)data.size(); ++j)
+ {
+ switch(data[j])
+ {
+ case '"':
+ output << "\\\"";
+ break;
+ case '\\':
+ output << "\\\\";
+ break;
+ default:
+ output << data[i];
+ break;
+ }
+ }
+
+ output << '"';
+ }
+
#if 0
if (!node->getAttribute(SGPropertyNode::READ))
output << " read=\"n\"";
static bool
-writeNode (ostream &output, const SGPropertyNode * node,
- bool write_all, int indent, SGPropertyNode::Attribute archive_flag)
+writeNode( std::ostream &output,
+ const SGPropertyNode * node,
+ 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.
+ // Don't write the node or any of
+ // its descendants unless it is
+ // allowed to be archived.
if (!write_all && !isArchivable(node, archive_flag))
- return true; // Everything's OK, but we won't write.
+ return true; // Everything's OK, but we won't write.
const string name = node->getName();
int nChildren = node->nChildren();
- bool node_has_value = false;
+ const SGPropertyNode* attr_node = node->getChild(ATTR, 0);
+ bool attr_written = false,
+ node_has_value = false;
- // If there is a literal value,
- // write it first.
+ // If there is a literal value,
+ // write it first.
if (node->hasValue() && (write_all || node->getAttribute(archive_flag))) {
doIndent(output, indent);
output << '<' << name;
- writeAtts(output, node, nChildren != 0);
+ writeAtts(output, node, nChildren != 0, attr_node);
+ attr_written = true;
if (node->isAlias() && node->getAliasTarget() != 0) {
output << " alias=\"" << node->getAliasTarget()->getPath()
- << "\"/>" << endl;
+ << "\"/>" << endl;
} else {
if (node->getType() != simgear::props::UNSPECIFIED)
- output << " type=\"" << getTypeName(node->getType()) << '"';
+ output << " type=\"" << getTypeName(node->getType()) << '"';
output << '>';
writeData(output, node->getStringValue());
output << "</" << name << '>' << endl;
node_has_value = true;
}
- // If there are children, write them next.
- if (nChildren > 0) {
+ // If there are children, write them next.
+ if( nChildren > (attr_node ? 1 : 0) )
+ {
doIndent(output, indent);
output << '<' << name;
- writeAtts(output, node, node_has_value);
+ writeAtts(output, node, node_has_value, attr_written ? attr_node : NULL);
output << '>' << endl;
- for (int i = 0; i < nChildren; i++)
- writeNode(output, node->getChild(i), write_all, indent + INDENT_STEP, archive_flag);
+ for(int i = 0; i < nChildren; i++)
+ {
+ if( node->getChild(i)->getNameString() != ATTR )
+ writeNode( output,
+ node->getChild(i),
+ write_all,
+ indent + INDENT_STEP,
+ archive_flag );
+ }
doIndent(output, indent);
output << "</" << name << '>' << endl;
}
*
* @param in The source property tree.
* @param out The destination property tree.
- * @param attr_value Only copy properties with given attribute values.
- * @param attr_mask Mask for attributes to be considered by attr_value
- * (default is 0 = attributes not considered, all
- * properties copied).
* @return true if all properties were copied, false if some failed
* (for example, if the property's value is tied read-only).
*/
bool
-copyProperties (const SGPropertyNode *in, SGPropertyNode *out,
- int attr_value, int attr_mask)
+copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
{
using namespace simgear;
bool retval = copyPropertyValue(in, out);
int nChildren = in->nChildren();
for (int i = 0; i < nChildren; i++) {
const SGPropertyNode * in_child = in->getChild(i);
- int mask = attr_mask;
- /* attributes have no meaning for nodes without values - except
- * the PRESERVE flag. So ignore them. */
- if (!in_child->hasValue())
- mask &= SGPropertyNode::PRESERVE;
- if ((in_child->getAttributes() & mask) == (attr_value & mask))
- {
- SGPropertyNode * out_child = out->getChild(in_child->getNameString(),
+ SGPropertyNode * out_child = out->getChild(in_child->getNameString(),
in_child->getIndex(),
false);
if (!out_child)
in_child->getIndex(),
true);
}
- else
- {
- mask = attr_mask;
- if (!out_child->hasValue())
- mask &= SGPropertyNode::PRESERVE;
- if ((out_child->getAttributes() & mask) != (attr_value & mask))
- out_child = NULL;
- }
- if (out_child &&
- (!copyProperties(in_child, out_child, attr_value, attr_mask)))
+
+ if (out_child && !copyProperties(in_child, out_child))
retval = false;
- }
}
return retval;