blob: 1b9ff1fcedcd0ed1bf140bfc61a9eb32dff6bf8c [file] [log] [blame]
njn7b880bc2005-08-14 22:43:53 +00001
2#include <assert.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "pub_core_basics.h"
8#include "pub_core_libcbase.h"
9#include "pub_core_libcassert.h"
10#include "pub_core_libcprint.h"
11
12// I need this to avoid some signedness warnings, not sure why
sewardjb1e123a2005-08-19 09:07:34 +000013// #define Char char
14// jrs 19 Aug 2005: m_oset.c relies on Char being a signed char.
15// It appears that plain 'char' on ppc32 is unsigned and so the
16// above #define screws up the AVL tree balancing logic and
17// leads to segfaults. Commenting it out and using the standard
18// definition of Char from pub_core_basics.h seems a good solution
19// as that has the same signedness on all platforms.
njn7b880bc2005-08-14 22:43:53 +000020
21// Crudely redirect various VG_(foo)() functions to their libc equivalents.
22#undef vg_assert
23#define vg_assert(e) assert(e)
24#undef vg_assert2
25#define vg_assert2(e, fmt, args...) assert(e)
26
27#define vgPlain_printf printf
28#define vgPlain_memset memset
29#define vgPlain_memcpy memcpy
30#define vgPlain_random random
31
32#include "coregrind/m_oset.c"
33
34#define NN 1000 // Size of OSets being created
35
36//---------------------------------------------------------------------------
37// Int example
38//---------------------------------------------------------------------------
39
40// This example shows that an element can be a single value (in this case an
41// Int), in which case the element is also the key.
42
43__attribute__((unused))
44static Char *intToStr(void *p)
45{
46 static char buf[16];
47 sprintf(buf, "%d", *(Int*)p);
48 return buf;
49}
50
51__attribute__((unused))
52static Int intCmp(void* vkey, void* velem)
53{
54 return *(Int*)vkey - *(Int*)velem;
55}
56
57void example1(void)
58{
59 Int i, v, n, prev;
60 Int* vs[NN];
61 Int *pv;
62
63 // Create a static OSet of Ints. This one uses fast (built-in)
64 // comparisons.
65 OSet* oset1 = VG_(OSet_Create)(0,
66 NULL,
67 (void*)malloc, free);
68
69 // Try some operations on an empty OSet to ensure they don't screw up.
70 vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
71 vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
72 vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
73 vg_assert( ! VG_(OSet_Next)(oset1) );
74 vg_assert( 0 == VG_(OSet_Size)(oset1) );
75
76 // Create some elements, with gaps (they're all even) but no dups,
77 // and shuffle them randomly.
78 for (i = 0; i < NN; i++) {
79 vs[i] = VG_(OSet_AllocNode)(oset1, sizeof(Int));
80 *(vs[i]) = 2*i;
81 }
82 for (i = 0; i < NN; i++) {
83 Int r1 = random() % NN;
84 Int r2 = random() % NN;
85 Int* tmp= vs[r1];
86 vs[r1] = vs[r2];
87 vs[r2] = tmp;
88 }
89
90 // Insert the elements
91 for (i = 0; i < NN; i++) {
92 VG_(OSet_Insert)(oset1, vs[i]);
93 }
94
95 // Check the size
96 vg_assert( NN == VG_(OSet_Size)(oset1) );
97
98 // Check we can find all the elements we inserted
99 for (i = 0; i < NN; i++) {
100 assert( VG_(OSet_Contains)(oset1, vs[i]) );
101 }
102
103 // Check we cannot find elements we did not insert, below, within (odd
104 // numbers), and above the inserted elements.
105 v = -1;
106 assert( ! VG_(OSet_Contains)(oset1, &v) );
107 for (i = 0; i < NN; i++) {
108 v = *(vs[i]) + 1;
109 assert( ! VG_(OSet_Contains)(oset1, &v) );
110 }
111 v = NN*2;
112 assert( ! VG_(OSet_Contains)(oset1, &v) );
113
114 // Check we can find all the elements we inserted, and the right values
115 // are returned.
116 for (i = 0; i < NN; i++) {
117 assert( vs[i] == VG_(OSet_Lookup)(oset1, vs[i]) );
118 }
119
120 // Check that we can iterate over the OSet elements in sorted order, and
121 // there is the right number of them.
122 n = 0;
123 pv = NULL;
124 prev = -1;
125 VG_(OSet_ResetIter)(oset1);
126 while ( (pv = VG_(OSet_Next)(oset1)) ) {
127 Int curr = *pv;
128 assert(prev < curr);
129 prev = curr;
130 n++;
131 }
132 assert(NN == n);
133 vg_assert( ! VG_(OSet_Next)(oset1) );
134 vg_assert( ! VG_(OSet_Next)(oset1) );
135
136 // Check that we can remove half of the elements, and that their values
137 // are as expected.
138 for (i = 0; i < NN; i += 2) {
139 assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
140 assert( pv == vs[i] );
141 }
142
143 // Check the size
144 vg_assert( NN/2 == VG_(OSet_Size)(oset1) );
145
146 // Check we can find the remaining elements (with the right values).
147 for (i = 1; i < NN; i += 2) {
njnaa260e82005-08-17 21:06:07 +0000148 assert( pv = VG_(OSet_LookupWithCmp)(oset1, vs[i], NULL) );
njn7b880bc2005-08-14 22:43:53 +0000149 assert( pv == vs[i] );
150 }
151
152 // Check we cannot find any of the elements we removed.
153 for (i = 0; i < NN; i += 2) {
154 assert( ! VG_(OSet_Contains)(oset1, vs[i]) );
155 }
156
157 // Check that we can remove the remaining half of the elements, and that
158 // their values are as expected.
159 for (i = 1; i < NN; i += 2) {
160 assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
161 assert( pv == vs[i] );
162 }
163
164 // Try some more operations on the empty OSet to ensure they don't screw up.
165 vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
166 vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
167 vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
168 vg_assert( ! VG_(OSet_Next)(oset1) );
169 vg_assert( 0 == VG_(OSet_Size)(oset1) );
170
171 // Free a few elements
172 VG_(OSet_FreeNode)(oset1, vs[0]);
173 VG_(OSet_FreeNode)(oset1, vs[1]);
174 VG_(OSet_FreeNode)(oset1, vs[2]);
175
176 // Re-insert remaining elements, to give OSet_Destroy something to work with.
177 for (i = 3; i < NN; i++) {
178 VG_(OSet_Insert)(oset1, vs[i]);
179 }
180
181 // Print the list
182 OSet_Print(oset1, "foo", intToStr);
183
184 // Destroy the OSet
185 VG_(OSet_Destroy)(oset1);
186}
187
188
189//---------------------------------------------------------------------------
190// Struct example
191//---------------------------------------------------------------------------
192
193// This element shows that a key can be in the middle of the element, and
194// be of arbitrary size and even span multiple (contiguous) fields. It
195// also demonstrates how an OSet can be used to implement a list of
196// non-overlapping intervals.
197
198typedef struct {
199 Int b1;
200 Addr first;
201 Addr last;
202 Int b2;
203}
204Block;
205
206__attribute__((unused))
207static Char *blockToStr(void *p)
208{
209 static char buf[32];
210 Block* b = (Block*)p;
211 sprintf(buf, "<(%d) %lu..%lu (%d)>", b->b1, b->first, b->last, b->b2);
212 return buf;
213}
214
215static Int blockCmp(void* vkey, void* velem)
216{
217 Addr key = *(Addr*)vkey;
218 Block* elem = (Block*)velem;
219
220 assert(elem->first <= elem->last);
221 if (key < elem->first) return -1;
222 if (key > elem->last) return 1;
223 return 0;
224}
225
226void example2(void)
227{
228 Int i, n;
229 Addr a;
230 Block* vs[NN];
231 Block v, prev;
232 Block *pv;
233
234 // Create a dynamic OSet of Blocks. This one uses slow (custom)
235 // comparisons.
236 OSet* oset2 = VG_(OSet_Create)(offsetof(Block, first),
237 blockCmp,
238 (void*)malloc, free);
239
240 // Try some operations on an empty OSet to ensure they don't screw up.
241 vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
242 vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
243 vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
244 vg_assert( ! VG_(OSet_Next)(oset2) );
245 vg_assert( 0 == VG_(OSet_Size)(oset2) );
246
247 // Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
248 // no dups, and shuffle them randomly.
249 for (i = 0; i < NN; i++) {
250 vs[i] = VG_(OSet_AllocNode)(oset2, sizeof(Block));
251 vs[i]->b1 = i;
252 vs[i]->first = i*10 + 1;
253 vs[i]->last = vs[i]->first + 2;
254 vs[i]->b2 = i+1;
255 }
256 for (i = 0; i < NN; i++) {
257 Int r1 = random() % NN;
258 Int r2 = random() % NN;
259 Block* tmp = vs[r1];
260 vs[r1] = vs[r2];
261 vs[r2] = tmp;
262 }
263
264 // Insert the elements
265 for (i = 0; i < NN; i++) {
266 VG_(OSet_Insert)(oset2, vs[i]);
267 }
268
269 // Check the size
270 vg_assert( NN == VG_(OSet_Size)(oset2) );
271
272 // Check we can find all the elements we inserted, within the full range
273 // of each Block.
274 for (i = 0; i < NN; i++) {
275 a = vs[i]->first + 0; assert( VG_(OSet_Contains)(oset2, &a) );
276 a = vs[i]->first + 1; assert( VG_(OSet_Contains)(oset2, &a) );
277 a = vs[i]->first + 2; assert( VG_(OSet_Contains)(oset2, &a) );
278 }
279
280 // Check we cannot find elements we did not insert, below and above the
281 // ranges of the inserted elements.
282 a = 0;
283 assert( ! VG_(OSet_Contains)(oset2, &a) );
284 for (i = 0; i < NN; i++) {
285 a = vs[i]->first - 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
286 a = vs[i]->first + 3; assert( ! VG_(OSet_Contains)(oset2, &a) );
287 }
288
289 // Check we can find all the elements we inserted, and the right values
290 // are returned.
291 for (i = 0; i < NN; i++) {
292 a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
293 a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
294 a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
njnaa260e82005-08-17 21:06:07 +0000295 assert( vs[i] == VG_(OSet_LookupWithCmp)(oset2, &a, blockCmp) );
njn7b880bc2005-08-14 22:43:53 +0000296 }
297
298 // Check that we can iterate over the OSet elements in sorted order, and
299 // there is the right number of them.
300 n = 0;
301 pv = NULL;
302 prev.last = 0;
303 VG_(OSet_ResetIter)(oset2);
304 while ( (pv = VG_(OSet_Next)(oset2)) ) {
305 Block curr = *pv;
306 assert(prev.last < curr.first);
307 prev = curr;
308 n++;
309 }
310 assert(NN == n);
311 vg_assert( ! VG_(OSet_Next)(oset2) );
312 vg_assert( ! VG_(OSet_Next)(oset2) );
313
314 // Check that we can remove half of the elements, and that their values
315 // are as expected.
316 for (i = 0; i < NN; i += 2) {
317 a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
318 }
319
320 // Check the size
321 vg_assert( NN/2 == VG_(OSet_Size)(oset2) );
322
323 // Check we can find the remaining elements (with the right values).
324 for (i = 1; i < NN; i += 2) {
325 a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
326 a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
327 a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
328 }
329
330 // Check we cannot find any of the elements we removed.
331 for (i = 0; i < NN; i += 2) {
332 a = vs[i]->first + 0; assert( ! VG_(OSet_Contains)(oset2, &a) );
333 a = vs[i]->first + 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
334 a = vs[i]->first + 2; assert( ! VG_(OSet_Contains)(oset2, &a) );
335 }
336
337 // Check that we can remove the remaining half of the elements, and that
338 // their values are as expected.
339 for (i = 1; i < NN; i += 2) {
340 a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
341 }
342
343 // Try some more operations on the empty OSet to ensure they don't screw up.
344 vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
345 vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
346 vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
347 vg_assert( ! VG_(OSet_Next)(oset2) );
348 vg_assert( 0 == VG_(OSet_Size)(oset2) );
349
350 // Re-insert all elements, to give OSet_Destroy something to work with.
351 for (i = 0; i < NN; i++) {
352 VG_(OSet_Insert)(oset2, vs[i]);
353 }
354
355 // Destroy the OSet
356 VG_(OSet_Destroy)(oset2);
357}
358
359//-----------------------------------------------------------------------
360// main()
361//-----------------------------------------------------------------------
362
363int main(void)
364{
365 example1();
366 example2();
367 return 0;
368}