2 /*--------------------------------------------------------------------*/
3 /*--- An AVL tree based finite map for word keys and word values. ---*/
4 /*--- Inspired by Haskell's "FiniteMap" library. ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Valgrind, a dynamic binary instrumentation
12 Copyright (C) 2007-2015 Julian Seward
15 This code is based on previous work by Nicholas Nethercote
16 (coregrind/m_oset.c) which is
18 Copyright (C) 2005-2015 Nicholas Nethercote
21 which in turn was derived partially from:
24 Copyright (C) 2000,2002 Daniel Nagy
26 This program is free software; you can redistribute it and/or
27 modify it under the terms of the GNU General Public License as
28 published by the Free Software Foundation; either version 2 of
29 the License, or (at your option) any later version.
32 (taken from libavl-0.4/debian/copyright)
34 This program is free software; you can redistribute it and/or
35 modify it under the terms of the GNU General Public License as
36 published by the Free Software Foundation; either version 2 of the
37 License, or (at your option) any later version.
39 This program is distributed in the hope that it will be useful, but
40 WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 General Public License for more details.
44 You should have received a copy of the GNU General Public License
45 along with this program; if not, write to the Free Software
46 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
49 The GNU General Public License is contained in the file COPYING.
52 #include "pub_core_basics.h"
53 #include "pub_core_libcassert.h"
54 #include "pub_core_libcbase.h"
55 #include "pub_core_wordfm.h" /* self */
58 //------------------------------------------------------------------//
60 //--- Implementation ---//
61 //------------------------------------------------------------------//
63 /* One element of the AVL tree */
68 struct _AvlNode
* child
[2]; /* [0] is left subtree, [1] is right */
69 Char balance
; /* do not make this unsigned */
80 #define WFM_STKMAX 32 // At most 2**32 entries can be iterated over
84 void* (*alloc_nofail
)( const HChar
*, SizeT
);
86 void (*dealloc
)(void*);
87 Word (*kCmp
)(UWord
,UWord
);
88 AvlNode
* nodeStack
[WFM_STKMAX
]; // Iterator node stack
89 Int numStack
[WFM_STKMAX
]; // Iterator num stack
90 Int stackTop
; // Iterator stack pointer, one past end
94 static Bool
avl_removeroot_wrk(AvlNode
** t
, Word(*kCmp
)(UWord
,UWord
));
96 /* Swing to the left. Warning: no balance maintainance. */
97 static void avl_swl ( AvlNode
** root
)
100 AvlNode
* b
= a
->child
[1];
102 a
->child
[1] = b
->child
[0];
106 /* Swing to the right. Warning: no balance maintainance. */
107 static void avl_swr ( AvlNode
** root
)
110 AvlNode
* b
= a
->child
[0];
112 a
->child
[0] = b
->child
[1];
116 /* Balance maintainance after especially nasty swings. */
117 static void avl_nasty ( AvlNode
* root
)
119 switch (root
->balance
) {
121 root
->child
[0]->balance
= 0;
122 root
->child
[1]->balance
= 1;
125 root
->child
[0]->balance
= -1;
126 root
->child
[1]->balance
= 0;
129 root
->child
[0]->balance
= 0;
130 root
->child
[1]->balance
= 0;
138 /* Find size of a non-NULL tree. */
139 static UWord
size_avl_nonNull ( const AvlNode
* nd
)
141 return 1 + (nd
->child
[0] ? size_avl_nonNull(nd
->child
[0]) : 0)
142 + (nd
->child
[1] ? size_avl_nonNull(nd
->child
[1]) : 0);
145 /* Unsignedly compare w1 and w2. If w1 < w2, produce a negative
146 number; if w1 > w2 produce a positive number, and if w1 == w2
148 static inline Word
cmp_unsigned_Words ( UWord w1
, UWord w2
) {
149 if (w1
< w2
) return -1;
150 if (w1
> w2
) return 1;
154 /* Insert element a into the AVL tree t. Returns True if the depth of
155 the tree has grown. If element with that key is already present,
156 just copy a->val to existing node, first returning old ->val field
157 of existing node in *oldV, so that the caller can finalize it
161 Bool
avl_insert_wrk ( AvlNode
** rootp
,
162 /*OUT*/MaybeWord
* oldV
,
164 Word (*kCmp
)(UWord
,UWord
) )
174 /* insert into an empty tree? */
180 cmpres
= kCmp
? /*boxed*/ kCmp( (*rootp
)->key
, a
->key
)
181 : /*unboxed*/ cmp_unsigned_Words( (UWord
)(*rootp
)->key
,
185 /* insert into the left subtree */
186 if ((*rootp
)->child
[0]) {
187 AvlNode
* left_subtree
= (*rootp
)->child
[0];
188 if (avl_insert_wrk(&left_subtree
, oldV
, a
, kCmp
)) {
189 switch ((*rootp
)->balance
--) {
190 case 1: return False
;
193 default: vg_assert(0);
195 if ((*rootp
)->child
[0]->balance
< 0) {
197 (*rootp
)->balance
= 0;
198 (*rootp
)->child
[1]->balance
= 0;
200 avl_swl( &((*rootp
)->child
[0]) );
205 (*rootp
)->child
[0] = left_subtree
;
209 (*rootp
)->child
[0] = a
;
210 if ((*rootp
)->balance
--)
214 vg_assert(0);/*NOTREACHED*/
218 /* insert into the right subtree */
219 if ((*rootp
)->child
[1]) {
220 AvlNode
* right_subtree
= (*rootp
)->child
[1];
221 if (avl_insert_wrk(&right_subtree
, oldV
, a
, kCmp
)) {
222 switch((*rootp
)->balance
++){
223 case -1: return False
;
226 default: vg_assert(0);
228 if ((*rootp
)->child
[1]->balance
> 0) {
230 (*rootp
)->balance
= 0;
231 (*rootp
)->child
[0]->balance
= 0;
233 avl_swr( &((*rootp
)->child
[1]) );
238 (*rootp
)->child
[1] = right_subtree
;
242 (*rootp
)->child
[1] = a
;
243 if ((*rootp
)->balance
++)
247 vg_assert(0);/*NOTREACHED*/
250 /* cmpres == 0, a duplicate - replace the val, but don't
251 incorporate the node in the tree */
253 oldV
->w
= (*rootp
)->val
;
254 (*rootp
)->val
= a
->val
;
259 /* Remove an element a from the AVL tree t. a must be part of
260 the tree. Returns True if the depth of the tree has shrunk.
263 Bool
avl_remove_wrk ( AvlNode
** rootp
,
265 Word(*kCmp
)(UWord
,UWord
) )
269 cmpres
= kCmp
? /*boxed*/ kCmp( (*rootp
)->key
, a
->key
)
270 : /*unboxed*/ cmp_unsigned_Words( (UWord
)(*rootp
)->key
,
274 /* remove from the left subtree */
275 AvlNode
* left_subtree
= (*rootp
)->child
[0];
276 vg_assert(left_subtree
);
277 ch
= avl_remove_wrk(&left_subtree
, a
, kCmp
);
278 (*rootp
)->child
[0]=left_subtree
;
280 switch ((*rootp
)->balance
++) {
281 case -1: return True
;
282 case 0: return False
;
284 default: vg_assert(0);
286 switch ((*rootp
)->child
[1]->balance
) {
289 (*rootp
)->balance
= -1;
290 (*rootp
)->child
[0]->balance
= 1;
294 (*rootp
)->balance
= 0;
295 (*rootp
)->child
[0]->balance
= 0;
302 avl_swr( &((*rootp
)->child
[1]) );
310 /* remove from the right subtree */
311 AvlNode
* right_subtree
= (*rootp
)->child
[1];
312 vg_assert(right_subtree
);
313 ch
= avl_remove_wrk(&right_subtree
, a
, kCmp
);
314 (*rootp
)->child
[1] = right_subtree
;
316 switch ((*rootp
)->balance
--) {
318 case 0: return False
;
320 default: vg_assert(0);
322 switch ((*rootp
)->child
[0]->balance
) {
325 (*rootp
)->balance
= 1;
326 (*rootp
)->child
[1]->balance
= -1;
330 (*rootp
)->balance
= 0;
331 (*rootp
)->child
[1]->balance
= 0;
338 avl_swl( &((*rootp
)->child
[0]) );
345 vg_assert(cmpres
== 0);
346 vg_assert((*rootp
)==a
);
347 return avl_removeroot_wrk(rootp
, kCmp
);
352 /* Remove the root of the AVL tree *rootp.
353 * Warning: dumps core if *rootp is empty
356 Bool
avl_removeroot_wrk ( AvlNode
** rootp
,
357 Word(*kCmp
)(UWord
,UWord
) )
361 if (!(*rootp
)->child
[0]) {
362 if (!(*rootp
)->child
[1]) {
366 (*rootp
) = (*rootp
)->child
[1];
369 if (!(*rootp
)->child
[1]) {
370 (*rootp
) = (*rootp
)->child
[0];
373 if ((*rootp
)->balance
< 0) {
374 /* remove from the left subtree */
375 a
= (*rootp
)->child
[0];
376 while (a
->child
[1]) a
= a
->child
[1];
378 /* remove from the right subtree */
379 a
= (*rootp
)->child
[1];
380 while (a
->child
[0]) a
= a
->child
[0];
382 ch
= avl_remove_wrk(rootp
, a
, kCmp
);
383 a
->child
[0] = (*rootp
)->child
[0];
384 a
->child
[1] = (*rootp
)->child
[1];
385 a
->balance
= (*rootp
)->balance
;
387 if(a
->balance
== 0) return ch
;
392 AvlNode
* avl_find_node ( AvlNode
* t
, Word k
, Word(*kCmp
)(UWord
,UWord
) )
395 /* Boxed comparisons */
398 if (t
== NULL
) return NULL
;
399 cmpresS
= kCmp(t
->key
, k
);
400 if (cmpresS
> 0) t
= t
->child
[0]; else
401 if (cmpresS
< 0) t
= t
->child
[1]; else
405 /* Unboxed comparisons */
406 Word cmpresS
; /* signed */
407 UWord cmpresU
; /* unsigned */
409 if (t
== NULL
) return NULL
; /* unlikely ==> predictable */
410 cmpresS
= cmp_unsigned_Words( (UWord
)t
->key
, (UWord
)k
);
411 if (cmpresS
== 0) return t
; /* unlikely ==> predictable */
412 cmpresU
= (UWord
)cmpresS
;
413 cmpresU
>>=/*unsigned*/ (8 * sizeof(cmpresU
) - 1);
414 t
= t
->child
[cmpresU
];
420 Bool
avl_find_bounds ( const AvlNode
* t
,
421 /*OUT*/UWord
* kMinP
, /*OUT*/UWord
* vMinP
,
422 /*OUT*/UWord
* kMaxP
, /*OUT*/UWord
* vMaxP
,
423 UWord minKey
, UWord minVal
,
424 UWord maxKey
, UWord maxVal
,
426 Word(*kCmp
)(UWord
,UWord
) )
428 UWord kLowerBound
= minKey
;
429 UWord vLowerBound
= minVal
;
430 UWord kUpperBound
= maxKey
;
431 UWord vUpperBound
= maxVal
;
433 Word cmpresS
= kCmp
? kCmp(t
->key
, key
)
434 : cmp_unsigned_Words(t
->key
, key
);
436 kLowerBound
= t
->key
;
437 vLowerBound
= t
->val
;
442 kUpperBound
= t
->key
;
443 vUpperBound
= t
->val
;
447 /* We should never get here. If we do, it means the given key
448 is actually present in the tree, which means the original
449 call was invalid -- an error on the caller's part, and we
450 cannot give any meaningful values for the bounds. (Well,
451 maybe we could, but we're not gonna. Ner!) */
454 if (kMinP
) *kMinP
= kLowerBound
;
455 if (vMinP
) *vMinP
= vLowerBound
;
456 if (kMaxP
) *kMaxP
= kUpperBound
;
457 if (vMaxP
) *vMaxP
= vUpperBound
;
461 // Clear the iterator stack.
462 static void stackClear(WordFM
* fm
)
466 for (i
= 0; i
< WFM_STKMAX
; i
++) {
467 fm
->nodeStack
[i
] = NULL
;
473 // Push onto the iterator stack.
474 static inline void stackPush(WordFM
* fm
, AvlNode
* n
, Int i
)
476 vg_assert(fm
->stackTop
< WFM_STKMAX
);
477 vg_assert(1 <= i
&& i
<= 3);
478 fm
->nodeStack
[fm
->stackTop
] = n
;
479 fm
-> numStack
[fm
->stackTop
] = i
;
483 // Pop from the iterator stack.
484 static inline Bool
stackPop(WordFM
* fm
, AvlNode
** n
, Int
* i
)
486 vg_assert(fm
->stackTop
<= WFM_STKMAX
);
488 if (fm
->stackTop
> 0) {
490 *n
= fm
->nodeStack
[fm
->stackTop
];
491 *i
= fm
-> numStack
[fm
->stackTop
];
492 vg_assert(1 <= *i
&& *i
<= 3);
493 fm
->nodeStack
[fm
->stackTop
] = NULL
;
494 fm
-> numStack
[fm
->stackTop
] = 0;
502 AvlNode
* avl_dopy ( const AvlNode
* nd
,
503 UWord(*dopyK
)(UWord
),
504 UWord(*dopyV
)(UWord
),
505 void*(alloc_nofail
)(const HChar
*,SizeT
),
510 vg_assert(nd
!= NULL
);
512 nyu
= alloc_nofail(cc
, sizeof(AvlNode
));
514 nyu
->child
[0] = nd
->child
[0];
515 nyu
->child
[1] = nd
->child
[1];
516 nyu
->balance
= nd
->balance
;
520 nyu
->key
= dopyK( nd
->key
);
522 /* copying assumedly unboxed keys */
528 nyu
->val
= dopyV( nd
->val
);
530 /* copying assumedly unboxed vals */
536 nyu
->child
[0] = avl_dopy( nyu
->child
[0], dopyK
, dopyV
,
540 nyu
->child
[1] = avl_dopy( nyu
->child
[1], dopyK
, dopyV
,
547 /* Initialise a WordFM. */
548 static void initFM ( WordFM
* fm
,
549 void* (*alloc_nofail
)( const HChar
*, SizeT
),
551 void (*dealloc
)(void*),
552 Word (*kCmp
)(UWord
,UWord
) )
556 fm
->alloc_nofail
= alloc_nofail
;
558 fm
->dealloc
= dealloc
;
562 /* --- Public interface functions --- */
564 /* Allocate and initialise a WordFM. If kCmp is non-NULL, elements in
565 the set are ordered according to the ordering specified by kCmp,
566 which becomes obvious if you use VG_(initIterFM),
567 VG_(initIterAtFM), VG_(nextIterFM), VG_(doneIterFM) to iterate over
568 sections of the map, or the whole thing. If kCmp is NULL then the
569 ordering used is unsigned word ordering (UWord) on the key
571 WordFM
* VG_(newFM
) ( void* (*alloc_nofail
)( const HChar
*, SizeT
),
573 void (*dealloc
)(void*),
574 Word (*kCmp
)(UWord
,UWord
) )
576 WordFM
* fm
= alloc_nofail(cc
, sizeof(WordFM
));
577 initFM(fm
, alloc_nofail
, cc
, dealloc
, kCmp
);
581 static void avl_free ( AvlNode
* nd
,
584 void(*dealloc
)(void*) )
589 avl_free(nd
->child
[0], kFin
, vFin
, dealloc
);
591 avl_free(nd
->child
[1], kFin
, vFin
, dealloc
);
596 VG_(memset
)(nd
, 0, sizeof(AvlNode
));
600 /* Free up the FM. If kFin is non-NULL, it is applied to keys
601 before the FM is deleted; ditto with vFin for vals. */
602 void VG_(deleteFM
) ( WordFM
* fm
, void(*kFin
)(UWord
), void(*vFin
)(UWord
) )
604 void(*dealloc
)(void*) = fm
->dealloc
;
605 avl_free( fm
->root
, kFin
, vFin
, dealloc
);
606 VG_(memset
)(fm
, 0, sizeof(WordFM
) );
610 /* Add (k,v) to fm. */
611 Bool
VG_(addToFM
) ( WordFM
* fm
, UWord k
, UWord v
)
615 node
= fm
->alloc_nofail( fm
->cc
, sizeof(AvlNode
) );
620 avl_insert_wrk( &fm
->root
, &oldV
, node
, fm
->kCmp
);
621 //if (oldV.b && fm->vFin)
622 // fm->vFin( oldV.w );
628 // Delete key from fm, returning associated key and val if found
629 Bool
VG_(delFromFM
) ( WordFM
* fm
,
630 /*OUT*/UWord
* oldK
, /*OUT*/UWord
* oldV
, UWord key
)
632 AvlNode
* node
= avl_find_node( fm
->root
, key
, fm
->kCmp
);
634 avl_remove_wrk( &fm
->root
, node
, fm
->kCmp
);
646 // Look up in fm, assigning found key & val at spec'd addresses
647 Bool
VG_(lookupFM
) ( const WordFM
* fm
,
648 /*OUT*/UWord
* keyP
, /*OUT*/UWord
* valP
, UWord key
)
650 AvlNode
* node
= avl_find_node( fm
->root
, key
, fm
->kCmp
);
662 // See comment in pub_tool_wordfm.h for explanation
663 Bool
VG_(findBoundsFM
)( const WordFM
* fm
,
664 /*OUT*/UWord
* kMinP
, /*OUT*/UWord
* vMinP
,
665 /*OUT*/UWord
* kMaxP
, /*OUT*/UWord
* vMaxP
,
666 UWord minKey
, UWord minVal
,
667 UWord maxKey
, UWord maxVal
,
670 /* really we should assert that minKey <= key <= maxKey,
671 where <= is as defined by fm->kCmp. */
672 return avl_find_bounds( fm
->root
, kMinP
, vMinP
,
679 // See comment in pub_tool_wordfm.h for performance warning
680 UWord
VG_(sizeFM
) ( const WordFM
* fm
)
682 // Hmm, this is a bad way to do this
683 return fm
->root
? size_avl_nonNull( fm
->root
) : 0;
686 // NB UNTESTED! TEST BEFORE USE!
687 //Bool VG_(isEmptyFM)( const WordFM* fm )
689 // return fm->root ? False : True;
692 // set up FM for iteration
693 void VG_(initIterFM
) ( WordFM
* fm
)
698 stackPush(fm
, fm
->root
, 1);
701 // set up FM for iteration so that the first key subsequently produced
702 // by VG_(nextIterFM) is the smallest key in the map >= start_at.
703 // Naturally ">=" is defined by the comparison function supplied to
704 // VG_(newFM), as documented above.
705 void VG_(initIterAtFM
) ( WordFM
* fm
, UWord start_at
)
709 Word cmpresS
; /* signed */
710 UWord cmpresU
; /* unsigned */
719 // We need to do regular search and fill in the stack.
723 if (t
== NULL
) return;
726 = fm
->kCmp
? /*boxed*/ fm
->kCmp( t
->key
, start_at
)
727 : /*unboxed*/ cmp_unsigned_Words( t
->key
, start_at
);
730 // We found the exact key -- we are done.
731 // The iteration should start with this node.
733 // The stack now looks like {2, 2, ... ,2, 2}
736 cmpresU
= (UWord
)cmpresS
;
737 cmpresU
>>=/*unsigned*/ (8 * sizeof(cmpresU
) - 1);
739 // Push this node only if we go to the left child.
742 t
= t
->child
[cmpresU
];
744 if (stackPop(fm
, &n
, &i
)) {
745 // If we've pushed something to stack and did not find the exact key,
746 // we must fix the top element of stack.
749 // the stack looks like {2, 2, ..., 2, 3}
753 // get next key/val pair. Will vg_assert if fm has been modified
754 // or looked up in since initIter{,At}FM was called.
755 Bool
VG_(nextIterFM
) ( WordFM
* fm
, /*OUT*/UWord
* pKey
, /*OUT*/UWord
* pVal
)
762 // This in-order traversal requires each node to be pushed and popped
763 // three times. These could be avoided by updating nodes in-situ on the
764 // top of the stack, but the push/pop cost is so small that it's worth
765 // keeping this loop in this simpler form.
766 while (stackPop(fm
, &n
, &i
)) {
770 /* if (n->child[0]) stackPush(fm, n->child[0], 1); */
771 if (n
->child
[0]) { n
= n
->child
[0]; goto case_1
; }
775 if (pKey
) *pKey
= n
->key
;
776 if (pVal
) *pVal
= n
->val
;
779 /* if (n->child[1]) stackPush(fm, n->child[1], 1); */
780 if (n
->child
[1]) { n
= n
->child
[1]; goto case_1
; }
787 // Stack empty, iterator is exhausted, return NULL
791 // Finish an FM iteration
792 void VG_(doneIterFM
) ( WordFM
* fm
)
796 WordFM
* VG_(dopyFM
) ( WordFM
* fm
, UWord(*dopyK
)(UWord
),
797 UWord(*dopyV
)(UWord
) )
801 /* can't clone the fm whilst iterating on it */
802 vg_assert(fm
->stackTop
== 0);
804 nyu
= fm
->alloc_nofail( fm
->cc
, sizeof(WordFM
) );
809 VG_(memset
)(fm
->nodeStack
, 0, sizeof(fm
->nodeStack
));
810 VG_(memset
)(fm
->numStack
, 0, sizeof(fm
->numStack
));
813 nyu
->root
= avl_dopy( nyu
->root
, dopyK
, dopyV
,
814 fm
->alloc_nofail
, fm
->cc
);
822 //------------------------------------------------------------------//
823 //--- end WordFM ---//
824 //--- Implementation ---//
825 //------------------------------------------------------------------//
827 //------------------------------------------------------------------//
828 //--- WordBag (unboxed words only) ---//
829 //--- Implementation ---//
830 //------------------------------------------------------------------//
832 /* A trivial container, to make it opaque. */
837 WordBag
* VG_(newBag
) ( void* (*alloc_nofail
)( const HChar
*, SizeT
),
839 void (*dealloc
)(void*) )
841 WordBag
* bag
= alloc_nofail(cc
, sizeof(WordBag
));
842 bag
->fm
= VG_(newFM
)( alloc_nofail
, cc
, dealloc
, NULL
);
846 void VG_(deleteBag
) ( WordBag
* bag
)
848 void (*dealloc
)(void*) = bag
->fm
->dealloc
;
849 VG_(deleteFM
)( bag
->fm
, NULL
, NULL
);
850 VG_(memset
)(bag
, 0, sizeof(WordBag
));
854 void VG_(addToBag
)( WordBag
* bag
, UWord w
)
857 if (VG_(lookupFM
)(bag
->fm
, &key
, &count
, w
)) {
859 vg_assert(count
>= 1);
860 VG_(addToFM
)(bag
->fm
, w
, count
+1);
862 VG_(addToFM
)(bag
->fm
, w
, 1);
866 UWord
VG_(elemBag
) ( const WordBag
* bag
, UWord w
)
869 if (VG_(lookupFM
)( bag
->fm
, &key
, &count
, w
)) {
871 vg_assert(count
>= 1);
878 UWord
VG_(sizeUniqueBag
) ( const WordBag
* bag
)
880 return VG_(sizeFM
)( bag
->fm
);
883 static UWord
sizeTotalBag_wrk ( const AvlNode
* nd
)
885 /* unchecked pre: nd is non-NULL */
889 w
+= sizeTotalBag_wrk(nd
->child
[0]);
891 w
+= sizeTotalBag_wrk(nd
->child
[1]);
894 UWord
VG_(sizeTotalBag
)( const WordBag
* bag
)
897 return sizeTotalBag_wrk(bag
->fm
->root
);
902 Bool
VG_(delFromBag
)( WordBag
* bag
, UWord w
)
905 if (VG_(lookupFM
)(bag
->fm
, &key
, &count
, w
)) {
907 vg_assert(count
>= 1);
909 VG_(addToFM
)(bag
->fm
, w
, count
-1);
911 vg_assert(count
== 1);
912 VG_(delFromFM
)( bag
->fm
, NULL
, NULL
, w
);
920 Bool
VG_(isEmptyBag
)( const WordBag
* bag
)
922 return VG_(sizeFM
)(bag
->fm
) == 0;
925 Bool
VG_(isSingletonTotalBag
)( const WordBag
* bag
)
928 if (VG_(sizeFM
)(bag
->fm
) != 1)
932 vg_assert(!nd
->child
[0]);
933 vg_assert(!nd
->child
[1]);
937 UWord
VG_(anyElementOfBag
)( const WordBag
* bag
)
939 /* Return an arbitrarily chosen element in the bag. We might as
940 well return the one at the root of the underlying AVL tree. */
941 AvlNode
* nd
= bag
->fm
->root
;
942 vg_assert(nd
); /* if this fails, 'bag' is empty - caller is in error. */
943 vg_assert(nd
->val
>= 1);
947 void VG_(initIterBag
)( WordBag
* bag
)
949 VG_(initIterFM
)(bag
->fm
);
952 Bool
VG_(nextIterBag
)( WordBag
* bag
, /*OUT*/UWord
* pVal
, /*OUT*/UWord
* pCount
)
954 return VG_(nextIterFM
)( bag
->fm
, pVal
, pCount
);
957 void VG_(doneIterBag
)( WordBag
* bag
)
959 VG_(doneIterFM
)( bag
->fm
);
962 //------------------------------------------------------------------//
963 //--- end WordBag (unboxed words only) ---//
964 //--- Implementation ---//
965 //------------------------------------------------------------------//
967 /*--------------------------------------------------------------------*/
968 /*--- end m_wordfm.c ---*/
969 /*--------------------------------------------------------------------*/