fuzz_ball 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/fuzz_ball/duple_index/DupleIndex.c +276 -0
- data/ext/fuzz_ball/duple_index/DupleIndex.h +60 -0
- data/ext/fuzz_ball/duple_index/extconf.rb +5 -0
- data/ext/fuzz_ball/duple_index/utarray.h +226 -0
- data/ext/fuzz_ball/duple_index/uthash.h +904 -0
- data/ext/fuzz_ball/duple_index/utlist.h +522 -0
- data/ext/fuzz_ball/duple_index/utstring.h +148 -0
- data/ext/fuzz_ball/smith_waterman/SmithWaterman.c +211 -0
- data/ext/fuzz_ball/smith_waterman/SmithWaterman.h +19 -0
- data/ext/fuzz_ball/smith_waterman/extconf.rb +5 -0
- data/lib/fuzz_ball.rb +6 -0
- data/lib/fuzz_ball/searcher.rb +92 -0
- metadata +66 -0
@@ -0,0 +1,522 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007-2011, Troy D. Hanson http://uthash.sourceforge.net
|
3
|
+
All rights reserved.
|
4
|
+
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
* Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
12
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
13
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
14
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
15
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
16
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
17
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
18
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
19
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
20
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
21
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
|
+
*/
|
23
|
+
|
24
|
+
#ifndef UTLIST_H
|
25
|
+
#define UTLIST_H
|
26
|
+
|
27
|
+
#define UTLIST_VERSION 1.9.4
|
28
|
+
|
29
|
+
#include <assert.h>
|
30
|
+
|
31
|
+
/*
|
32
|
+
* This file contains macros to manipulate singly and doubly-linked lists.
|
33
|
+
*
|
34
|
+
* 1. LL_ macros: singly-linked lists.
|
35
|
+
* 2. DL_ macros: doubly-linked lists.
|
36
|
+
* 3. CDL_ macros: circular doubly-linked lists.
|
37
|
+
*
|
38
|
+
* To use singly-linked lists, your structure must have a "next" pointer.
|
39
|
+
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
|
40
|
+
* Either way, the pointer to the head of the list must be initialized to NULL.
|
41
|
+
*
|
42
|
+
* ----------------.EXAMPLE -------------------------
|
43
|
+
* struct item {
|
44
|
+
* int id;
|
45
|
+
* struct item *prev, *next;
|
46
|
+
* }
|
47
|
+
*
|
48
|
+
* struct item *list = NULL:
|
49
|
+
*
|
50
|
+
* int main() {
|
51
|
+
* struct item *item;
|
52
|
+
* ... allocate and populate item ...
|
53
|
+
* DL_APPEND(list, item);
|
54
|
+
* }
|
55
|
+
* --------------------------------------------------
|
56
|
+
*
|
57
|
+
* For doubly-linked lists, the append and delete macros are O(1)
|
58
|
+
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
|
59
|
+
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
|
60
|
+
*/
|
61
|
+
|
62
|
+
/* These macros use decltype or the earlier __typeof GNU extension.
|
63
|
+
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
64
|
+
when compiling c++ code), this code uses whatever method is needed
|
65
|
+
or, for VS2008 where neither is available, uses casting workarounds. */
|
66
|
+
#ifdef _MSC_VER /* MS compiler */
|
67
|
+
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
68
|
+
#define LDECLTYPE(x) decltype(x)
|
69
|
+
#else /* VS2008 or older (or VS2010 in C mode) */
|
70
|
+
#define NO_DECLTYPE
|
71
|
+
#define LDECLTYPE(x) char*
|
72
|
+
#endif
|
73
|
+
#else /* GNU, Sun and other compilers */
|
74
|
+
#define LDECLTYPE(x) __typeof(x)
|
75
|
+
#endif
|
76
|
+
|
77
|
+
/* for VS2008 we use some workarounds to get around the lack of decltype,
|
78
|
+
* namely, we always reassign our tmp variable to the list head if we need
|
79
|
+
* to dereference its prev/next pointers, and save/restore the real head.*/
|
80
|
+
#ifdef NO_DECLTYPE
|
81
|
+
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
|
82
|
+
#define _NEXT(elt,list) ((char*)((list)->next))
|
83
|
+
#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
|
84
|
+
#define _PREV(elt,list) ((char*)((list)->prev))
|
85
|
+
#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
|
86
|
+
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
|
87
|
+
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
|
88
|
+
#else
|
89
|
+
#define _SV(elt,list)
|
90
|
+
#define _NEXT(elt,list) ((elt)->next)
|
91
|
+
#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
|
92
|
+
#define _PREV(elt,list) ((elt)->prev)
|
93
|
+
#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
|
94
|
+
#define _RS(list)
|
95
|
+
#define _CASTASGN(a,b) (a)=(b)
|
96
|
+
#endif
|
97
|
+
|
98
|
+
/******************************************************************************
|
99
|
+
* The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
|
100
|
+
* Unwieldy variable names used here to avoid shadowing passed-in variables. *
|
101
|
+
*****************************************************************************/
|
102
|
+
#define LL_SORT(list, cmp) \
|
103
|
+
do { \
|
104
|
+
LDECLTYPE(list) _ls_p; \
|
105
|
+
LDECLTYPE(list) _ls_q; \
|
106
|
+
LDECLTYPE(list) _ls_e; \
|
107
|
+
LDECLTYPE(list) _ls_tail; \
|
108
|
+
LDECLTYPE(list) _ls_oldhead; \
|
109
|
+
LDECLTYPE(list) _tmp; \
|
110
|
+
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
111
|
+
if (list) { \
|
112
|
+
_ls_insize = 1; \
|
113
|
+
_ls_looping = 1; \
|
114
|
+
while (_ls_looping) { \
|
115
|
+
_CASTASGN(_ls_p,list); \
|
116
|
+
_CASTASGN(_ls_oldhead,list); \
|
117
|
+
list = NULL; \
|
118
|
+
_ls_tail = NULL; \
|
119
|
+
_ls_nmerges = 0; \
|
120
|
+
while (_ls_p) { \
|
121
|
+
_ls_nmerges++; \
|
122
|
+
_ls_q = _ls_p; \
|
123
|
+
_ls_psize = 0; \
|
124
|
+
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
125
|
+
_ls_psize++; \
|
126
|
+
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
|
127
|
+
if (!_ls_q) break; \
|
128
|
+
} \
|
129
|
+
_ls_qsize = _ls_insize; \
|
130
|
+
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
131
|
+
if (_ls_psize == 0) { \
|
132
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
133
|
+
} else if (_ls_qsize == 0 || !_ls_q) { \
|
134
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
135
|
+
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
136
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
137
|
+
} else { \
|
138
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
139
|
+
} \
|
140
|
+
if (_ls_tail) { \
|
141
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
142
|
+
} else { \
|
143
|
+
_CASTASGN(list,_ls_e); \
|
144
|
+
} \
|
145
|
+
_ls_tail = _ls_e; \
|
146
|
+
} \
|
147
|
+
_ls_p = _ls_q; \
|
148
|
+
} \
|
149
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
|
150
|
+
if (_ls_nmerges <= 1) { \
|
151
|
+
_ls_looping=0; \
|
152
|
+
} \
|
153
|
+
_ls_insize *= 2; \
|
154
|
+
} \
|
155
|
+
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
156
|
+
} while (0)
|
157
|
+
|
158
|
+
#define DL_SORT(list, cmp) \
|
159
|
+
do { \
|
160
|
+
LDECLTYPE(list) _ls_p; \
|
161
|
+
LDECLTYPE(list) _ls_q; \
|
162
|
+
LDECLTYPE(list) _ls_e; \
|
163
|
+
LDECLTYPE(list) _ls_tail; \
|
164
|
+
LDECLTYPE(list) _ls_oldhead; \
|
165
|
+
LDECLTYPE(list) _tmp; \
|
166
|
+
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
167
|
+
if (list) { \
|
168
|
+
_ls_insize = 1; \
|
169
|
+
_ls_looping = 1; \
|
170
|
+
while (_ls_looping) { \
|
171
|
+
_CASTASGN(_ls_p,list); \
|
172
|
+
_CASTASGN(_ls_oldhead,list); \
|
173
|
+
list = NULL; \
|
174
|
+
_ls_tail = NULL; \
|
175
|
+
_ls_nmerges = 0; \
|
176
|
+
while (_ls_p) { \
|
177
|
+
_ls_nmerges++; \
|
178
|
+
_ls_q = _ls_p; \
|
179
|
+
_ls_psize = 0; \
|
180
|
+
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
181
|
+
_ls_psize++; \
|
182
|
+
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
|
183
|
+
if (!_ls_q) break; \
|
184
|
+
} \
|
185
|
+
_ls_qsize = _ls_insize; \
|
186
|
+
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
187
|
+
if (_ls_psize == 0) { \
|
188
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
189
|
+
} else if (_ls_qsize == 0 || !_ls_q) { \
|
190
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
191
|
+
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
192
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
193
|
+
} else { \
|
194
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
195
|
+
} \
|
196
|
+
if (_ls_tail) { \
|
197
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
198
|
+
} else { \
|
199
|
+
_CASTASGN(list,_ls_e); \
|
200
|
+
} \
|
201
|
+
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
|
202
|
+
_ls_tail = _ls_e; \
|
203
|
+
} \
|
204
|
+
_ls_p = _ls_q; \
|
205
|
+
} \
|
206
|
+
_CASTASGN(list->prev, _ls_tail); \
|
207
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
|
208
|
+
if (_ls_nmerges <= 1) { \
|
209
|
+
_ls_looping=0; \
|
210
|
+
} \
|
211
|
+
_ls_insize *= 2; \
|
212
|
+
} \
|
213
|
+
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
214
|
+
} while (0)
|
215
|
+
|
216
|
+
#define CDL_SORT(list, cmp) \
|
217
|
+
do { \
|
218
|
+
LDECLTYPE(list) _ls_p; \
|
219
|
+
LDECLTYPE(list) _ls_q; \
|
220
|
+
LDECLTYPE(list) _ls_e; \
|
221
|
+
LDECLTYPE(list) _ls_tail; \
|
222
|
+
LDECLTYPE(list) _ls_oldhead; \
|
223
|
+
LDECLTYPE(list) _tmp; \
|
224
|
+
LDECLTYPE(list) _tmp2; \
|
225
|
+
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
226
|
+
if (list) { \
|
227
|
+
_ls_insize = 1; \
|
228
|
+
_ls_looping = 1; \
|
229
|
+
while (_ls_looping) { \
|
230
|
+
_CASTASGN(_ls_p,list); \
|
231
|
+
_CASTASGN(_ls_oldhead,list); \
|
232
|
+
list = NULL; \
|
233
|
+
_ls_tail = NULL; \
|
234
|
+
_ls_nmerges = 0; \
|
235
|
+
while (_ls_p) { \
|
236
|
+
_ls_nmerges++; \
|
237
|
+
_ls_q = _ls_p; \
|
238
|
+
_ls_psize = 0; \
|
239
|
+
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
240
|
+
_ls_psize++; \
|
241
|
+
_SV(_ls_q,list); \
|
242
|
+
if (_NEXT(_ls_q,list) == _ls_oldhead) { \
|
243
|
+
_ls_q = NULL; \
|
244
|
+
} else { \
|
245
|
+
_ls_q = _NEXT(_ls_q,list); \
|
246
|
+
} \
|
247
|
+
_RS(list); \
|
248
|
+
if (!_ls_q) break; \
|
249
|
+
} \
|
250
|
+
_ls_qsize = _ls_insize; \
|
251
|
+
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
252
|
+
if (_ls_psize == 0) { \
|
253
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
254
|
+
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
255
|
+
} else if (_ls_qsize == 0 || !_ls_q) { \
|
256
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
257
|
+
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
258
|
+
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
259
|
+
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
|
260
|
+
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
261
|
+
} else { \
|
262
|
+
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
|
263
|
+
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
264
|
+
} \
|
265
|
+
if (_ls_tail) { \
|
266
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
|
267
|
+
} else { \
|
268
|
+
_CASTASGN(list,_ls_e); \
|
269
|
+
} \
|
270
|
+
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
|
271
|
+
_ls_tail = _ls_e; \
|
272
|
+
} \
|
273
|
+
_ls_p = _ls_q; \
|
274
|
+
} \
|
275
|
+
_CASTASGN(list->prev,_ls_tail); \
|
276
|
+
_CASTASGN(_tmp2,list); \
|
277
|
+
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
|
278
|
+
if (_ls_nmerges <= 1) { \
|
279
|
+
_ls_looping=0; \
|
280
|
+
} \
|
281
|
+
_ls_insize *= 2; \
|
282
|
+
} \
|
283
|
+
} else _tmp=NULL; /* quiet gcc unused variable warning */ \
|
284
|
+
} while (0)
|
285
|
+
|
286
|
+
/******************************************************************************
|
287
|
+
* singly linked list macros (non-circular) *
|
288
|
+
*****************************************************************************/
|
289
|
+
#define LL_PREPEND(head,add) \
|
290
|
+
do { \
|
291
|
+
(add)->next = head; \
|
292
|
+
head = add; \
|
293
|
+
} while (0)
|
294
|
+
|
295
|
+
#define LL_CONCAT(head1,head2) \
|
296
|
+
do { \
|
297
|
+
LDECLTYPE(head1) _tmp; \
|
298
|
+
if (head1) { \
|
299
|
+
_tmp = head1; \
|
300
|
+
while (_tmp->next) { _tmp = _tmp->next; } \
|
301
|
+
_tmp->next=(head2); \
|
302
|
+
} else { \
|
303
|
+
(head1)=(head2); \
|
304
|
+
} \
|
305
|
+
} while (0)
|
306
|
+
|
307
|
+
#define LL_APPEND(head,add) \
|
308
|
+
do { \
|
309
|
+
LDECLTYPE(head) _tmp; \
|
310
|
+
(add)->next=NULL; \
|
311
|
+
if (head) { \
|
312
|
+
_tmp = head; \
|
313
|
+
while (_tmp->next) { _tmp = _tmp->next; } \
|
314
|
+
_tmp->next=(add); \
|
315
|
+
} else { \
|
316
|
+
(head)=(add); \
|
317
|
+
} \
|
318
|
+
} while (0)
|
319
|
+
|
320
|
+
#define LL_DELETE(head,del) \
|
321
|
+
do { \
|
322
|
+
LDECLTYPE(head) _tmp; \
|
323
|
+
if ((head) == (del)) { \
|
324
|
+
(head)=(head)->next; \
|
325
|
+
} else { \
|
326
|
+
_tmp = head; \
|
327
|
+
while (_tmp->next && (_tmp->next != (del))) { \
|
328
|
+
_tmp = _tmp->next; \
|
329
|
+
} \
|
330
|
+
if (_tmp->next) { \
|
331
|
+
_tmp->next = ((del)->next); \
|
332
|
+
} \
|
333
|
+
} \
|
334
|
+
} while (0)
|
335
|
+
|
336
|
+
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
|
337
|
+
#define LL_APPEND_VS2008(head,add) \
|
338
|
+
do { \
|
339
|
+
if (head) { \
|
340
|
+
(add)->next = head; /* use add->next as a temp variable */ \
|
341
|
+
while ((add)->next->next) { (add)->next = (add)->next->next; } \
|
342
|
+
(add)->next->next=(add); \
|
343
|
+
} else { \
|
344
|
+
(head)=(add); \
|
345
|
+
} \
|
346
|
+
(add)->next=NULL; \
|
347
|
+
} while (0)
|
348
|
+
|
349
|
+
#define LL_DELETE_VS2008(head,del) \
|
350
|
+
do { \
|
351
|
+
if ((head) == (del)) { \
|
352
|
+
(head)=(head)->next; \
|
353
|
+
} else { \
|
354
|
+
char *_tmp = (char*)(head); \
|
355
|
+
while (head->next && (head->next != (del))) { \
|
356
|
+
head = head->next; \
|
357
|
+
} \
|
358
|
+
if (head->next) { \
|
359
|
+
head->next = ((del)->next); \
|
360
|
+
} \
|
361
|
+
{ \
|
362
|
+
char **_head_alias = (char**)&(head); \
|
363
|
+
*_head_alias = _tmp; \
|
364
|
+
} \
|
365
|
+
} \
|
366
|
+
} while (0)
|
367
|
+
#ifdef NO_DECLTYPE
|
368
|
+
#undef LL_APPEND
|
369
|
+
#define LL_APPEND LL_APPEND_VS2008
|
370
|
+
#undef LL_DELETE
|
371
|
+
#define LL_DELETE LL_DELETE_VS2008
|
372
|
+
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
|
373
|
+
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
|
374
|
+
#endif
|
375
|
+
/* end VS2008 replacements */
|
376
|
+
|
377
|
+
#define LL_FOREACH(head,el) \
|
378
|
+
for(el=head;el;el=el->next)
|
379
|
+
|
380
|
+
#define LL_FOREACH_SAFE(head,el,tmp) \
|
381
|
+
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
382
|
+
|
383
|
+
#define LL_SEARCH_SCALAR(head,out,field,val) \
|
384
|
+
do { \
|
385
|
+
LL_FOREACH(head,out) { \
|
386
|
+
if ((out)->field == (val)) break; \
|
387
|
+
} \
|
388
|
+
} while(0)
|
389
|
+
|
390
|
+
#define LL_SEARCH(head,out,elt,cmp) \
|
391
|
+
do { \
|
392
|
+
LL_FOREACH(head,out) { \
|
393
|
+
if ((cmp(out,elt))==0) break; \
|
394
|
+
} \
|
395
|
+
} while(0)
|
396
|
+
|
397
|
+
/******************************************************************************
|
398
|
+
* doubly linked list macros (non-circular) *
|
399
|
+
*****************************************************************************/
|
400
|
+
#define DL_PREPEND(head,add) \
|
401
|
+
do { \
|
402
|
+
(add)->next = head; \
|
403
|
+
if (head) { \
|
404
|
+
(add)->prev = (head)->prev; \
|
405
|
+
(head)->prev = (add); \
|
406
|
+
} else { \
|
407
|
+
(add)->prev = (add); \
|
408
|
+
} \
|
409
|
+
(head) = (add); \
|
410
|
+
} while (0)
|
411
|
+
|
412
|
+
#define DL_APPEND(head,add) \
|
413
|
+
do { \
|
414
|
+
if (head) { \
|
415
|
+
(add)->prev = (head)->prev; \
|
416
|
+
(head)->prev->next = (add); \
|
417
|
+
(head)->prev = (add); \
|
418
|
+
(add)->next = NULL; \
|
419
|
+
} else { \
|
420
|
+
(head)=(add); \
|
421
|
+
(head)->prev = (head); \
|
422
|
+
(head)->next = NULL; \
|
423
|
+
} \
|
424
|
+
} while (0);
|
425
|
+
|
426
|
+
#define DL_CONCAT(head1,head2) \
|
427
|
+
do { \
|
428
|
+
LDECLTYPE(head1) _tmp; \
|
429
|
+
if (head2) { \
|
430
|
+
if (head1) { \
|
431
|
+
_tmp = (head2)->prev; \
|
432
|
+
(head2)->prev = (head1)->prev; \
|
433
|
+
(head1)->prev->next = (head2); \
|
434
|
+
(head1)->prev = _tmp; \
|
435
|
+
} else { \
|
436
|
+
(head1)=(head2); \
|
437
|
+
} \
|
438
|
+
} \
|
439
|
+
} while (0);
|
440
|
+
|
441
|
+
#define DL_DELETE(head,del) \
|
442
|
+
do { \
|
443
|
+
assert((del)->prev != NULL); \
|
444
|
+
if ((del)->prev == (del)) { \
|
445
|
+
(head)=NULL; \
|
446
|
+
} else if ((del)==(head)) { \
|
447
|
+
(del)->next->prev = (del)->prev; \
|
448
|
+
(head) = (del)->next; \
|
449
|
+
} else { \
|
450
|
+
(del)->prev->next = (del)->next; \
|
451
|
+
if ((del)->next) { \
|
452
|
+
(del)->next->prev = (del)->prev; \
|
453
|
+
} else { \
|
454
|
+
(head)->prev = (del)->prev; \
|
455
|
+
} \
|
456
|
+
} \
|
457
|
+
} while (0);
|
458
|
+
|
459
|
+
|
460
|
+
#define DL_FOREACH(head,el) \
|
461
|
+
for(el=head;el;el=el->next)
|
462
|
+
|
463
|
+
/* this version is safe for deleting the elements during iteration */
|
464
|
+
#define DL_FOREACH_SAFE(head,el,tmp) \
|
465
|
+
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
466
|
+
|
467
|
+
/* these are identical to their singly-linked list counterparts */
|
468
|
+
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
|
469
|
+
#define DL_SEARCH LL_SEARCH
|
470
|
+
|
471
|
+
/******************************************************************************
|
472
|
+
* circular doubly linked list macros *
|
473
|
+
*****************************************************************************/
|
474
|
+
#define CDL_PREPEND(head,add) \
|
475
|
+
do { \
|
476
|
+
if (head) { \
|
477
|
+
(add)->prev = (head)->prev; \
|
478
|
+
(add)->next = (head); \
|
479
|
+
(head)->prev = (add); \
|
480
|
+
(add)->prev->next = (add); \
|
481
|
+
} else { \
|
482
|
+
(add)->prev = (add); \
|
483
|
+
(add)->next = (add); \
|
484
|
+
} \
|
485
|
+
(head)=(add); \
|
486
|
+
} while (0)
|
487
|
+
|
488
|
+
#define CDL_DELETE(head,del) \
|
489
|
+
do { \
|
490
|
+
if ( ((head)==(del)) && ((head)->next == (head))) { \
|
491
|
+
(head) = 0L; \
|
492
|
+
} else { \
|
493
|
+
(del)->next->prev = (del)->prev; \
|
494
|
+
(del)->prev->next = (del)->next; \
|
495
|
+
if ((del) == (head)) (head)=(del)->next; \
|
496
|
+
} \
|
497
|
+
} while (0);
|
498
|
+
|
499
|
+
#define CDL_FOREACH(head,el) \
|
500
|
+
for(el=head;el;el=(el->next==head ? 0L : el->next))
|
501
|
+
|
502
|
+
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
|
503
|
+
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
|
504
|
+
(el) && ((tmp2)=(el)->next, 1); \
|
505
|
+
((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
|
506
|
+
|
507
|
+
#define CDL_SEARCH_SCALAR(head,out,field,val) \
|
508
|
+
do { \
|
509
|
+
CDL_FOREACH(head,out) { \
|
510
|
+
if ((out)->field == (val)) break; \
|
511
|
+
} \
|
512
|
+
} while(0)
|
513
|
+
|
514
|
+
#define CDL_SEARCH(head,out,elt,cmp) \
|
515
|
+
do { \
|
516
|
+
CDL_FOREACH(head,out) { \
|
517
|
+
if ((cmp(out,elt))==0) break; \
|
518
|
+
} \
|
519
|
+
} while(0)
|
520
|
+
|
521
|
+
#endif /* UTLIST_H */
|
522
|
+
|