1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-17 03:10:58 -08:00

Permitting tree traversals to abort early.

Copied from Perforce
 Change: 184511
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2014-02-23 14:42:23 +00:00
parent 59334b5e4f
commit f47100fd09
3 changed files with 23 additions and 12 deletions

View file

@ -667,7 +667,7 @@ void CBSIterate(CBS cbs, CBSIterateMethod iterate,
closure.iterate = iterate;
closure.closureP = closureP;
closure.closureS = closureS;
TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey,
(void)TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey,
CBSIterateVisit, &closure, 0);
cbsLeave(cbs);

View file

@ -155,13 +155,16 @@ Bool TreeInsert(Tree *treeReturn, Tree root, Tree node,
* <http://en.wikipedia.org/wiki/Tree_traversal#Morris_in-order_traversal_using_threading>
*
* The tree may not be modified during the traversal, and the traversal
* must complete. TODO: Is there a way to abort early?
* must complete.
*
* TreeTraverse is generally superior if comparisons are cheap.
*/
void TreeTraverseMorris(Tree tree, TreeVisitor visit,
Bool TreeTraverseMorris(Tree tree, TreeVisitor visit,
void *closureP, Size closureS)
{
Tree node;
Bool visiting = TRUE;
AVER(TreeCheck(tree));
AVER(FUNCHECK(visit));
@ -170,7 +173,8 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit,
node = tree;
while (node != TreeEMPTY) {
if (node->left == TreeEMPTY) {
(void)visit(node, closureP, closureS);
if (visiting)
visiting = visit(node, closureP, closureS);
node = node->right;
} else {
Tree pre = node->left;
@ -182,7 +186,10 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit,
}
if (pre->right == node) {
pre->right = TreeEMPTY;
(void)visit(node, closureP, closureS);
if (visiting)
visiting = visit(node, closureP, closureS);
else if (node == tree)
return FALSE;
node = node->right;
break;
}
@ -190,6 +197,8 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit,
}
}
}
return visiting;
}
@ -231,7 +240,7 @@ static Tree stepUpLeft(Tree node, Tree *parentIO)
return parent;
}
void TreeTraverse(Tree tree,
Bool TreeTraverse(Tree tree,
TreeCompare compare,
TreeKeyMethod key,
TreeVisitor visit, void *closureP, Size closureS)
@ -246,7 +255,7 @@ void TreeTraverse(Tree tree,
node = tree;
if (node == TreeEMPTY)
return;
return TRUE;
down:
if (TreeHasLeft(node)) {
@ -264,7 +273,7 @@ down:
up:
if (parent == TreeEMPTY)
return;
return TRUE;
if (compare(parent, key(node)) != CompareLESS) {
node = stepUpLeft(node, &parent);
goto up;
@ -279,7 +288,7 @@ up:
abort:
if (parent == TreeEMPTY)
return;
return FALSE;
if (compare(parent, key(node)) != CompareLESS)
node = stepUpLeft(node, &parent);
else

View file

@ -2,6 +2,8 @@
*
* $Id$
* Copyright (C) 2014 Ravenbrook Limited. See end of file for license.
*
* Simple binary trees, for use as building blocks.
*/
#ifndef tree_h
@ -77,11 +79,11 @@ extern Bool TreeInsert(Tree *treeReturn, Tree root, Tree node,
TreeKey key, TreeCompare compare);
typedef Bool TreeVisitor(Tree tree, void *closureP, Size closureS);
extern void TreeTraverse(Tree tree,
extern Bool TreeTraverse(Tree tree,
TreeCompare compare,
TreeKeyMethod key,
TreeVisitor visit, void *closureP, Size closureS);
extern void TreeTraverseMorris(Tree tree, TreeVisitor visit,
extern Bool TreeTraverseMorris(Tree tree, TreeVisitor visit,
void *closureP, Size closureS);
extern void TreeRotateLeft(Tree *nodeIO);