}
+/**
+ * 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.
*/
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);
}
+/**
+ * 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
{
}
}
+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),
}
entry * e = _data[index]->get_entry(key, true);
e->set_value(value);
+ value->add_linked_node(this);
}
void
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
void trace_write () const;
+ /**
+ * Remove this node from all nodes that link to it in their path cache.
+ */
+ void remove_from_path_caches();
+
+
class hash_table;
int _index;
SGPropertyNode * _parent;
vector<SGPropertyNode_ptr> _children;
vector<SGPropertyNode_ptr> _removedChildren;
+ vector<hash_table *> _linkedNodes;
mutable string _path;
mutable string _buffer;
hash_table * _path_cache;
vector <SGPropertyChangeListener *> * _listeners;
+ /**
+ * Register/unregister node that links to this node in its path cache.
+ */
+ void add_linked_node (hash_table * node) { _linkedNodes.push_back(node); }
+ bool remove_linked_node (hash_table * node);
+
+
\f
/**
- * A very simple hash table with no remove functionality.
+ * A very simple hash table.
*/
class hash_table {
public:
bucket ();
~bucket ();
entry * get_entry (const char * key, bool create = false);
- void erase(const char * key);
+ void erase (const char * key);
+ bool erase (SGPropertyNode * node);
private:
int _length;
entry ** _entries;
~hash_table ();
SGPropertyNode * get (const char * key);
void put (const char * key, SGPropertyNode * value);
- void erase(const char * key);
+ void erase (const char * key);
+ bool erase (SGPropertyNode * node);
private:
unsigned int hashcode (const char * key);