1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- An ordered set implemented using an AVL tree.       m_oset.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2005-2013 Nicholas Nethercote
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      njn@valgrind.org
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------------------
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This file is based on:
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   ANSI C Library for maintainance of AVL Balanced Trees
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   (C) 2000 Daniel Nagy, Budapest University of Technology and Economics
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   Released under GNU General Public License (GPL) version 2
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------------------
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This file implements a generic ordered set using an AVL tree.
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Each node in the tree has two parts.
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - First is the AVL metadata, which is three words: a left pointer, a
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   right pointer, and a word containing balancing information and a
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   "magic" value which provides some checking that the user has not
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   corrupted the metadata.  So the overhead is 12 bytes on 32-bit
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   platforms and 24 bytes on 64-bit platforms.
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Second is the user's data.  This can be anything.  Note that because it
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   comes after the metadata, it will only be word-aligned, even if the
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   user data is a struct that would normally be doubleword-aligned.
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// AvlNode* node -> +---------------+  V
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                  | struct        |
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                  |   AvlNode     |
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// void* element -> +---------------+  ^
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                  | element       |  |
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      keyOff ->   | key           | elemSize
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                  +---------------+  v
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Users have to allocate AvlNodes with OSetGen_AllocNode(), which allocates
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// space for the metadata.
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The terminology used throughout this file:
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - a "node", usually called "n", is a pointer to the metadata.
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - an "element", usually called "e", is a pointer to the user data.
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - a "key", usually called "k", is a pointer to a key.
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The helper functions elem_of_node and node_of_elem do the pointer
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// arithmetic to switch between the node and the element.  The node magic is
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// checked after each operation to make sure that we're really operating on
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// an AvlNode.
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Each tree also has an iterator.  Note that we cannot use the iterator
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// internally within this file (eg. we could implement OSetGen_Size() by
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// stepping through with the iterator and counting nodes) because it's
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// non-reentrant -- the user might be using it themselves, and the
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// concurrent uses would screw things up.
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_oset.h"
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_poolalloc.h"
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Types and constants                                          ---*/
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct _OSetNode OSetNode;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Internal names for the OSet types.
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef OSet     AvlTree;
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef OSetNode AvlNode;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The padding ensures that magic is right at the end of the node,
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// regardless of the machine's word size, so that any overwrites will be
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// detected earlier.
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _OSetNode {
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* left;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* right;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char     balance;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char     padding[sizeof(void*)-sizeof(Char)-sizeof(Short)];
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Short    magic;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_MAX    32    // At most 2**32 entries can be iterated over
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OSET_MAGIC   0x5b1f
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// An OSet (AVL tree).  If cmp is NULL, the key must be a UWord, and must
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// be the first word in the element.  If cmp is set, arbitrary keys in
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// arbitrary positions can be used.
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _OSet {
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT       keyOff;     // key offset
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSetCmp_t   cmp;        // compare a key and an element, or NULL
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSetAlloc_t alloc;      // allocator
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* cc;        // cc for allocator
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSetFree_t  free;       // deallocator
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   PoolAlloc*  node_pa;    // (optional) pool allocator for nodes.
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SizeT       maxEltSize; // for node_pa, must be > 0. Otherwise unused.
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word        nElems;     // number of elements in the tree
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode*    root;       // root node
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode*    nodeStack[STACK_MAX];   // Iterator node stack
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int          numStack[STACK_MAX];   // Iterator num stack
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         stackTop;               // Iterator stack pointer, one past end
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper operations                                            ---*/
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Given a pointer to the node's element, return the pointer to the AvlNode
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// structure.  If the node has a bad magic number, it will die with an
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// assertion failure.
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAvlNode* node_of_elem(const void *elem)
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* n = (AvlNode*)((Addr)elem - sizeof(AvlNode));
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert2(n->magic == OSET_MAGIC,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "bad magic on node %p = %x (expected %x)\n"
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "possible causes:\n"
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              " - node not allocated with VG_(OSetGen_AllocNode)()?\n"
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              " - node metadata corrupted by underwriting start of element?\n",
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              n, n->magic, OSET_MAGIC);
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Given an AvlNode, return the pointer to the element.
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* elem_of_node(const AvlNode *n)
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert2(n->magic == OSET_MAGIC,
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "bad magic on node %p = %x (expected %x)\n"
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "possible causes:\n"
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              " - node metadata corrupted by overwriting end of element?\n",
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              n, n->magic, OSET_MAGIC);
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)((Addr)n + sizeof(AvlNode));
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Like elem_of_node, but no magic checking.
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* elem_of_node_no_check(const AvlNode *n)
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)((Addr)n + sizeof(AvlNode));
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* slow_key_of_node(AvlTree* t, AvlNode* n)
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)((Addr)elem_of_node(n) + t->keyOff);
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* fast_key_of_node(AvlNode* n)
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return elem_of_node(n);
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Compare the first word of each element.  Inlining is *crucial*.
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Word fast_cmp(const void* k, const AvlNode* n)
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord w1 = *(const UWord*)k;
183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord w2 = *(const UWord*)elem_of_node(n);
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // In previous versions, we tried to do this faster by doing
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // "return w1 - w2".  But it didn't work reliably, because the
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // complete result of subtracting two N-bit numbers is an N+1-bit
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // number, and what the caller is interested in is the sign of
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the complete N+1-bit result.  The branching version is slightly
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // slower, but safer and easier to understand.
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w1 > w2) return  1;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w1 < w2) return -1;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Compare a key and an element.  Inlining is *crucial*.
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline Word slow_cmp(const AvlTree* t, const void* k, const AvlNode* n)
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t->cmp(k, elem_of_node(n));
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Swing to the left.   Warning: no balance maintainance.
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void avl_swl ( AvlNode** root )
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* a = *root;
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* b = a->right;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *root    = b;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a->right = b->left;
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b->left  = a;
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Swing to the right.  Warning: no balance maintainance.
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void avl_swr ( AvlNode** root )
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* a = *root;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* b = a->left;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *root    = b;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a->left  = b->right;
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b->right = a;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Balance maintainance after especially nasty swings.
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void avl_nasty ( AvlNode* root )
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (root->balance) {
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case -1:
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->left->balance  = 0;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->right->balance = 1;
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1:
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->left->balance  =-1;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->right->balance = 0;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0:
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->left->balance  = 0;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      root->right->balance = 0;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   root->balance = 0;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Clear the iterator stack.
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void stackClear(AvlTree* t)
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < STACK_MAX; i++) {
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->nodeStack[i] = NULL;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->numStack[i]  = 0;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->stackTop = 0;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Push onto the iterator stack.
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void stackPush(AvlTree* t, AvlNode* n, Int i)
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t->stackTop < STACK_MAX);
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(1 <= i && i <= 3);
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->nodeStack[t->stackTop] = n;
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t-> numStack[t->stackTop] = i;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->stackTop++;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Pop from the iterator stack.
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool stackPop(AvlTree* t, AvlNode** n, Int* i)
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t->stackTop <= STACK_MAX);
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t->stackTop > 0) {
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->stackTop--;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *n = t->nodeStack[t->stackTop];
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *i = t-> numStack[t->stackTop];
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(1 <= *i && *i <= 3);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->nodeStack[t->stackTop] = NULL;
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t-> numStack[t->stackTop] = 0;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Creating and destroying AvlTrees and AvlNodes                ---*/
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The underscores avoid GCC complaints about overshadowing global names.
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAvlTree* VG_(OSetGen_Create)(PtrdiffT _keyOff, OSetCmp_t _cmp,
289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             OSetAlloc_t _alloc, const HChar* _cc,
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             OSetFree_t _free)
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlTree* t;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Check the padding is right and the AvlNode is the expected size.
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(AvlNode) == 3*sizeof(void*));
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Sanity check args
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(_alloc);
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(_free);
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!_cmp) vg_assert(0 == _keyOff);    // If no cmp, offset must be zero
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t           = _alloc(_cc, sizeof(AvlTree));
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->keyOff   = _keyOff;
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->cmp      = _cmp;
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->alloc    = _alloc;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->cc       = _cc;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->free     = _free;
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->node_pa  = NULL;
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->maxEltSize = 0; // Just in case it would be wrongly used.
310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->nElems   = 0;
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->root     = NULL;
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stackClear(t);
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return t;
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
317663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAvlTree* VG_(OSetGen_Create_With_Pool)(PtrdiffT _keyOff, OSetCmp_t _cmp,
318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       OSetAlloc_t _alloc, const HChar* _cc,
319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       OSetFree_t _free,
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       SizeT _poolSize,
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       SizeT _maxEltSize)
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AvlTree* t;
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = VG_(OSetGen_Create) (_keyOff, _cmp,
326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            _alloc, _cc,
327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            _free);
328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vg_assert (_poolSize > 0);
330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vg_assert (_maxEltSize > 0);
331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->maxEltSize = _maxEltSize;
332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->node_pa = VG_(newPA)(sizeof(AvlNode)
333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           + VG_ROUNDUP(_maxEltSize, sizeof(void*)),
334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           _poolSize,
335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           t->alloc,
336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           _cc,
337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           t->free);
338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VG_(addRefPA) (t->node_pa);
339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return t;
341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
343663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAvlTree* VG_(OSetGen_EmptyClone) (AvlTree* os)
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AvlTree* t;
346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vg_assert(os);
348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t           = os->alloc(os->cc, sizeof(AvlTree));
350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->keyOff   = os->keyOff;
351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->cmp      = os->cmp;
352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->alloc    = os->alloc;
353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->cc       = os->cc;
354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->free     = os->free;
355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->node_pa  = os->node_pa;
356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (t->node_pa)
357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(addRefPA) (t->node_pa);
358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t->maxEltSize = os->maxEltSize;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->nElems   = 0;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->root     = NULL;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stackClear(t);
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovAvlTree* VG_(OSetWord_Create)(OSetAlloc_t _alloc, const HChar* _cc,
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              OSetFree_t _free)
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(OSetGen_Create)(/*keyOff*/0, /*cmp*/NULL, _alloc, _cc, _free);
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Destructor, frees up all memory held by remaining nodes.
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetGen_Destroy)(AvlTree* t)
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool has_node_pa;
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   has_node_pa = t->node_pa != NULL;
379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*
381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * If we are the only remaining user of this pool allocator, release all
382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * the elements by deleting the pool allocator. That's more efficient than
383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * deleting tree nodes one by one.
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    */
385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!has_node_pa || VG_(releasePA)(t->node_pa) > 0) {
386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AvlNode* n = NULL;
387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int i = 0;
388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Word sz = 0;
389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stackClear(t);
391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (t->root)
392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stackPush(t, t->root, 1);
393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Free all the AvlNodes.  This is a post-order traversal, because we */
395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* must free all children of a node before the node itself. */
396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      while (stackPop(t, &n, &i)) {
397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (i) {
398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 1:
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            stackPush(t, n, 2);
400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (n->left)  stackPush(t, n->left, 1);
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 2:
403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            stackPush(t, n, 3);
404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (n->right) stackPush(t, n->right, 1);
405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 3:
407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (has_node_pa)
408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               VG_(freeEltPA) (t->node_pa, n);
409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else
410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               t->free(n);
411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz++;
412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vg_assert(sz == t->nElems);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Free the AvlTree itself. */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->free(t);
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetWord_Destroy)(AvlTree* t)
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_Destroy)(t);
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Allocate and initialise a new node.
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(OSetGen_AllocNode)(AvlTree* t, SizeT elemSize)
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AvlNode* n;
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int nodeSize = sizeof(AvlNode) + elemSize;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(elemSize > 0);
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (t->node_pa) {
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vg_assert(elemSize <= t->maxEltSize);
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      n = VG_(allocEltPA) (t->node_pa);
436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      n = t->alloc( t->cc, nodeSize );
438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(n, 0, nodeSize);
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->magic = OSET_MAGIC;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return elem_of_node(n);
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetGen_FreeNode)(AvlTree* t, void* e)
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (t->node_pa)
447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(freeEltPA) (t->node_pa, node_of_elem (e));
448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t->free( node_of_elem(e) );
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insertion                                                    ---*/
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Word cmp_key_root(AvlTree* t, AvlNode* n)
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t->cmp
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ? slow_cmp(t, slow_key_of_node(t, n), t->root)
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          : fast_cmp(   fast_key_of_node(   n), t->root);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Insert element e into the non-empty AVL tree t.
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Returns True if the depth of the tree has grown.
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool avl_insert(AvlTree* t, AvlNode* n)
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word cmpres = cmp_key_root(t, n);
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cmpres < 0) {
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Insert into the left subtree.
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (t->root->left) {
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Only need to set the used fields in the subtree.
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AvlTree left_subtree;
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         left_subtree.root   = t->root->left;
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         left_subtree.cmp    = t->cmp;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         left_subtree.keyOff = t->keyOff;
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (avl_insert(&left_subtree, n)) {
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             switch (t->root->balance--) {
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 1: return False;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 0: return True;
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             }
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             if (t->root->left->balance < 0) {
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                avl_swr(&(t->root));
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t->root->balance = 0;
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t->root->right->balance = 0;
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             } else {
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                avl_swl(&(t->root->left));
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                avl_swr(&(t->root));
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                avl_nasty(t->root);
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             }
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->left=left_subtree.root;
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t->root->left = n;
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (t->root->balance--) return False;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (cmpres > 0) {
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Insert into the right subtree
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (t->root->right) {
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Only need to set the used fields in the subtree.
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AvlTree right_subtree;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         right_subtree.root   = t->root->right;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         right_subtree.cmp    = t->cmp;
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         right_subtree.keyOff = t->keyOff;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (avl_insert(&right_subtree, n)) {
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (t->root->balance++) {
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case -1: return False;
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case  0: return True;
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t->root->right->balance > 0) {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               avl_swl(&(t->root));
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t->root->balance = 0;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t->root->left->balance = 0;
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               avl_swr(&(t->root->right));
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               avl_swl(&(t->root));
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               avl_nasty(t->root);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->right=right_subtree.root;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t->root->right = n;
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (t->root->balance++) return False;
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert2(0, "OSet{Word,Gen}_Insert: duplicate element added");
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Insert element e into the AVL tree t.  This is just a wrapper for
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// avl_insert() which doesn't return a Bool.
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetGen_Insert)(AvlTree* t, void* e)
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* n;
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise.  Even though OSetGen_AllocNode zeroes these fields,
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // we should do it again in case a node is removed and then
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // re-added to the tree.
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n          = node_of_elem(e);
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->left    = 0;
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->right   = 0;
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->balance = 0;
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Insert into an empty tree
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!t->root) {
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->root = n;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avl_insert(t, n);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->nElems++;
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->stackTop = 0;  // So the iterator can't get out of sync
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetWord_Insert)(AvlTree* t, UWord val)
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word* node = VG_(OSetGen_AllocNode)(t, sizeof(UWord));
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *node = val;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_Insert)(t, node);
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Lookup                                                       ---*/
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Find the *node* in t matching k, or NULL if not found.
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AvlNode* avl_lookup(const AvlTree* t, const void* k)
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word     cmpres;
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* curr = t->root;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t->cmp) {
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // General case
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (curr == NULL) return NULL;
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cmpres = slow_cmp(t, k, curr);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if      (cmpres < 0) curr = curr->left;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (cmpres > 0) curr = curr->right;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else return curr;
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Fast-track special case.  We use the no-check version of
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // elem_of_node because it saves about 10% on lookup time.  This
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // shouldn't be very dangerous because each node will have been
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // checked on insertion.
596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UWord w1 = *(const UWord*)k;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord w2;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (curr == NULL) return NULL;
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         w2 = *(UWord*)elem_of_node_no_check(curr);
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if      (w1 < w2) curr = curr->left;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (w1 > w2) curr = curr->right;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else return curr;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Find the *element* in t matching k, or NULL if not found.
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(OSetGen_Lookup)(const AvlTree* t, const void* k)
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* n;
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = avl_lookup(t, k);
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( n ? elem_of_node(n) : NULL );
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Find the *element* in t matching k, or NULL if not found;  use the given
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// comparison function rather than the standard one.
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(OSetGen_LookupWithCmp)(AvlTree* t, const void* k, OSetCmp_t cmp)
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Save the normal one to the side, then restore once we're done.
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void* e;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSetCmp_t tmpcmp;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpcmp = t->cmp;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->cmp = cmp;
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   e = VG_(OSetGen_Lookup)(t, k);
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->cmp = tmpcmp;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Is there an element matching k?
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(OSetGen_Contains)(const AvlTree* t, const void* k)
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (NULL != VG_(OSetGen_Lookup)(t, k));
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(OSetWord_Contains)(AvlTree* t, UWord val)
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (NULL != VG_(OSetGen_Lookup)(t, &val));
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Deletion                                                     ---*/
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool avl_removeroot(AvlTree* t);
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Remove an already-selected node n from the AVL tree t.
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Returns True if the depth of the tree has shrunk.
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool avl_remove(AvlTree* t, AvlNode* n)
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ch;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word cmpres = cmp_key_root(t, n);
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cmpres < 0) {
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AvlTree left_subtree;
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Remove from the left subtree
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(t->root->left);
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Only need to set the used fields in the subtree.
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left_subtree.root   = t->root->left;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left_subtree.cmp    = t->cmp;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left_subtree.keyOff = t->keyOff;
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ch = avl_remove(&left_subtree, n);
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->root->left = left_subtree.root;
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ch) {
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (t->root->balance++) {
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case -1: return True;
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case  0: return False;
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (t->root->right->balance) {
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            avl_swl(&(t->root));
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->balance = -1;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->left->balance = 1;
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            avl_swl(&(t->root));
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->balance = 0;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->left->balance = 0;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_swr(&(t->root->right));
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_swl(&(t->root));
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_nasty(t->root);
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (cmpres > 0) {
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Remove from the right subtree
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AvlTree right_subtree;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(t->root->right);
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Only need to set the used fields in the subtree.
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      right_subtree.root   = t->root->right;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      right_subtree.cmp    = t->cmp;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      right_subtree.keyOff = t->keyOff;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ch = avl_remove(&right_subtree, n);
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->root->right = right_subtree.root;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ch) {
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (t->root->balance--) {
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: return True;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: return False;
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (t->root->left->balance) {
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            avl_swr(&(t->root));
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->balance = 1;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->right->balance = -1;
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case -1:
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            avl_swr(&(t->root));
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->balance = 0;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t->root->right->balance = 0;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_swl(&(t->root->left));
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_swr(&(t->root));
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         avl_nasty(t->root);
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Found the node to be removed.
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(t->root == n);
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return avl_removeroot(t);
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Remove the root of the AVL tree t.
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Returns True if the depth of the tree has shrunk.
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool avl_removeroot(AvlTree* t)
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     ch;
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* n;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!t->root->left) {
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!t->root->right) {
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t->root = NULL;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->root = t->root->right;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!t->root->right) {
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->root = t->root->left;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t->root->balance < 0) {
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Remove from the left subtree
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n = t->root->left;
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n->right) n = n->right;
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Remove from the right subtree
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n = t->root->right;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n->left) n = n->left;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ch = avl_remove(t, n);
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->left    = t->root->left;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->right   = t->root->right;
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->balance = t->root->balance;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t->root    = n;
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n->balance == 0) return ch;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Remove and return the element matching the key 'k', or NULL
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// if not present.
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(OSetGen_Remove)(AvlTree* t, const void* k)
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Have to find the node first, then remove it.
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvlNode* n = avl_lookup(t, k);
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n) {
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avl_remove(t, n);
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->nElems--;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t->stackTop = 0;     // So the iterator can't get out of sync
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return elem_of_node(n);
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(OSetWord_Remove)(AvlTree* t, UWord val)
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void* n = VG_(OSetGen_Remove)(t, &val);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n) {
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_FreeNode)(t, n);
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Iterator                                                     ---*/
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The iterator is implemented using in-order traversal with an explicit
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// stack, which lets us do the traversal one step at a time and remember
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// where we are between each call to OSetGen_Next().
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetGen_ResetIter)(AvlTree* t)
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stackClear(t);
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t->root)
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stackPush(t, t->root, 1);
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetWord_ResetIter)(AvlTree* t)
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(t);
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(OSetGen_Next)(AvlTree* t)
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = 0;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSetNode* n = NULL;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This in-order traversal requires each node to be pushed and popped
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // three times.  These could be avoided by updating nodes in-situ on the
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // top of the stack, but the push/pop cost is so small that it's worth
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // keeping this loop in this simpler form.
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (stackPop(t, &n, &i)) {
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i) {
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: case_1:
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stackPush(t, n, 2);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* if (n->left)  stackPush(t, n->left, 1); */
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n->left) { n = n->left; goto case_1; }
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stackPush(t, n, 3);
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return elem_of_node(n);
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* if (n->right) stackPush(t, n->right, 1); */
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n->right) { n = n->right; goto case_1; }
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Stack empty, iterator is exhausted, return NULL
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(OSetWord_Next)(AvlTree* t, UWord* val)
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord* n = VG_(OSetGen_Next)(t);
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n) {
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *val = *n;
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// set up 'oset' for iteration so that the first key subsequently
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// produced VG_(OSetGen_Next) is the smallest key in the map
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// >= start_at.  Naturally ">=" is defined by the comparison
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// function supplied to VG_(OSetGen_Create).
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(OSetGen_ResetIterAt)(AvlTree* oset, const void* k)
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   AvlNode *t;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word    cmpresS; /* signed */
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord   cmpresU; /* unsigned */
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(oset);
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stackClear(oset);
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!oset->root)
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // We need to do regular search and fill in the stack.
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t = oset->root;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (t == NULL) return;
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (oset->cmp) {
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cmpresS = (Word)slow_cmp(oset, k, t);
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cmpresS = fast_cmp(k, t);
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Switch the sense of the comparison, since the comparison
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         order of args (k vs t) above is opposite to that of the
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         corresponding code in hg_wordfm.c. */
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cmpresS < 0) { cmpresS = 1; }
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (cmpresS > 0) { cmpresS = -1; }
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cmpresS == 0) {
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // We found the exact key -- we are done.
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // The iteration should start with this node.
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stackPush(oset, t, 2);
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // The stack now looks like {2, 2, ... ,2, 2}
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmpresU = (UWord)cmpresS;
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1);
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(cmpresU == 0 || cmpresU == 1);
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!cmpresU) {
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Push this node only if we go to the left child.
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stackPush(oset, t, 2);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t = cmpresU==0 ? t->left : t->right;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Miscellaneous operations                                     ---*/
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWord VG_(OSetGen_Size)(const AvlTree* t)
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(t);
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t->nElems;
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWord VG_(OSetWord_Size)(AvlTree* t)
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(OSetGen_Size)(t);
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void OSet_Print2( AvlTree* t, AvlNode* n,
929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         HChar*(*strElem)(void *), Int p )
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This is a recursive in-order traversal.
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int q = p;
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (NULL == n) return;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n->right) OSet_Print2(t, n->right, strElem, p+1);
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (q--) VG_(printf)(".. ");
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("%s\n", strElem(elem_of_node(n)));
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n->left) OSet_Print2(t, n->left, strElem, p+1);
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused))
941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void OSet_Print( AvlTree* t, const HChar *where,
942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        HChar*(*strElem)(void *) )
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-- start %s ----------------\n", where);
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSet_Print2(t, t->root, strElem, 0);
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-- end   %s ----------------\n", where);
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
952