]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/props.cxx
Maik JUSTUS:
[simgear.git] / simgear / props / props.cxx
index 976ba30d322a2b997e5c958d1e918375f1c7aef8..fe3001129f475e27b1f708933e1023ae06ec5bc4 100644 (file)
@@ -250,7 +250,7 @@ compare_strings (const char * s1, const char * s2)
  * Locate a child node by name and index.
  */
 static int
-find_child (const char * name, int index, vector<SGPropertyNode_ptr> nodes)
+find_child (const char * name, int index, const vector<SGPropertyNode_ptr>& nodes)
 {
   int nNodes = nodes.size();
   for (int i = 0; i < nNodes; i++) {
@@ -749,9 +749,20 @@ SGPropertyNode::SGPropertyNode (const char * name,
  */
 SGPropertyNode::~SGPropertyNode ()
 {
+  // zero out all parent pointers, else they might be dangling
+  for (unsigned i = 0; i < _children.size(); ++i)
+    _children[i]->_parent = 0;
+  for (unsigned i = 0; i < _removedChildren.size(); ++i)
+    _removedChildren[i]->_parent = 0;
   delete _path_cache;
   clearValue();
-  delete _listeners;
+
+  if (_listeners) {
+    vector<SGPropertyChangeListener*>::iterator it;
+    for (it = _listeners->begin(); it != _listeners->end(); ++it)
+      (*it)->unregister_property(this);
+    delete _listeners;
+  }
 }
 
 
@@ -899,6 +910,21 @@ SGPropertyNode::getChildren (const char * name) const
 }
 
 
+/**
+ * Remove this node from all nodes that link to it in their path cache.
+ */
+void
+SGPropertyNode::remove_from_path_caches ()
+{
+  for (unsigned int i = 0; i < _linkedNodes.size(); i++)
+    _linkedNodes[i]->erase(this);
+
+  _linkedNodes.clear();
+  for (unsigned int i = 0; i < _children.size(); ++i)
+    _children[i]->remove_from_path_caches();
+}
+
+
 /**
  * Remove child by position.
  */
@@ -906,7 +932,7 @@ SGPropertyNode_ptr
 SGPropertyNode::removeChild (int pos, bool keep)
 {
   SGPropertyNode_ptr node;
-  if (pos < 0 || pos >= _children.size())
+  if (pos < 0 || pos >= (int)_children.size())
     return node;
 
   vector<SGPropertyNode_ptr>::iterator it = _children.begin();
@@ -916,8 +942,8 @@ SGPropertyNode::removeChild (int pos, bool keep)
   if (keep) {
     _removedChildren.push_back(node);
   }
-  if (_path_cache)
-     _path_cache->erase(node->getName()); // EMH - TODO: Take "index" into account!
+
+  node->remove_from_path_caches();
   node->setAttribute(REMOVED, true);
   node->clearValue();
   fireChildRemoved(node);
@@ -956,6 +982,24 @@ SGPropertyNode::removeChildren (const char * name, bool keep)
 }
 
 
+/**
+  * Remove a linked node.
+  */
+bool
+SGPropertyNode::remove_linked_node (hash_table * node)
+{
+  for (unsigned int i = 0; i < _linkedNodes.size(); i++) {
+    if (_linkedNodes[i] == node) {
+      vector<hash_table *>::iterator it = _linkedNodes.begin();
+      it += i;
+      _linkedNodes.erase(it);
+      return true;
+    }
+  }
+  return false;
+}
+
+
 const char *
 SGPropertyNode::getDisplayName (bool simplify) const
 {
@@ -2199,6 +2243,20 @@ SGPropertyNode::hash_table::bucket::erase (const char * key)
   }
 }
 
+bool
+SGPropertyNode::hash_table::bucket::erase (SGPropertyNode * node)
+{
+  for (int i = 0; i < _length; i++) {
+    if (_entries[i]->get_value() == node) {
+      for (++i; i < _length; i++) {
+        _entries[i-1] = _entries[i];
+      }
+      _length--;
+      return true;
+    }
+  }
+  return false;
+}
 
 SGPropertyNode::hash_table::hash_table ()
   : _data_length(0),
@@ -2243,6 +2301,7 @@ SGPropertyNode::hash_table::put (const char * key, SGPropertyNode * value)
   }
   entry * e = _data[index]->get_entry(key, true);
   e->set_value(value);
+  value->add_linked_node(this);
 }
 
 void
@@ -2253,7 +2312,19 @@ SGPropertyNode::hash_table::erase (const char * key)
   unsigned int index = hashcode(key) % _data_length;
   if (_data[index] == 0)
     return;
+  _data[index]->get_entry(key, true)->get_value()->remove_linked_node(this);
   _data[index]->erase(key);
+  _data[index] = 0;
+}
+
+bool
+SGPropertyNode::hash_table::erase (SGPropertyNode * node)
+{
+  for (unsigned int d = 0; d < _data_length; d++)
+    if (_data[d] && _data[d]->erase(node))
+      return true;
+
+  return false;
 }
 
 unsigned int
@@ -2275,12 +2346,8 @@ SGPropertyNode::hash_table::hashcode (const char * key)
 
 SGPropertyChangeListener::~SGPropertyChangeListener ()
 {
-                               // This will come back and remove
-                               // the current item each time.  Is
-                               // that OK?
-  vector<SGPropertyNode *>::iterator it;
-  for (it = _properties.begin(); it != _properties.end(); it++)
-    (*it)->removeChangeListener(this);
+  for (int i = _properties.size() - 1; i >= 0; i--)
+    _properties[i]->removeChangeListener(this);
 }
 
 void