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