7428d6ec795f8ebce2c9399defcbd773a84e7396
[libfirm] / pdeq.c
1 /* Pdeq --- double ended queue of generic pointers.
2    Copyright (C) 1995, 1996 Christian von Roques */
3
4 /* $Id$ */
5
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 # ifdef HAVE_STRING_H
14 #  include <string.h>
15 # endif
16 #include "tune.h"
17 #include "cookies.h"
18 #include "debug.h"
19 #include "malloc.h"
20 #include "pdeq.h"
21
22
23 #ifndef INLINE
24 #ifdef USE_GCC_INLINE
25 #define INLINE inline
26 #else
27 #define INLINE
28 #endif
29 #endif
30
31 /* # of data items in block */
32 #define NDATA ((int)((PREF_MALLOC_SIZE - offsetof (pdeq, data)) / sizeof (void *)))
33
34 #ifdef NDEBUG
35 # define VRFY(dq) ((void)0)
36 #else
37 # define VRFY(dq) \
38     (d_(df_vrfy_level,1) ? _pdeq_vrfy ((dq)) : assert ((dq) && ((dq)->cookie == PDEQ_COOKIE1)))
39 #endif
40
41
42 struct pdeq {
43 #ifndef NDEBUG
44   unsigned cookie;
45 #endif
46   pdeq *l_end, *r_end;          /* left and right ends of the deque */
47   pdeq *l, *r;                  /*  left and right neighbour */
48   int n, p;
49   const void *data[1];
50 };
51
52
53 /* cache of unused, pdeq blocks to speed up new_pdeq and del_pdeq. */
54 /* +1 for compilers that can't grok empty arrays */
55 pdeq *pdeq_block_cache[TUNE_NSAVED_PDEQS+1];
56 unsigned pdeqs_cached;          /* # pdeqs in pdeq_store */
57
58
59 static INLINE void
60 free_pdeq_block (pdeq *p)
61 {
62 #ifndef NDEBUG
63   p->cookie = 0xbadf00d1;
64 #endif
65   if (pdeqs_cached < TUNE_NSAVED_PDEQS) {
66     if (d_ (df_pdeq, 2)) printf ("[%p ==> pdeq_block_cache] ", p);
67     pdeq_block_cache[pdeqs_cached++] = p;
68   } else {
69     if (d_ (df_pdeq, 2)) printf ("[%p ==> free] ", p);
70     xfree (p);
71   }
72 }
73
74
75 static INLINE pdeq *
76 alloc_pdeq_block (void)
77 {
78   pdeq *p;
79   if (TUNE_NSAVED_PDEQS && pdeqs_cached) {
80     p = pdeq_block_cache[--pdeqs_cached];
81     if (d_ (df_pdeq, 2)) printf ("[pdeq_block_cache ==> %p] ", p);
82   } else {
83     p = xmalloc (PREF_MALLOC_SIZE);
84     if (d_ (df_pdeq, 2)) printf ("[malloc ==> %p] ", p);
85   }
86   return p;
87 }
88
89
90 #ifndef NDEBUG
91 void
92 _pdeq_vrfy (pdeq *dq)
93 {
94   pdeq *q;
95
96   if (d_ (df_pdeq, 5)) printf ("[pdeq_vrfy %p] ", dq);
97
98   assert (   dq
99           && (dq->cookie == PDEQ_COOKIE1)
100           && (dq->l_end && dq->r_end));
101   q = dq->l_end;
102   while (q) {
103     assert (   ((q == dq) || (q->cookie == PDEQ_COOKIE2))
104             && ((q == dq->l_end) ^ (q->l!=0))
105             && ((q == dq->r_end) ^ (q->r!=0))
106             && (!q->l || (q == q->l->r))
107             && ((q->n>=0) && (q->n<=NDATA))
108             && ((q == dq->l_end) || (q == dq->r_end) || (q->n == NDATA))
109             && ((q->p>=0) && (q->p<NDATA)));
110     q = q->r;
111   }
112 }
113 #endif
114
115
116 pdeq *
117 new_pdeq (void)
118 {
119   pdeq *dq;
120
121   dq = alloc_pdeq_block();
122
123 #ifndef NDEBUG
124   dq->cookie = PDEQ_COOKIE1;
125 #endif
126   dq->l_end = dq->r_end = dq;
127   dq->l = dq->r = NULL;
128   dq->n = dq->p = 0;
129
130   VRFY (dq);
131   if (d_ (df_pdeq, 1)) printf ("(new_pdeq ==> %p)\n", dq);
132   return dq;
133 }
134
135
136 pdeq *
137 new_pdeq1 (const void *x)
138 {
139   return pdeq_putr (new_pdeq(), x);
140 }
141
142
143 void
144 del_pdeq (pdeq *dq)
145 {
146   pdeq *q, *qq;
147
148   VRFY (dq);
149
150   q = dq->l_end;                /* left end of chain */
151   /* pdeq trunk empty, but !pdeq_empty() ==> trunk not in chain */
152   if (dq->n == 0 && dq->l_end != dq ) {
153     free_pdeq_block (dq);
154   }
155
156   /* Free all blocks in the pdeq chain */
157   do {
158     qq = q->r;
159     free_pdeq_block (q);
160   } while ((q = qq));
161
162   if (d_ (df_pdeq, 1)) printf ("(del_pdeq %p)\n", dq);
163 }
164
165
166 bool
167 pdeq_empty (pdeq *dq)
168 {
169   VRFY (dq);
170   if (d_ (df_pdeq, 4)) printf ("(pdeq_empty %p ==> %d)\n", dq, dq->l_end->n == 0);
171   return dq->l_end->n == 0;
172 }
173
174
175 int
176 pdeq_len (pdeq *dq)
177 {
178   int n;
179   pdeq *q;
180
181   VRFY (dq);
182
183   n = 0;
184   q = dq->l_end;
185   do {
186     n += q->n;
187     q = q->r;
188   }  while (q);
189
190   if (d_ (df_pdeq, 4)) printf ("(pdeq_len %p ==> %d)\n", dq, n);
191   return n;
192 }
193
194
195 pdeq *
196 pdeq_putr (pdeq *dq, const void *x)
197 {
198   pdeq *rdq;
199   int n;
200   bool pr = 0;
201
202   VRFY (dq);
203
204   rdq = dq->r_end;
205   if (rdq->n >= NDATA) {        /* tailblock full */
206     pdeq *ndq;
207
208     ndq = dq;                   /* try to reuse trunk, but ... */
209     if (dq->n) {                /* ... if trunk used */
210       /* allocate and init new block */
211       ndq = alloc_pdeq_block ();
212       pr = d_ (df_pdeq, 2);
213 #ifndef NDEBUG
214       ndq->cookie = PDEQ_COOKIE2;
215 #endif
216       ndq->l_end = ndq->r_end = NULL;
217     }
218
219     ndq->r = NULL;
220     ndq->l = rdq; rdq->r = ndq;
221     ndq->n = 0; ndq->p = 0;
222     dq->r_end = ndq;
223     rdq = ndq;
224   }
225
226   n = rdq->n++ + rdq->p;
227   if (n >= NDATA) n -= NDATA;
228
229   rdq->data[n] = x;
230
231   VRFY (dq);
232   if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putr %p %p)\n", dq, x);
233   return dq;
234 }
235
236
237 pdeq *
238 pdeq_putl (pdeq *dq, const void *x)
239 {
240   pdeq *ldq;
241   int p;
242   bool pr = 0;
243
244   VRFY (dq);
245
246   ldq = dq->l_end;
247   if (ldq->n >= NDATA) {        /* headblock full */
248     pdeq *ndq;
249
250     ndq = dq;                   /* try to reuse trunk, but ... */
251     if (dq->n) {                /* ... if trunk used */
252       /* allocate and init new block */
253       ndq = alloc_pdeq_block ();
254       pr = d_ (df_pdeq, 2);
255 #ifndef NDEBUG
256       ndq->cookie = PDEQ_COOKIE2;
257 #endif
258       ndq->l_end = ndq->r_end = NULL;
259     }
260
261     ndq->l = NULL;
262     ndq->r = ldq; ldq->l = ndq;
263     ndq->n = 0; ndq->p = 0;
264     dq->l_end = ndq;
265     ldq = ndq;
266   }
267
268   ldq->n++;
269   p = ldq->p - 1;
270   if (p < 0) p += NDATA;
271   ldq->p = p;
272
273   ldq->data[p] = x;
274
275   VRFY (dq);
276   if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putl %p %p)\n", dq, x);
277   return dq;
278 }
279
280
281 void *
282 pdeq_getr (pdeq *dq)
283 {
284   pdeq *rdq;
285   const void *x;
286   int n;
287   bool pr = 0;
288
289   VRFY (dq);
290   assert (dq->l_end->n);
291
292   rdq = dq->r_end;
293   n = rdq->p + --rdq->n;
294   if (n>=NDATA) n -= NDATA;
295   x = rdq->data[n];
296
297   if (rdq->n == 0) {
298     if (rdq->l) {
299       dq->r_end = rdq->l;
300       rdq->l->r = NULL;
301       rdq->l = NULL;
302     } else {
303       dq->r_end = dq->l_end = dq;
304     }
305     if (dq != rdq) {
306       free_pdeq_block (rdq);
307       pr = d_ (df_pdeq, 2);
308     }
309   }
310
311   VRFY (dq);
312   if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getr %p ==> %p)\n", dq, x);
313   return (void *)x;
314 }
315
316
317 void *
318 pdeq_getl (pdeq *dq)
319 {
320   pdeq *ldq;
321   const void *x;
322   int p;
323   bool pr = 0;
324
325   VRFY (dq);
326   assert (dq->l_end->n);
327
328   ldq = dq->l_end;
329   p = ldq->p;
330   x = ldq->data[p];
331   if (++p >= NDATA) p = 0;
332   ldq->p = p;
333
334   if (--ldq->n == 0) {
335     if (ldq->r) {
336       dq->l_end = ldq->r;
337       ldq->r->l = NULL;
338       ldq->r = NULL;
339     } else {
340       dq->l_end = dq->r_end = dq;
341     }
342     if (dq != ldq) {
343       free_pdeq_block (ldq);
344       pr = d_ (df_pdeq, 2);
345     }
346   }
347
348   VRFY (dq);
349   if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getl %p ==> %p)\n", dq, x);
350   return (void *)x;
351 }
352
353
354 bool
355 pdeq_contains (pdeq *dq, const void *x)
356 {
357   pdeq *q;
358
359   VRFY (dq);
360
361   q = dq->l_end;
362   do {
363     int p, ep;
364
365     p = q->p; ep = p + q->n;
366
367     if (ep > NDATA) {
368       do if (q->data[p] == x) goto found; while (++p < NDATA);
369       p = 0;
370       ep -= NDATA;
371     }
372
373     while (p < ep) if (q->data[p++] == x) goto found;
374
375     q = q->r;
376   } while (q);
377
378   if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 0)\n", dq, x);
379   return 0;
380
381 found:  /* The two gotos can be optimized away, if !DEBUG */
382   if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 1)\n", dq, x);
383   return 1;
384 }
385
386
387 void *
388 pdeq_search (pdeq *dq, cmp_fun cmp, const void *key)
389 {
390   pdeq *q;
391   int p;
392
393   VRFY (dq);
394
395   q = dq->l_end;
396   do {
397     int ep;
398
399     p = q->p; ep = p + q->n;
400
401     if (ep > NDATA) {
402       do if (!cmp (q->data[p], key)) goto found; while (++p < NDATA);
403       p = 0;
404       ep -= NDATA;
405     }
406
407     while (p < ep) if (!cmp (q->data[p++], key)) goto found;
408
409     q = q->r;
410   } while (q);
411
412   if (d_ (df_pdeq, 3)) printf ("(pdeq_search %p %p %p ==> 0)\n", dq, cmp, key);
413   return NULL;
414
415 found:  /* The two gotos can be optimized away, if !DEBUG */
416   if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p %p ==> %p)\n",
417                                dq, cmp, key, q->data[p]);
418   return (void *)q->data[p-1];
419 }
420
421
422 void **
423 pdeq_copyl (pdeq *dq, const void **dst)
424 {
425   pdeq *q;
426   const void **d = dst;
427
428   VRFY (dq);
429
430   q = dq->l_end;
431   while (q) {
432     int p, n;
433
434     p = q->p; n = q->n;
435
436     if (n + p > NDATA) {
437       int nn = NDATA - p;
438       memcpy (d, &q->data[p], nn * sizeof (void *)); d += nn;
439       p = 0; n -= nn;
440     }
441
442     memcpy (d, &q->data[p], n * sizeof (void *)); d += n;
443
444     q = q->r;
445   }
446
447   if (d_ (df_pdeq, 3)) printf ("(pdeq_copyl %p %p ==> %p)\n", dq, dst, d);
448   return (void **)dst;
449 }
450
451
452 void **
453 pdeq_copyr (pdeq *dq, const void **dst)
454 {
455   pdeq *q;
456   const void **d = dst;
457
458   VRFY (dq);
459
460   q = dq->r_end;
461   while (q) {
462     int p, i;
463
464     p = q->p; i = q->n + p - 1;
465     if (i >= NDATA) {
466       i -= NDATA;
467       do *d++ = q->data[i]; while (--i >= 0);
468       i = NDATA - 1;
469     }
470
471     do *d++ = q->data[i]; while (--i >= p);
472
473     q = q->l;
474   }
475
476   if (d_ (df_pdeq, 3)) printf ("(pdeq_copyr %p %p ==> %p)\n", dq, dst, d);
477   return (void **)dst;
478 }