1
Fork 0
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:
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.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);

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> * <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

View file

@ -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);