]> git.mxchange.org Git - simgear.git/commitdiff
Melchior FRANZ:
authorehofman <ehofman>
Mon, 27 Jun 2005 13:49:28 +0000 (13:49 +0000)
committerehofman <ehofman>
Mon, 27 Jun 2005 13:49:28 +0000 (13:49 +0000)
- introduce removeChildren() and removeChildren(name)  to remove all children
  or all with a given name
- let removeChild() and removeChildren() also remove child trees, and let them
  return a "dirty" boolean that indicates if one or more subnodes had to be
  kept because of refcounting (removeChild returned a SGPropertyNode_ptr before)
- make alias/unalias increase/decrease the refcounter
- don't remove refcounted or tied nodes

This patch makes the SGPropertyNode_ptr actually useful. Until today, they did
proper refcounting (except for aliases), but no other part did check this counter.

But SGPropertyNode_ptr aren't only useful for the first time, they are now
highly recommended for every place that relies on a node address, and wants
to "lock" it (so that removeChild(ren) will never try to remove them). This
is not guaranteed for SGPropertyNode* (and never was). Of course, that's not
an imminent problem, as only four places currently use removeChild(ren) and
these are careful to only remove their own data.

simgear/props/props.cxx
simgear/props/props.hxx

index dd8cb0c01fea7436eb50bf4be6bff8d733f0f48d..7c004b5a69ea60e0d23035918cd577f4f045a936 100644 (file)
@@ -778,6 +778,7 @@ SGPropertyNode::alias (SGPropertyNode * target)
   clearValue();
   _value.alias = target;
   _type = ALIAS;
+  _value.alias->incrementRef();
   return true;
 }
 
@@ -801,6 +802,7 @@ SGPropertyNode::unalias ()
   if (_type != ALIAS)
     return false;
   _type = NONE;
+  _value.alias->decrementRef();
   _value.alias = 0;
   return true;
 }
@@ -912,29 +914,69 @@ SGPropertyNode::getChildren (const char * name) const
 
 
 /**
- * Remove a child node
+ * Remove a child node, and all children that aren't referenced.
+ * "keep" does only apply to the outmost item. Returns "true" if
+ * not all nodes could be removed.
  */
-SGPropertyNode_ptr 
+bool
 SGPropertyNode::removeChild (const char * name, int index, bool keep)
 {
-  SGPropertyNode_ptr ret;
+  bool dirty = false;
   int pos = find_child(name, index, _children);
   if (pos >= 0) {
     vector<SGPropertyNode_ptr>::iterator it = _children.begin();
     it += pos;
-    SGPropertyNode_ptr node = _children[pos];
-    _children.erase(it);
-    if (keep) {
-      _removedChildren.push_back(node);
+    SGPropertyNode *node = _children[pos];
+    if (node->nChildren() && node->removeChildren())
+      dirty = true;
+
+    if (node->_count == 1 && !node->nChildren()) {
+      if (keep)
+        _removedChildren.push_back(node);
+
+      if (_path_cache)
+        _path_cache->erase(name); // EMH - TODO: Take "index" into account!
+
+      node->setAttribute(REMOVED, true);
+      node->clearValue();
+      fireChildRemoved(node);
+      _children.erase(it);
+    }
+  }
+  return dirty;
+}
+
+/**
+ * Remove all children nodes, or all with a given name. Returns
+ * "true" if not all nodes could be removed.
+ */
+bool
+SGPropertyNode::removeChildren(const char *name)
+{
+  bool dirty = false;
+  vector<SGPropertyNode_ptr>::iterator it = _children.end();
+  vector<SGPropertyNode_ptr>::iterator begin = _children.begin();
+  while (it-- != begin) {
+    SGPropertyNode *node = *it;
+    if (name && !compare_strings(node->getName(), name))
+      continue;
+
+    if (node->nChildren() && node->removeChildren())
+      dirty = true;
+
+    if (node->isTied() || node->_count != 1 || node->nChildren())
+      dirty = true;
+    else {
+      if (_path_cache)
+        _path_cache->erase(node->getName());
+
+      node->setAttribute(REMOVED, true);
+      node->clearValue();
+      fireChildRemoved(node);
+      _children.erase(it);
     }
-    if (_path_cache)
-       _path_cache->erase(name); // EMH - TODO: Take "index" into account!
-    node->setAttribute(REMOVED, true);
-    node->clearValue();
-    ret = node;
-    fireChildRemoved(node);
-  }
-  return ret;
+  }
+  return dirty;
 }
 
 
index 9ce7df4bf52524d315366884ae72b97b292da427..75da1a0c8e49fc93c279600c26d135c7613966db 100644 (file)
@@ -707,10 +707,16 @@ public:
 
 
   /**
-   * Remove a child node
+   * Remove a child node (returns true if at least one node had to remain,
+   * because it was tied, aliased, or refcounted through SGPropertyNode_ptr.
    */
-  SGPropertyNode_ptr removeChild (const char * name, int index = 0,
-                                  bool keep = true);
+  bool removeChild (const char * name, int index = 0, bool keep = true);
+
+
+  /**
+   * Remove all children nodes, or all with a given name.
+   */
+  bool removeChildren(const char * name = 0);
 
 
   //