diff --git a/simgear/props/props_io.cxx b/simgear/props/props_io.cxx index ee432b33..69500977 100644 --- a/simgear/props/props_io.cxx +++ b/simgear/props/props_io.cxx @@ -854,4 +854,48 @@ copyPropertiesWithAttribute(const SGPropertyNode *in, SGPropertyNode *out, return true; } +namespace { + +// for normal recursion we want to call the predicate *before* creating children +bool _inner_copyPropertiesIf(const SGPropertyNode *in, SGPropertyNode *out, + PropertyPredicate predicate) +{ + bool retval = copyPropertyValue(in, out); + if (!retval) { + return false; + } + out->setAttributes( in->getAttributes() ); + + int nChildren = in->nChildren(); + for (int i = 0; i < nChildren; i++) { + const SGPropertyNode* in_child = in->getChild(i); + // skip this child + if (!predicate(in_child)) { + continue; + } + + SGPropertyNode* out_child = out->getChild(in_child->getNameString(), + in_child->getIndex(), + true); + + bool ok = copyPropertiesIf(in_child, out_child, predicate); + if (!ok) { + return false; + } + } // of children iteration + return true; +} + +} // of anonymous namespace + +bool copyPropertiesIf(const SGPropertyNode *in, SGPropertyNode *out, + PropertyPredicate predicate) +{ + // allow the *entire* copy to be a no-op + bool doCopy = predicate(in); + if (!doCopy) + return true; // doesn't count as failure + + return _inner_copyPropertiesIf(in, out, predicate); +} // end of props_io.cxx diff --git a/simgear/props/props_io.hxx b/simgear/props/props_io.hxx index b7f9dd86..17c28df3 100644 --- a/simgear/props/props_io.hxx +++ b/simgear/props/props_io.hxx @@ -17,6 +17,7 @@ #include #include +#include /** * Read properties from an XML input stream. @@ -67,6 +68,16 @@ bool copyProperties (const SGPropertyNode *in, SGPropertyNode *out); bool copyPropertiesWithAttribute(const SGPropertyNode *in, SGPropertyNode *out, SGPropertyNode::Attribute attr); +using PropertyPredicate = std::function; + +/** + * Copy properties, if the predicate returns true for the in node. + * If a parent node returns false, descendats will not be + * checked + */ +bool copyPropertiesIf(const SGPropertyNode *in, SGPropertyNode *out, + PropertyPredicate predicate); + #endif // __PROPS_IO_HXX // end of props_io.hxx