1
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
13 // #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.
20
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
31 #include "coregrind/m_oset.c"
32
33 #define NN 1000 // Size of OSets being created
34
35
36 /* Consistent random number generator, so it produces the
37 same results on all platforms. */
38
39 #define random error_do_not_use_libc_random
40
41 static UInt seed = 0;
myrandom(void)42 static UInt myrandom( void )
43 {
44 seed = (1103515245 * seed + 12345);
45 return seed;
46 }
47
allocate_node(HChar * cc,SizeT szB)48 static void* allocate_node(HChar* cc, SizeT szB)
49 { return malloc(szB); }
50
free_node(void * p)51 static void free_node(void* p)
52 { return free(p); }
53
54
55 //---------------------------------------------------------------------------
56 // Word example
57 //---------------------------------------------------------------------------
58
59 // This example shows that an element can be a single value (in this
60 // case a Word), in which case the element is also the key.
61
62 __attribute__((unused))
wordToStr(void * p)63 static Char *wordToStr(void *p)
64 {
65 static char buf[32];
66 sprintf(buf, "%ld", *(Word*)p);
67 return buf;
68 }
69
70 __attribute__((unused))
wordCmp(void * vkey,void * velem)71 static Word wordCmp(void* vkey, void* velem)
72 {
73 return *(Word*)vkey - *(Word*)velem;
74 }
75
example1(void)76 void example1(void)
77 {
78 Int i, n;
79 Word v, prev;
80 Word* vs[NN];
81 Word *pv;
82
83 // Create a static OSet of Ints. This one uses fast (built-in)
84 // comparisons.
85 OSet* oset = VG_(OSetGen_Create)(0,
86 NULL,
87 allocate_node, "oset_test.1", free_node);
88
89 // Try some operations on an empty OSet to ensure they don't screw up.
90 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
91 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
92 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
93 vg_assert( ! VG_(OSetGen_Next)(oset) );
94 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
95
96 // Create some elements, with gaps (they're all even) but no dups,
97 // and shuffle them randomly.
98 for (i = 0; i < NN; i++) {
99 vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Word));
100 *(vs[i]) = 2*i;
101 }
102 seed = 0;
103 for (i = 0; i < NN; i++) {
104 Word r1 = myrandom() % NN;
105 Word r2 = myrandom() % NN;
106 Word* tmp= vs[r1];
107 vs[r1] = vs[r2];
108 vs[r2] = tmp;
109 }
110
111 // Insert the elements
112 for (i = 0; i < NN; i++) {
113 VG_(OSetGen_Insert)(oset, vs[i]);
114 }
115
116 // Check the size
117 vg_assert( NN == VG_(OSetGen_Size)(oset) );
118
119 // Check we can find all the elements we inserted
120 for (i = 0; i < NN; i++) {
121 assert( VG_(OSetGen_Contains)(oset, vs[i]) );
122 }
123
124 // Check we cannot find elements we did not insert, below, within (odd
125 // numbers), and above the inserted elements.
126 v = -1;
127 assert( ! VG_(OSetGen_Contains)(oset, &v) );
128 for (i = 0; i < NN; i++) {
129 v = *(vs[i]) + 1;
130 assert( ! VG_(OSetGen_Contains)(oset, &v) );
131 }
132 v = NN*2;
133 assert( ! VG_(OSetGen_Contains)(oset, &v) );
134
135 // Check we can find all the elements we inserted, and the right values
136 // are returned.
137 for (i = 0; i < NN; i++) {
138 assert( vs[i] == VG_(OSetGen_Lookup)(oset, vs[i]) );
139 }
140
141 // Check that we can iterate over the OSet elements in sorted order, and
142 // there is the right number of them.
143 n = 0;
144 pv = NULL;
145 prev = -1;
146 VG_(OSetGen_ResetIter)(oset);
147 while ( (pv = VG_(OSetGen_Next)(oset)) ) {
148 Word curr = *pv;
149 assert(prev < curr);
150 prev = curr;
151 n++;
152 }
153 assert(NN == n);
154 vg_assert( ! VG_(OSetGen_Next)(oset) );
155 vg_assert( ! VG_(OSetGen_Next)(oset) );
156
157 // Check that we can remove half of the elements, and that their values
158 // are as expected.
159 for (i = 0; i < NN; i += 2) {
160 assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
161 assert( pv == vs[i] );
162 }
163
164 // Check the size
165 vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
166
167 // Check we can find the remaining elements (with the right values).
168 for (i = 1; i < NN; i += 2) {
169 assert( pv = VG_(OSetGen_LookupWithCmp)(oset, vs[i], NULL) );
170 assert( pv == vs[i] );
171 }
172
173 // Check we cannot find any of the elements we removed.
174 for (i = 0; i < NN; i += 2) {
175 assert( ! VG_(OSetGen_Contains)(oset, vs[i]) );
176 }
177
178 // Check that we can remove the remaining half of the elements, and that
179 // their values are as expected.
180 for (i = 1; i < NN; i += 2) {
181 assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
182 assert( pv == vs[i] );
183 }
184
185 // Try some more operations on the empty OSet to ensure they don't screw up.
186 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
187 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
188 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
189 vg_assert( ! VG_(OSetGen_Next)(oset) );
190 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
191
192 // Free a few elements
193 VG_(OSetGen_FreeNode)(oset, vs[0]);
194 VG_(OSetGen_FreeNode)(oset, vs[1]);
195 VG_(OSetGen_FreeNode)(oset, vs[2]);
196
197 // Re-insert remaining elements, to give OSetGen_Destroy something to
198 // work with.
199 for (i = 3; i < NN; i++) {
200 VG_(OSetGen_Insert)(oset, vs[i]);
201 }
202
203 // Print the list
204 OSet_Print(oset, "oset1", wordToStr);
205
206 // Destroy the OSet
207 VG_(OSetGen_Destroy)(oset);
208 }
209
210
example1b(void)211 void example1b(void)
212 {
213 Int i, n;
214 Word v = 0, prev;
215 Word vs[NN];
216
217 // Create a static OSet of Ints. This one uses fast (built-in)
218 // comparisons.
219 OSet* oset = VG_(OSetWord_Create)(allocate_node, "oset_test.2", free_node);
220
221 // Try some operations on an empty OSet to ensure they don't screw up.
222 vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
223 vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
224 vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
225 vg_assert( 0 == VG_(OSetWord_Size)(oset) );
226
227 // Create some elements, with gaps (they're all even) but no dups,
228 // and shuffle them randomly.
229 for (i = 0; i < NN; i++) {
230 vs[i] = 2*i;
231 }
232 seed = 0;
233 for (i = 0; i < NN; i++) {
234 Word r1 = myrandom() % NN;
235 Word r2 = myrandom() % NN;
236 Word tmp = vs[r1];
237 vs[r1] = vs[r2];
238 vs[r2] = tmp;
239 }
240
241 // Insert the elements
242 for (i = 0; i < NN; i++) {
243 VG_(OSetWord_Insert)(oset, vs[i]);
244 }
245
246 // Check the size
247 vg_assert( NN == VG_(OSetWord_Size)(oset) );
248
249 // Check we can find all the elements we inserted
250 for (i = 0; i < NN; i++) {
251 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
252 }
253
254 // Check we cannot find elements we did not insert, below, within (odd
255 // numbers), and above the inserted elements.
256 v = -1;
257 assert( ! VG_(OSetWord_Contains)(oset, v) );
258 for (i = 0; i < NN; i++) {
259 v = vs[i] + 1;
260 assert( ! VG_(OSetWord_Contains)(oset, v) );
261 }
262 v = NN*2;
263 assert( ! VG_(OSetWord_Contains)(oset, v) );
264
265 // Check we can find all the elements we inserted.
266 for (i = 0; i < NN; i++) {
267 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
268 }
269
270 // Check that we can iterate over the OSet elements in sorted order, and
271 // there is the right number of them.
272 n = 0;
273 prev = -1;
274 VG_(OSetWord_ResetIter)(oset);
275 while ( VG_(OSetWord_Next)(oset, &v) ) {
276 Word curr = v;
277 assert(prev < curr);
278 prev = curr;
279 n++;
280 }
281 assert(NN == n);
282 vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
283 vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
284
285 // Check that we can remove half of the elements.
286 for (i = 0; i < NN; i += 2) {
287 assert( VG_(OSetWord_Remove)(oset, vs[i]) );
288 }
289
290 // Check the size
291 vg_assert( NN/2 == VG_(OSetWord_Size)(oset) );
292
293 // Check we can find the remaining elements (with the right values).
294 for (i = 1; i < NN; i += 2) {
295 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
296 }
297
298 // Check we cannot find any of the elements we removed.
299 for (i = 0; i < NN; i += 2) {
300 assert( ! VG_(OSetWord_Contains)(oset, vs[i]) );
301 }
302
303 // Check that we can remove the remaining half of the elements.
304 for (i = 1; i < NN; i += 2) {
305 assert( VG_(OSetWord_Remove)(oset, vs[i]) );
306 }
307
308 // Try some more operations on the empty OSet to ensure they don't screw up.
309 vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
310 vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
311 vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
312 vg_assert( 0 == VG_(OSetWord_Size)(oset) );
313
314 // Re-insert remaining elements, to give OSetWord_Destroy something to
315 // work with.
316 for (i = 3; i < NN; i++) {
317 VG_(OSetWord_Insert)(oset, vs[i]);
318 }
319
320 // Print the list
321 OSet_Print(oset, "oset1b", wordToStr);
322
323 // Destroy the OSet
324 VG_(OSetWord_Destroy)(oset);
325 }
326
327
328 //---------------------------------------------------------------------------
329 // Struct example
330 //---------------------------------------------------------------------------
331
332 // This element shows that a key can be in the middle of the element, and
333 // be of arbitrary size and even span multiple (contiguous) fields. It
334 // also demonstrates how an OSet can be used to implement a list of
335 // non-overlapping intervals.
336
337 typedef struct {
338 Int b1;
339 Addr first;
340 Addr last;
341 Int b2;
342 }
343 Block;
344
345 __attribute__((unused))
blockToStr(void * p)346 static Char *blockToStr(void *p)
347 {
348 static char buf[32];
349 Block* b = (Block*)p;
350 sprintf(buf, "<(%d) %lu..%lu (%d)>", b->b1, b->first, b->last, b->b2);
351 return buf;
352 }
353
blockCmp(const void * vkey,const void * velem)354 static Word blockCmp(const void* vkey, const void* velem)
355 {
356 Addr key = *(const Addr*)vkey;
357 const Block* elem = (const Block*)velem;
358
359 assert(elem->first <= elem->last);
360 if (key < elem->first) return -1;
361 if (key > elem->last) return 1;
362 return 0;
363 }
364
example2(void)365 void example2(void)
366 {
367 Int i, n;
368 Addr a;
369 Block* vs[NN];
370 Block v, prev;
371 Block *pv;
372
373 // Create a dynamic OSet of Blocks. This one uses slow (custom)
374 // comparisons.
375 OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
376 blockCmp,
377 allocate_node, "oset_test.3", free_node);
378
379 // Try some operations on an empty OSet to ensure they don't screw up.
380 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
381 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
382 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
383 vg_assert( ! VG_(OSetGen_Next)(oset) );
384 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
385
386 // Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
387 // no dups, and shuffle them randomly.
388 for (i = 0; i < NN; i++) {
389 vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Block));
390 vs[i]->b1 = i;
391 vs[i]->first = i*10 + 1;
392 vs[i]->last = vs[i]->first + 2;
393 vs[i]->b2 = i+1;
394 }
395 seed = 0;
396 for (i = 0; i < NN; i++) {
397 Int r1 = myrandom() % NN;
398 Int r2 = myrandom() % NN;
399 Block* tmp = vs[r1];
400 vs[r1] = vs[r2];
401 vs[r2] = tmp;
402 }
403
404 // Insert the elements
405 for (i = 0; i < NN; i++) {
406 VG_(OSetGen_Insert)(oset, vs[i]);
407 }
408
409 // Check the size
410 vg_assert( NN == VG_(OSetGen_Size)(oset) );
411
412 // Check we can find all the elements we inserted, within the full range
413 // of each Block.
414 for (i = 0; i < NN; i++) {
415 a = vs[i]->first + 0; assert( VG_(OSetGen_Contains)(oset, &a) );
416 a = vs[i]->first + 1; assert( VG_(OSetGen_Contains)(oset, &a) );
417 a = vs[i]->first + 2; assert( VG_(OSetGen_Contains)(oset, &a) );
418 }
419
420 // Check we cannot find elements we did not insert, below and above the
421 // ranges of the inserted elements.
422 a = 0;
423 assert( ! VG_(OSetGen_Contains)(oset, &a) );
424 for (i = 0; i < NN; i++) {
425 a = vs[i]->first - 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
426 a = vs[i]->first + 3; assert( ! VG_(OSetGen_Contains)(oset, &a) );
427 }
428
429 // Check we can find all the elements we inserted, and the right values
430 // are returned.
431 for (i = 0; i < NN; i++) {
432 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
433 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
434 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
435 assert( vs[i] == VG_(OSetGen_LookupWithCmp)(oset, &a, blockCmp) );
436 }
437
438 // Check that we can iterate over the OSet elements in sorted order, and
439 // there is the right number of them.
440 n = 0;
441 pv = NULL;
442 prev.last = 0;
443 VG_(OSetGen_ResetIter)(oset);
444 while ( (pv = VG_(OSetGen_Next)(oset)) ) {
445 Block curr = *pv;
446 assert(prev.last < curr.first);
447 prev = curr;
448 n++;
449 }
450 assert(NN == n);
451 vg_assert( ! VG_(OSetGen_Next)(oset) );
452 vg_assert( ! VG_(OSetGen_Next)(oset) );
453
454 // Check that we can remove half of the elements, and that their values
455 // are as expected.
456 for (i = 0; i < NN; i += 2) {
457 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
458 }
459
460 // Check the size
461 vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
462
463 // Check we can find the remaining elements (with the right values).
464 for (i = 1; i < NN; i += 2) {
465 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
466 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
467 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
468 }
469
470 // Check we cannot find any of the elements we removed.
471 for (i = 0; i < NN; i += 2) {
472 a = vs[i]->first + 0; assert( ! VG_(OSetGen_Contains)(oset, &a) );
473 a = vs[i]->first + 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
474 a = vs[i]->first + 2; assert( ! VG_(OSetGen_Contains)(oset, &a) );
475 }
476
477 // Check that we can remove the remaining half of the elements, and that
478 // their values are as expected.
479 for (i = 1; i < NN; i += 2) {
480 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
481 }
482
483 // Try some more operations on the empty OSet to ensure they don't screw up.
484 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
485 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
486 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
487 vg_assert( ! VG_(OSetGen_Next)(oset) );
488 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
489
490 // Re-insert all elements, to give OSetGen_Destroy something to work with.
491 for (i = 0; i < NN; i++) {
492 VG_(OSetGen_Insert)(oset, vs[i]);
493 }
494
495 // Destroy the OSet
496 VG_(OSetGen_Destroy)(oset);
497 }
498
499 //-----------------------------------------------------------------------
500 // main()
501 //-----------------------------------------------------------------------
502
main(void)503 int main(void)
504 {
505 example1();
506 example1b();
507 example2();
508 return 0;
509 }
510