]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libfrog/avl64.c
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "platform_defs.h"
29 avl64tree_desc_t
*tree
,
32 avl64node_t
*back
= np
->avl_back
;
33 avl64node_t
*forw
= np
->avl_forw
;
34 avl64node_t
*nextino
= np
->avl_nextino
;
35 int bal
= np
->avl_balance
;
37 ASSERT(bal
!= AVL_BALANCE
|| (!back
&& !forw
) || (back
&& forw
));
38 ASSERT(bal
!= AVL_FORW
|| forw
);
39 ASSERT(bal
!= AVL_BACK
|| back
);
42 ASSERT(AVL_START(tree
, np
) < AVL_START(tree
, forw
));
43 ASSERT(np
->avl_forw
->avl_parent
== np
);
44 ASSERT(back
|| bal
== AVL_FORW
);
46 ASSERT(bal
!= AVL_FORW
);
47 ASSERT(bal
== AVL_BALANCE
|| back
);
48 ASSERT(bal
== AVL_BACK
|| !back
);
52 ASSERT(AVL_START(tree
, np
) > AVL_START(tree
, back
));
53 ASSERT(np
->avl_back
->avl_parent
== np
);
54 ASSERT(forw
|| bal
== AVL_BACK
);
56 ASSERT(bal
!= AVL_BACK
);
57 ASSERT(bal
== AVL_BALANCE
|| forw
);
58 ASSERT(bal
== AVL_FORW
|| !forw
);
64 ASSERT(AVL_END(tree
, np
) <= AVL_START(tree
, nextino
));
69 avl64tree_desc_t
*tree
,
72 avl64node_t
*nlast
, *nnext
, *np
;
78 ASSERT(!nnext
|| nnext
->avl_parent
== NULL
);
82 avl64_checknode(tree
, nnext
);
83 end
= AVL_END(tree
, nnext
);
86 if ((np
= nnext
->avl_forw
) && np
!= nlast
) {
91 nnext
= nnext
->avl_parent
;
97 if (np
= nnext
->avl_back
) {
98 if (AVL_END(tree
, np
) > offset
) {
105 nnext
= nnext
->avl_forw
;
107 nnext
= np
->avl_parent
;
112 #else /* ! AVL_DEBUG */
113 #define avl64_checktree(t,x)
114 #endif /* AVL_DEBUG */
118 * Reset balance for np up through tree.
119 * ``direction'' is the way that np's balance
120 * is headed after the deletion of one of its children --
121 * e.g., deleting a avl_forw child sends avl_balance toward AVL_BACK.
122 * Called only when deleting a node from the tree.
126 avl64tree_desc_t
*tree
,
130 avl64node_t
**rootp
= &tree
->avl_root
;
137 ASSERT(direction
== AVL_BACK
|| direction
== AVL_FORW
);
139 if (np
->avl_balance
== AVL_BALANCE
) {
140 np
->avl_balance
= direction
;
144 parent
= np
->avl_parent
;
147 * If balance is being restored, no local node
148 * reorganization is necessary, but may be at
149 * a higher node. Reset direction and continue.
151 if (direction
!= np
->avl_balance
) {
152 np
->avl_balance
= AVL_BALANCE
;
154 if (parent
->avl_forw
== np
)
155 direction
= AVL_BACK
;
157 direction
= AVL_FORW
;
166 * Imbalance. If a avl_forw node was removed, direction
167 * (and, by reduction, np->avl_balance) is/was AVL_BACK.
169 if (np
->avl_balance
== AVL_BACK
) {
171 ASSERT(direction
== AVL_BACK
);
172 child
= np
->avl_back
;
173 bal
= child
->avl_balance
;
175 if (bal
!= AVL_FORW
) /* single LL */ {
177 * np gets pushed down to lesser child's
182 * child-> B deleted A -D
185 cmn_err(CE_CONT, "!LL delete b 0x%x c 0x%x\n",
189 np
->avl_back
= child
->avl_forw
;
191 child
->avl_forw
->avl_parent
= np
;
192 child
->avl_forw
= np
;
195 if (parent
->avl_forw
== np
) {
196 parent
->avl_forw
= child
;
197 direction
= AVL_BACK
;
199 ASSERT(parent
->avl_back
== np
);
200 parent
->avl_back
= child
;
201 direction
= AVL_FORW
;
204 ASSERT(*rootp
== np
);
207 np
->avl_parent
= child
;
208 child
->avl_parent
= parent
;
210 if (bal
== AVL_BALANCE
) {
211 np
->avl_balance
= AVL_BACK
;
212 child
->avl_balance
= AVL_FORW
;
215 np
->avl_balance
= AVL_BALANCE
;
216 child
->avl_balance
= AVL_BALANCE
;
218 avl64_checktree(tree
, *rootp
);
223 /* child->avl_balance == AVL_FORW double LR rotation
225 * child's avl_forw node gets promoted up, along with
226 * its avl_forw subtree
235 cmn_err(CE_CONT, "!LR delete b 0x%x c 0x%x t 0x%x\n",
236 np, child, child->avl_forw);
239 tmp
= child
->avl_forw
;
240 bal
= tmp
->avl_balance
;
242 child
->avl_forw
= tmp
->avl_back
;
244 tmp
->avl_back
->avl_parent
= child
;
246 tmp
->avl_back
= child
;
247 child
->avl_parent
= tmp
;
249 np
->avl_back
= tmp
->avl_forw
;
251 tmp
->avl_forw
->avl_parent
= np
;
255 child
->avl_balance
= AVL_BACK
;
257 child
->avl_balance
= AVL_BALANCE
;
260 np
->avl_balance
= AVL_FORW
;
262 np
->avl_balance
= AVL_BALANCE
;
267 ASSERT(np
->avl_balance
== AVL_FORW
&& direction
== AVL_FORW
);
269 child
= np
->avl_forw
;
270 bal
= child
->avl_balance
;
272 if (bal
!= AVL_BACK
) /* single RR */ {
274 * np gets pushed down to greater child's
279 * deleted D <-child +B E
282 cmn_err(CE_CONT, "!RR delete b 0x%x c 0x%x\n",
286 np
->avl_forw
= child
->avl_back
;
288 child
->avl_back
->avl_parent
= np
;
289 child
->avl_back
= np
;
292 if (parent
->avl_forw
== np
) {
293 parent
->avl_forw
= child
;
294 direction
= AVL_BACK
;
296 ASSERT(parent
->avl_back
== np
);
297 parent
->avl_back
= child
;
298 direction
= AVL_FORW
;
301 ASSERT(*rootp
== np
);
304 np
->avl_parent
= child
;
305 child
->avl_parent
= parent
;
307 if (bal
== AVL_BALANCE
) {
308 np
->avl_balance
= AVL_FORW
;
309 child
->avl_balance
= AVL_BACK
;
312 np
->avl_balance
= AVL_BALANCE
;
313 child
->avl_balance
= AVL_BALANCE
;
315 avl64_checktree(tree
, *rootp
);
320 /* child->avl_balance == AVL_BACK double RL rotation
321 cmn_err(CE_CONT, "!RL delete b 0x%x c 0x%x t 0x%x\n",
322 np, child, child->avl_back);
325 tmp
= child
->avl_back
;
326 bal
= tmp
->avl_balance
;
328 child
->avl_back
= tmp
->avl_forw
;
330 tmp
->avl_forw
->avl_parent
= child
;
332 tmp
->avl_forw
= child
;
333 child
->avl_parent
= tmp
;
335 np
->avl_forw
= tmp
->avl_back
;
337 tmp
->avl_back
->avl_parent
= np
;
341 child
->avl_balance
= AVL_FORW
;
343 child
->avl_balance
= AVL_BALANCE
;
346 np
->avl_balance
= AVL_BACK
;
348 np
->avl_balance
= AVL_BALANCE
;
350 np
->avl_parent
= tmp
;
351 tmp
->avl_balance
= AVL_BALANCE
;
352 tmp
->avl_parent
= parent
;
355 if (parent
->avl_forw
== np
) {
356 parent
->avl_forw
= tmp
;
357 direction
= AVL_BACK
;
359 ASSERT(parent
->avl_back
== np
);
360 parent
->avl_back
= tmp
;
361 direction
= AVL_FORW
;
364 ASSERT(*rootp
== np
);
370 avl64_checktree(tree
, *rootp
);
375 * Remove node from tree.
376 * avl_delete does the local tree manipulations,
377 * calls retreat() to rebalance tree up to its root.
381 avl64tree_desc_t
*tree
,
384 avl64node_t
*forw
= np
->avl_forw
;
385 avl64node_t
*back
= np
->avl_back
;
386 avl64node_t
*parent
= np
->avl_parent
;
392 * a left child exits, then greatest left descendent's nextino
393 * is pointing to np; make it point to np->nextino.
395 nnext
= np
->avl_back
;
397 if (!nnext
->avl_forw
)
398 break; /* can't find anything bigger */
399 nnext
= nnext
->avl_forw
;
402 if (np
->avl_parent
) {
404 * find nearest ancestor with lesser value. That ancestor's
405 * nextino is pointing to np; make it point to np->nextino
407 nnext
= np
->avl_parent
;
409 if (AVL_END(tree
, nnext
) <= AVL_END(tree
, np
))
411 nnext
= nnext
->avl_parent
;
417 ASSERT(nnext
->avl_nextino
== np
);
418 nnext
->avl_nextino
= np
->avl_nextino
;
420 * Something preceeds np; np cannot be firstino.
422 ASSERT(tree
->avl_firstino
!= np
);
426 * Nothing preceeding np; after deletion, np's nextino
427 * is firstino of tree.
429 ASSERT(tree
->avl_firstino
== np
);
430 tree
->avl_firstino
= np
->avl_nextino
;
435 * Degenerate cases...
445 forw
->avl_parent
= parent
;
447 if (parent
->avl_forw
== np
) {
448 parent
->avl_forw
= forw
;
449 retreat(tree
, parent
, AVL_BACK
);
451 ASSERT(parent
->avl_back
== np
);
452 parent
->avl_back
= forw
;
453 retreat(tree
, parent
, AVL_FORW
);
456 ASSERT(tree
->avl_root
== np
);
457 tree
->avl_root
= forw
;
459 avl64_checktree(tree
, tree
->avl_root
);
464 * Harder case: children on both sides.
465 * If back's avl_forw pointer is null, just have back
466 * inherit np's avl_forw tree, remove np from the tree
467 * and adjust balance counters starting at back.
469 * np-> xI xH (befor retreat())
477 if ((forw
= back
->avl_forw
) == NULL
) {
479 * AVL_FORW retreat below will set back's
480 * balance to AVL_BACK.
482 back
->avl_balance
= np
->avl_balance
;
483 back
->avl_forw
= forw
= np
->avl_forw
;
484 forw
->avl_parent
= back
;
485 back
->avl_parent
= parent
;
488 if (parent
->avl_forw
== np
)
489 parent
->avl_forw
= back
;
491 ASSERT(parent
->avl_back
== np
);
492 parent
->avl_back
= back
;
495 ASSERT(tree
->avl_root
== np
);
496 tree
->avl_root
= back
;
500 * back is taking np's place in the tree, and
501 * has therefore lost a avl_back node (itself).
503 retreat(tree
, back
, AVL_FORW
);
504 avl64_checktree(tree
, tree
->avl_root
);
509 * Hardest case: children on both sides, and back's
510 * avl_forw pointer isn't null. Find the immediately
511 * inferior buffer by following back's avl_forw line
512 * to the end, then have it inherit np's avl_forw tree.
516 * G J back-> G J (before retreat())
524 while ((back
= forw
->avl_forw
))
528 * Will be adjusted by retreat() below.
530 forw
->avl_balance
= np
->avl_balance
;
533 * forw inherits np's avl_forw...
535 forw
->avl_forw
= np
->avl_forw
;
536 np
->avl_forw
->avl_parent
= forw
;
539 * ... forw's parent gets forw's avl_back...
541 back
= forw
->avl_parent
;
542 back
->avl_forw
= forw
->avl_back
;
544 forw
->avl_back
->avl_parent
= back
;
547 * ... forw gets np's avl_back...
549 forw
->avl_back
= np
->avl_back
;
550 np
->avl_back
->avl_parent
= forw
;
553 * ... and forw gets np's parent.
555 forw
->avl_parent
= parent
;
558 if (parent
->avl_forw
== np
)
559 parent
->avl_forw
= forw
;
561 parent
->avl_back
= forw
;
563 ASSERT(tree
->avl_root
== np
);
564 tree
->avl_root
= forw
;
568 * What used to be forw's parent is the starting
569 * point for rebalancing. It has lost a avl_forw node.
571 retreat(tree
, back
, AVL_BACK
);
572 avl64_checktree(tree
, tree
->avl_root
);
579 * Given range r [start, end), find any range which is contained in r.
580 * if checklen is non-zero, then only ranges of non-zero length are
581 * considered in finding a match.
585 avl64tree_desc_t
*tree
,
590 avl64node_t
*np
= tree
->avl_root
;
592 /* np = avl64_findadjacent(tree, start, AVL_SUCCEED); */
594 if (start
< AVL_START(tree
, np
)) {
599 /* if we were to add node with start, would
600 * have a growth of AVL_BACK
602 /* if succeeding node is needed, this is it.
606 if (start
>= AVL_END(tree
, np
)) {
611 /* if we were to add node with start, would
612 * have a growth of AVL_FORW;
614 /* we are looking for a succeeding node;
617 np
= np
->avl_nextino
;
620 /* AVL_START(tree, np) <= start < AVL_END(tree, np) */
624 if (checklen
== AVL_INCLUDE_ZEROLEN
) {
625 if (end
<= AVL_START(tree
, np
)) {
626 /* something follows start, but is
627 * is entierly after the range (end)
631 /* np may stradle [start, end) */
635 * find non-zero length region
637 while (np
&& (AVL_END(tree
, np
) - AVL_START(tree
, np
) == 0)
638 && (AVL_START(tree
, np
) < end
))
639 np
= np
->avl_nextino
;
641 if ((np
== NULL
) || (AVL_START(tree
, np
) >= end
))
646 * nothing succeeds start, all existing ranges are before start.
653 * Returns a pointer to range which contains value.
657 avl64tree_desc_t
*tree
,
660 avl64node_t
*np
= tree
->avl_root
;
663 if (value
< AVL_START(tree
, np
)) {
667 if (value
>= AVL_END(tree
, np
)) {
671 ASSERT(AVL_START(tree
, np
) <= value
&&
672 value
< AVL_END(tree
, np
));
680 * Returns a pointer to node which contains exact value.
684 avl64tree_desc_t
*tree
,
687 avl64node_t
*np
= tree
->avl_root
;
691 nvalue
= AVL_START(tree
, np
);
692 if (value
< nvalue
) {
696 if (value
== nvalue
) {
706 * Balance buffer AVL tree after attaching a new node to root.
707 * Called only by avl_insert.
716 * At this point, np points to the node to which
717 * a new node has been attached. All that remains is to
718 * propagate avl_balance up the tree.
721 avl64node_t
*parent
= np
->avl_parent
;
724 CERT(growth
== AVL_BACK
|| growth
== AVL_FORW
);
727 * If the buffer was already balanced, set avl_balance
728 * to the new direction. Continue if there is a
729 * parent after setting growth to reflect np's
730 * relation to its parent.
732 if (np
->avl_balance
== AVL_BALANCE
) {
733 np
->avl_balance
= growth
;
735 if (parent
->avl_forw
== np
)
738 ASSERT(parent
->avl_back
== np
);
748 if (growth
!= np
->avl_balance
) {
750 * Subtree is now balanced -- no net effect
751 * in the size of the subtree, so leave.
753 np
->avl_balance
= AVL_BALANCE
;
757 if (growth
== AVL_BACK
) {
759 child
= np
->avl_back
;
760 CERT(np
->avl_balance
== AVL_BACK
&& child
);
762 if (child
->avl_balance
== AVL_BACK
) { /* single LL */
764 * ``A'' just got inserted;
765 * np points to ``E'', child to ``C'',
766 * and it is already AVL_BACK --
767 * child will get promoted to top of subtree.
777 Note that child->avl_parent and
778 avl_balance get set in common code.
780 np
->avl_parent
= child
;
781 np
->avl_balance
= AVL_BALANCE
;
782 np
->avl_back
= child
->avl_forw
;
784 child
->avl_forw
->avl_parent
= np
;
785 child
->avl_forw
= np
;
790 * child's avl_forw node gets promoted to
791 * the top of the subtree.
802 avl64node_t
*tmp
= child
->avl_forw
;
804 CERT(child
->avl_balance
== AVL_FORW
&& tmp
);
806 child
->avl_forw
= tmp
->avl_back
;
808 tmp
->avl_back
->avl_parent
= child
;
810 tmp
->avl_back
= child
;
811 child
->avl_parent
= tmp
;
813 np
->avl_back
= tmp
->avl_forw
;
815 tmp
->avl_forw
->avl_parent
= np
;
818 np
->avl_parent
= tmp
;
820 if (tmp
->avl_balance
== AVL_BACK
)
821 np
->avl_balance
= AVL_FORW
;
823 np
->avl_balance
= AVL_BALANCE
;
825 if (tmp
->avl_balance
== AVL_FORW
)
826 child
->avl_balance
= AVL_BACK
;
828 child
->avl_balance
= AVL_BALANCE
;
831 * Set child to point to tmp since it is
832 * now the top of the subtree, and will
833 * get attached to the subtree parent in
834 * the common code below.
839 } else /* growth == AVL_BACK */ {
842 * This code is the mirror image of AVL_FORW above.
845 child
= np
->avl_forw
;
846 CERT(np
->avl_balance
== AVL_FORW
&& child
);
848 if (child
->avl_balance
== AVL_FORW
) { /* single RR */
849 np
->avl_parent
= child
;
850 np
->avl_balance
= AVL_BALANCE
;
851 np
->avl_forw
= child
->avl_back
;
853 child
->avl_back
->avl_parent
= np
;
854 child
->avl_back
= np
;
859 avl64node_t
*tmp
= child
->avl_back
;
861 ASSERT(child
->avl_balance
== AVL_BACK
&& tmp
);
863 child
->avl_back
= tmp
->avl_forw
;
865 tmp
->avl_forw
->avl_parent
= child
;
867 tmp
->avl_forw
= child
;
868 child
->avl_parent
= tmp
;
870 np
->avl_forw
= tmp
->avl_back
;
872 tmp
->avl_back
->avl_parent
= np
;
875 np
->avl_parent
= tmp
;
877 if (tmp
->avl_balance
== AVL_FORW
)
878 np
->avl_balance
= AVL_BACK
;
880 np
->avl_balance
= AVL_BALANCE
;
882 if (tmp
->avl_balance
== AVL_BACK
)
883 child
->avl_balance
= AVL_FORW
;
885 child
->avl_balance
= AVL_BALANCE
;
891 child
->avl_parent
= parent
;
892 child
->avl_balance
= AVL_BALANCE
;
895 if (parent
->avl_back
== np
)
896 parent
->avl_back
= child
;
898 parent
->avl_forw
= child
;
900 ASSERT(*rootp
== np
);
910 avl64_insert_find_growth(
911 avl64tree_desc_t
*tree
,
912 uint64_t start
, /* range start at start, */
913 uint64_t end
, /* exclusive */
914 int *growthp
) /* OUT */
916 avl64node_t
*root
= tree
->avl_root
;
920 ASSERT(np
); /* caller ensures that there is atleast one node in tree */
923 CERT(np
->avl_parent
|| root
== np
);
924 CERT(!np
->avl_parent
|| root
!= np
);
925 CERT(!(np
->avl_back
) || np
->avl_back
->avl_parent
== np
);
926 CERT(!(np
->avl_forw
) || np
->avl_forw
->avl_parent
== np
);
927 CERT(np
->avl_balance
!= AVL_FORW
|| np
->avl_forw
);
928 CERT(np
->avl_balance
!= AVL_BACK
|| np
->avl_back
);
929 CERT(np
->avl_balance
!= AVL_BALANCE
||
930 np
->avl_back
== NULL
|| np
->avl_forw
);
931 CERT(np
->avl_balance
!= AVL_BALANCE
||
932 np
->avl_forw
== NULL
|| np
->avl_back
);
934 if (AVL_START(tree
, np
) >= end
) {
943 if (AVL_END(tree
, np
) <= start
) {
951 /* found exact match -- let caller decide if it is an error */
960 avl64tree_desc_t
*tree
,
962 avl64node_t
*newnode
,
966 uint64_t start
= AVL_START(tree
, newnode
);
968 if (growth
== AVL_BACK
) {
970 parent
->avl_back
= newnode
;
972 * we are growing to the left; previous in-order to newnode is
973 * closest ancestor with lesser value. Before this
974 * insertion, this ancestor will be pointing to
975 * newnode's parent. After insertion, next in-order to newnode
978 newnode
->avl_nextino
= parent
;
981 if (AVL_END(tree
, nnext
) <= start
)
983 nnext
= nnext
->avl_parent
;
987 * nnext will be null if newnode is
988 * the least element, and hence very first in the list.
990 ASSERT(nnext
->avl_nextino
== parent
);
991 nnext
->avl_nextino
= newnode
;
995 parent
->avl_forw
= newnode
;
996 newnode
->avl_nextino
= parent
->avl_nextino
;
997 parent
->avl_nextino
= newnode
;
1004 avl64tree_desc_t
*tree
,
1005 avl64node_t
*newnode
)
1008 uint64_t start
= AVL_START(tree
, newnode
);
1009 uint64_t end
= AVL_END(tree
, newnode
);
1014 * Clean all pointers for sanity; some will be reset as necessary.
1016 newnode
->avl_nextino
= NULL
;
1017 newnode
->avl_parent
= NULL
;
1018 newnode
->avl_forw
= NULL
;
1019 newnode
->avl_back
= NULL
;
1020 newnode
->avl_balance
= AVL_BALANCE
;
1022 if ((np
= tree
->avl_root
) == NULL
) { /* degenerate case... */
1023 tree
->avl_root
= newnode
;
1024 tree
->avl_firstino
= newnode
;
1028 if ((np
= avl64_insert_find_growth(tree
, start
, end
, &growth
))
1030 if (start
!= end
) { /* non-zero length range */
1032 _("avl_insert: Warning! duplicate range [%llu,%llu]\n"),
1033 (unsigned long long)start
,
1034 (unsigned long long)end
);
1039 avl64_insert_grow(tree
, np
, newnode
, growth
);
1040 if (growth
== AVL_BACK
) {
1042 * Growing to left. if np was firstino, newnode will be firstino
1044 if (tree
->avl_firstino
== np
)
1045 tree
->avl_firstino
= newnode
;
1049 if (growth
== AVL_FORW
)
1051 * Cannot possibly be firstino; there is somebody to our left.
1056 newnode
->avl_parent
= np
;
1057 CERT(np
->avl_forw
== newnode
|| np
->avl_back
== newnode
);
1059 avl64_balance(&tree
->avl_root
, np
, growth
);
1061 avl64_checktree(tree
, tree
->avl_root
);
1068 * avl64_insert_immediate(tree, afterp, newnode):
1069 * insert newnode immediately into tree immediately after afterp.
1070 * after insertion, newnode is right child of afterp.
1073 avl64_insert_immediate(
1074 avl64tree_desc_t
*tree
,
1075 avl64node_t
*afterp
,
1076 avl64node_t
*newnode
)
1079 * Clean all pointers for sanity; some will be reset as necessary.
1081 newnode
->avl_nextino
= NULL
;
1082 newnode
->avl_parent
= NULL
;
1083 newnode
->avl_forw
= NULL
;
1084 newnode
->avl_back
= NULL
;
1085 newnode
->avl_balance
= AVL_BALANCE
;
1087 if (afterp
== NULL
) {
1088 tree
->avl_root
= newnode
;
1089 tree
->avl_firstino
= newnode
;
1093 ASSERT(afterp
->avl_forw
== NULL
);
1094 avl64_insert_grow(tree
, afterp
, newnode
, AVL_FORW
); /* grow to right */
1095 CERT(afterp
->avl_forw
== newnode
);
1096 avl64_balance(&tree
->avl_root
, afterp
, AVL_FORW
);
1097 avl64_checktree(tree
, tree
->avl_root
);
1102 * Returns first in order node
1105 avl64_firstino(avl64node_t
*root
)
1109 if ((np
= root
) == NULL
)
1112 while (np
->avl_back
)
1118 * Returns last in order node
1121 avl64_lastino(avl64node_t
*root
)
1125 if ((np
= root
) == NULL
)
1128 while (np
->avl_forw
)
1134 avl64_init_tree(avl64tree_desc_t
*tree
, avl64ops_t
*ops
)
1136 tree
->avl_root
= NULL
;
1137 tree
->avl_firstino
= NULL
;
1138 tree
->avl_ops
= ops
;
1143 avl64_printnode(avl64tree_desc_t
*tree
, avl64node_t
*np
, int nl
)
1145 printf("[%d-%d]%c", AVL_START(tree
, np
),
1146 (AVL_END(tree
, np
) - 1), nl
? '\n' : ' ');
1149 #ifdef STAND_ALONE_DEBUG
1151 struct avl_debug_node
{
1152 avl64node_t avl_node
;
1153 xfs_off_t avl_start
;
1154 unsigned int avl_size
;
1157 avl64ops_t avl_debug_ops
= {
1163 avl64_debug_start(avl64node_t
*node
)
1165 return (uint64_t)(struct avl_debug_node
*)node
->avl_start
;
1169 avl64_debug_end(avl64node_t
*node
)
1172 ((struct avl_debug_node
*)node
->avl_start
+
1173 (struct avl_debug_node
*)node
->avl_size
);
1176 avl_debug_node freenodes
[100];
1177 avl_debug_node
*freehead
= &freenodes
[0];
1179 static avl64node_t
*
1180 alloc_avl64_debug_node()
1182 freehead
->avl_balance
= AVL_BALANCE
;
1183 freehead
->avl_parent
= freehead
->avl_forw
= freehead
->avl_back
= NULL
;
1188 avl64_print(avl64tree_desc_t
*tree
, avl64node_t
*root
, int depth
)
1195 avl64_print(tree
, root
->avl_forw
, depth
+5);
1196 for (i
= 0; i
< depth
; i
++)
1198 avl64_printnode(tree
, root
,1);
1200 avl64_print(tree
, root
->avl_back
, depth
+5);
1207 avl64tree_desc_t tree
;
1208 char linebuf
[256], cmd
[256];
1210 avl64_init_tree(&tree
, &avl_debug_ops
);
1212 for (i
= 100; i
> 0; i
= i
- 10)
1214 np
= alloc__debug_avlnode();
1218 avl64_insert(&tree
, np
);
1220 avl64_print(&tree
, tree
.avl_root
, 0);
1222 for (np
= tree
.avl_firstino
; np
!= NULL
; np
= np
->avl_nextino
)
1223 avl64_printnode(&tree
, np
, 0);
1227 printf(_("Command [fpdir] : "));
1228 fgets(linebuf
, 256, stdin
);
1229 if (feof(stdin
)) break;
1231 if (sscanf(linebuf
, "%[fpdir]%d", cmd
, &i
) != 2)
1236 printf(_("end of range ? "));
1237 fgets(linebuf
, 256, stdin
);
1240 if (i
== j
) j
= i
+1;
1241 np
= avl64_findinrange(&tree
,i
,j
);
1243 avl64_printnode(&tree
, np
, 1);
1245 avl64_delete(&tree
, np
);
1247 printf(_("Cannot find %d\n"), i
);
1250 avl64_print(&tree
, tree
.avl_root
, 0);
1251 for (np
= tree
.avl_firstino
;
1252 np
!= NULL
; np
= np
->avl_nextino
)
1253 avl64_printnode(&tree
, np
, 0);
1257 np
= alloc_avlnode();
1260 printf(_("size of range ? "));
1261 fgets(linebuf
, 256, stdin
);
1265 avl64_insert(&tree
, np
);
1268 avl64node_t
*b
, *e
, *t
;
1271 printf(_("End of range ? "));
1272 fgets(linebuf
, 256, stdin
);
1275 printf(_("checklen 0/1 ? "));
1276 fgets(linebuf
, 256, stdin
);
1277 checklen
= atoi(linebuf
);
1280 b
= avl64_findanyrange(&tree
, i
, j
, checklen
);
1282 printf(_("Found something\n"));
1286 AVL_START(&tree
, t
) >= j
)
1288 avl64_printnode(&tree
, t
, 0);
1300 * Given a tree, find value; will find return range enclosing value,
1301 * or range immediately succeeding value,
1302 * or range immediately preceeding value.
1306 avl64tree_desc_t
*tree
,
1310 avl64node_t
*np
= tree
->avl_root
;
1313 if (value
< AVL_START(tree
, np
)) {
1318 /* if we were to add node with value, would
1319 * have a growth of AVL_BACK
1321 if (dir
== AVL_SUCCEED
) {
1322 /* if succeeding node is needed, this is it.
1326 if (dir
== AVL_PRECEED
) {
1328 * find nearest ancestor with lesser value.
1330 np
= np
->avl_parent
;
1332 if (AVL_END(tree
, np
) <= value
)
1334 np
= np
->avl_parent
;
1338 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1341 if (value
>= AVL_END(tree
, np
)) {
1346 /* if we were to add node with value, would
1347 * have a growth of AVL_FORW;
1349 if (dir
== AVL_SUCCEED
) {
1350 /* we are looking for a succeeding node;
1353 return(np
->avl_nextino
);
1355 if (dir
== AVL_PRECEED
) {
1356 /* looking for a preceeding node; this is it. */
1359 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1361 /* AVL_START(tree, np) <= value < AVL_END(tree, np) */
1371 * Given range r [start, end), find all ranges in tree which are contained
1372 * in r. At return, startp and endp point to first and last of
1373 * a chain of elements which describe the contained ranges. Elements
1374 * in startp ... endp are in sort order, and can be accessed by
1375 * using avl_nextino.
1380 avl64tree_desc_t
*tree
,
1383 avl64node_t
**startp
,
1388 np
= avl64_findadjacent(tree
, start
, AVL_SUCCEED
);
1389 if (np
== NULL
/* nothing succeding start */
1390 || (np
&& (end
<= AVL_START(tree
, np
))))
1391 /* something follows start,
1392 but... is entirely after end */
1401 /* see if end is in this region itself */
1402 if (end
<= AVL_END(tree
, np
) ||
1403 np
->avl_nextino
== NULL
||
1405 (end
<= AVL_START(tree
, np
->avl_nextino
)))) {
1409 /* have to munge for end */
1411 * note: have to look for (end - 1), since
1412 * findadjacent will look for exact value, and does not
1413 * care about the fact that end is actually one more
1414 * than the value actually being looked for; thus feed it one less.
1416 *endp
= avl64_findadjacent(tree
, (end
-1), AVL_PRECEED
);