Melchior FRANZ:
- 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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user