1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-06 03:40:56 -08:00

Implementing splayfindlast to match splayfindfirst. oops.

Copied from Perforce
 Change: 184578
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2014-02-27 16:03:55 +00:00
parent e6d1db24b6
commit 6b17c88c69

View file

@ -892,6 +892,10 @@ static Compare SplayFindLastCompare(void *key, SplayNode node)
* The given callbacks testNode and testTree detect this property in
* a single node or a sub-tree rooted at a node, and both receive the
* arbitrary closures closureP and closureS.
*
* TODO: This repeatedly splays failed matches to the root and rotates
* them, so it could have quite an unbalancing effect if size is small.
* Think about a better search, perhaps using TreeTraverse?
*/
Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree,
@ -926,6 +930,7 @@ Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree,
while (!found) {
SplayNode oldRoot, newRoot;
/* FIXME: Rename to "seen" and "not yet seen" or something. */
oldRoot = SplayTreeRoot(tree);
newRoot = SplayNodeRightChild(oldRoot);
@ -966,6 +971,7 @@ Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree,
{
SplayNode node;
SplayFindClosureStruct closureStruct;
Bool found;
AVER(nodeReturn != NULL);
AVERT(SplayTree, tree);
@ -983,13 +989,40 @@ Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree,
closureStruct.testTree = testTree;
closureStruct.tree = tree;
if (SplaySplay(&node, tree, (void *)&closureStruct,
&SplayFindLastCompare)) {
*nodeReturn = node;
return TRUE;
} else {
return FALSE;
found = SplaySplay(&node, tree, (void *)&closureStruct,
&SplayFindLastCompare) && closureStruct.found;
while (!found) {
SplayNode oldRoot, newRoot;
oldRoot = SplayTreeRoot(tree);
newRoot = SplayNodeLeftChild(oldRoot);
if (newRoot == NULL || !(*testTree)(tree, newRoot, closureP, closureS))
return FALSE; /* no suitable nodes in the rest of the tree */
/* Temporarily chop off the right half-tree, inclusive of root,
so that the search excludes any nodes we've seen already. */
SplayTreeSetRoot(tree, newRoot);
SplayNodeSetLeftChild(oldRoot, NULL);
found = SplaySplay(&node, tree, (void *)&closureStruct,
&SplayFindLastCompare) && closureStruct.found;
/* Restore the right tree, then rotate right so that the node we
just splayed is at the root. Update both. */
newRoot = SplayTreeRoot(tree);
SplayNodeSetLeftChild(oldRoot, newRoot);
SplayTreeSetRoot(tree, oldRoot);
SplayRotateRight(&tree->root, tree);
if (tree->updateNode != NULL) {
SplayNodeUpdate(tree, oldRoot);
SplayNodeUpdate(tree, newRoot);
}
}
*nodeReturn = node;
return TRUE;
}