mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-16 19:00:55 -08:00
Permitting tree traversals to abort early.
Copied from Perforce Change: 184511 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
59334b5e4f
commit
f47100fd09
3 changed files with 23 additions and 12 deletions
|
|
@ -667,7 +667,7 @@ void CBSIterate(CBS cbs, CBSIterateMethod iterate,
|
||||||
closure.iterate = iterate;
|
closure.iterate = iterate;
|
||||||
closure.closureP = closureP;
|
closure.closureP = closureP;
|
||||||
closure.closureS = closureS;
|
closure.closureS = closureS;
|
||||||
TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey,
|
(void)TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey,
|
||||||
CBSIterateVisit, &closure, 0);
|
CBSIterateVisit, &closure, 0);
|
||||||
|
|
||||||
cbsLeave(cbs);
|
cbsLeave(cbs);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
* <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
|
* 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)
|
void *closureP, Size closureS)
|
||||||
{
|
{
|
||||||
Tree node;
|
Tree node;
|
||||||
|
Bool visiting = TRUE;
|
||||||
|
|
||||||
AVER(TreeCheck(tree));
|
AVER(TreeCheck(tree));
|
||||||
AVER(FUNCHECK(visit));
|
AVER(FUNCHECK(visit));
|
||||||
|
|
@ -170,7 +173,8 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit,
|
||||||
node = tree;
|
node = tree;
|
||||||
while (node != TreeEMPTY) {
|
while (node != TreeEMPTY) {
|
||||||
if (node->left == TreeEMPTY) {
|
if (node->left == TreeEMPTY) {
|
||||||
(void)visit(node, closureP, closureS);
|
if (visiting)
|
||||||
|
visiting = visit(node, closureP, closureS);
|
||||||
node = node->right;
|
node = node->right;
|
||||||
} else {
|
} else {
|
||||||
Tree pre = node->left;
|
Tree pre = node->left;
|
||||||
|
|
@ -182,7 +186,10 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit,
|
||||||
}
|
}
|
||||||
if (pre->right == node) {
|
if (pre->right == node) {
|
||||||
pre->right = TreeEMPTY;
|
pre->right = TreeEMPTY;
|
||||||
(void)visit(node, closureP, closureS);
|
if (visiting)
|
||||||
|
visiting = visit(node, closureP, closureS);
|
||||||
|
else if (node == tree)
|
||||||
|
return FALSE;
|
||||||
node = node->right;
|
node = node->right;
|
||||||
break;
|
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;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeTraverse(Tree tree,
|
Bool TreeTraverse(Tree tree,
|
||||||
TreeCompare compare,
|
TreeCompare compare,
|
||||||
TreeKeyMethod key,
|
TreeKeyMethod key,
|
||||||
TreeVisitor visit, void *closureP, Size closureS)
|
TreeVisitor visit, void *closureP, Size closureS)
|
||||||
|
|
@ -246,7 +255,7 @@ void TreeTraverse(Tree tree,
|
||||||
node = tree;
|
node = tree;
|
||||||
|
|
||||||
if (node == TreeEMPTY)
|
if (node == TreeEMPTY)
|
||||||
return;
|
return TRUE;
|
||||||
|
|
||||||
down:
|
down:
|
||||||
if (TreeHasLeft(node)) {
|
if (TreeHasLeft(node)) {
|
||||||
|
|
@ -264,7 +273,7 @@ down:
|
||||||
|
|
||||||
up:
|
up:
|
||||||
if (parent == TreeEMPTY)
|
if (parent == TreeEMPTY)
|
||||||
return;
|
return TRUE;
|
||||||
if (compare(parent, key(node)) != CompareLESS) {
|
if (compare(parent, key(node)) != CompareLESS) {
|
||||||
node = stepUpLeft(node, &parent);
|
node = stepUpLeft(node, &parent);
|
||||||
goto up;
|
goto up;
|
||||||
|
|
@ -279,7 +288,7 @@ up:
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
if (parent == TreeEMPTY)
|
if (parent == TreeEMPTY)
|
||||||
return;
|
return FALSE;
|
||||||
if (compare(parent, key(node)) != CompareLESS)
|
if (compare(parent, key(node)) != CompareLESS)
|
||||||
node = stepUpLeft(node, &parent);
|
node = stepUpLeft(node, &parent);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
* Copyright (C) 2014 Ravenbrook Limited. See end of file for license.
|
* Copyright (C) 2014 Ravenbrook Limited. See end of file for license.
|
||||||
|
*
|
||||||
|
* Simple binary trees, for use as building blocks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef tree_h
|
#ifndef tree_h
|
||||||
|
|
@ -77,11 +79,11 @@ extern Bool TreeInsert(Tree *treeReturn, Tree root, Tree node,
|
||||||
TreeKey key, TreeCompare compare);
|
TreeKey key, TreeCompare compare);
|
||||||
|
|
||||||
typedef Bool TreeVisitor(Tree tree, void *closureP, Size closureS);
|
typedef Bool TreeVisitor(Tree tree, void *closureP, Size closureS);
|
||||||
extern void TreeTraverse(Tree tree,
|
extern Bool TreeTraverse(Tree tree,
|
||||||
TreeCompare compare,
|
TreeCompare compare,
|
||||||
TreeKeyMethod key,
|
TreeKeyMethod key,
|
||||||
TreeVisitor visit, void *closureP, Size closureS);
|
TreeVisitor visit, void *closureP, Size closureS);
|
||||||
extern void TreeTraverseMorris(Tree tree, TreeVisitor visit,
|
extern Bool TreeTraverseMorris(Tree tree, TreeVisitor visit,
|
||||||
void *closureP, Size closureS);
|
void *closureP, Size closureS);
|
||||||
|
|
||||||
extern void TreeRotateLeft(Tree *nodeIO);
|
extern void TreeRotateLeft(Tree *nodeIO);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue