X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fprops%2Fprops.cxx;h=fe3001129f475e27b1f708933e1023ae06ec5bc4;hb=8663c265d8da5d1401e3fb2d11c4bd274fb0794f;hp=976ba30d322a2b997e5c958d1e918375f1c7aef8;hpb=930a84b459d4f6abb444734a04ede3c4accaef9c;p=simgear.git diff --git a/simgear/props/props.cxx b/simgear/props/props.cxx index 976ba30d..fe300112 100644 --- a/simgear/props/props.cxx +++ b/simgear/props/props.cxx @@ -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 nodes) +find_child (const char * name, int index, const vector& 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::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::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::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::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