]> Git Repo - VerusCoin.git/blob - src/utlist.h
test
[VerusCoin.git] / src / utlist.h
1 /*
2  Copyright (c) 2007-2014, Troy D. Hanson   http://troydhanson.github.com/uthash/
3  All rights reserved.
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright
7  notice, this list of conditions and the following disclaimer.
8  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
9  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
10  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
12  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
13  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
16  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
18  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19  */
20  
21 #ifndef UTLIST_H
22 #define UTLIST_H
23
24 #define UTLIST_VERSION 1.9.9
25
26 #include <assert.h>
27
28 /*
29  * This file contains macros to manipulate singly and doubly-linked lists.
30  *
31  * 1. LL_ macros:  singly-linked lists.
32  * 2. DL_ macros:  doubly-linked lists.
33  * 3. CDL_ macros: circular doubly-linked lists.
34  *
35  * To use singly-linked lists, your structure must have a "next" pointer.
36  * To use doubly-linked lists, your structure must "prev" and "next" pointers.
37  * Either way, the pointer to the head of the list must be initialized to NULL.
38  *
39  * ----------------.EXAMPLE -------------------------
40  * struct item {
41  *      int id;
42  *      struct item *prev, *next;
43  * }
44  *
45  * struct item *list = NULL:
46  *
47  * int main() {
48  *      struct item *item;
49  *      ... allocate and populate item ...
50  *      DL_APPEND(list, item);
51  * }
52  * --------------------------------------------------
53  *
54  * For doubly-linked lists, the append and delete macros are O(1)
55  * For singly-linked lists, append and delete are O(n) but prepend is O(1)
56  * The sort macro is O(n log(n)) for all types of single/double/circular lists.
57  */
58
59 /* These macros use decltype or the earlier __typeof GNU extension.
60  As decltype is only available in newer compilers (VS2010 or gcc 4.3+
61  when compiling c++ code), this code uses whatever method is needed
62  or, for VS2008 where neither is available, uses casting workarounds. */
63 #ifdef _MSC_VER            /* MS compiler */
64 #if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
65 #define LDECLTYPE(x) decltype(x)
66 #else                     /* VS2008 or older (or VS2010 in C mode) */
67 #define NO_DECLTYPE
68 #define LDECLTYPE(x) char*
69 #endif
70 #elif defined(__ICCARM__)
71 #define NO_DECLTYPE
72 #define LDECLTYPE(x) char*
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,next) ((char*)((list)->next))
83 #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
84 /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
85 #define _PREVASGN(elt,list,to,prev) { 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,next) ((elt)->next)
91 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
92 /* #define _PREV(elt,list,prev) ((elt)->prev) */
93 #define _PREVASGN(elt,list,to,prev) ((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 LL_SORT2(list, cmp, next)
104
105 #define LL_SORT2(list, cmp, next)                                                              \
106 do {                                                                                           \
107 LDECLTYPE(list) _ls_p;                                                                       \
108 LDECLTYPE(list) _ls_q;                                                                       \
109 LDECLTYPE(list) _ls_e;                                                                       \
110 LDECLTYPE(list) _ls_tail;                                                                    \
111 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
112 if (list) {                                                                                  \
113 _ls_insize = 1;                                                                            \
114 _ls_looping = 1;                                                                           \
115 while (_ls_looping) {                                                                      \
116 _CASTASGN(_ls_p,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,next); _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 =                                            \
133 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
134 } else if (_ls_qsize == 0 || !_ls_q) {                                               \
135 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
136 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
137 } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
138 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
139 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
140 } else {                                                                             \
141 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
142 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
143 }                                                                                    \
144 if (_ls_tail) {                                                                      \
145 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
146 } else {                                                                             \
147 _CASTASGN(list,_ls_e);                                                             \
148 }                                                                                    \
149 _ls_tail = _ls_e;                                                                    \
150 }                                                                                      \
151 _ls_p = _ls_q;                                                                         \
152 }                                                                                        \
153 if (_ls_tail) {                                                                          \
154 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                     \
155 }                                                                                        \
156 if (_ls_nmerges <= 1) {                                                                  \
157 _ls_looping=0;                                                                         \
158 }                                                                                        \
159 _ls_insize *= 2;                                                                         \
160 }                                                                                          \
161 }                                                                                            \
162 } while (0)
163
164
165 #define DL_SORT(list, cmp)                                                                     \
166 DL_SORT2(list, cmp, prev, next)
167
168 #define DL_SORT2(list, cmp, prev, next)                                                        \
169 do {                                                                                           \
170 LDECLTYPE(list) _ls_p;                                                                       \
171 LDECLTYPE(list) _ls_q;                                                                       \
172 LDECLTYPE(list) _ls_e;                                                                       \
173 LDECLTYPE(list) _ls_tail;                                                                    \
174 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
175 if (list) {                                                                                  \
176 _ls_insize = 1;                                                                            \
177 _ls_looping = 1;                                                                           \
178 while (_ls_looping) {                                                                      \
179 _CASTASGN(_ls_p,list);                                                                   \
180 list = NULL;                                                                             \
181 _ls_tail = NULL;                                                                         \
182 _ls_nmerges = 0;                                                                         \
183 while (_ls_p) {                                                                          \
184 _ls_nmerges++;                                                                         \
185 _ls_q = _ls_p;                                                                         \
186 _ls_psize = 0;                                                                         \
187 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
188 _ls_psize++;                                                                         \
189 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
190 if (!_ls_q) break;                                                                   \
191 }                                                                                      \
192 _ls_qsize = _ls_insize;                                                                \
193 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
194 if (_ls_psize == 0) {                                                                \
195 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
196 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
197 } else if (_ls_qsize == 0 || !_ls_q) {                                               \
198 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
199 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
200 } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
201 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
202 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
203 } else {                                                                             \
204 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
205 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
206 }                                                                                    \
207 if (_ls_tail) {                                                                      \
208 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
209 } else {                                                                             \
210 _CASTASGN(list,_ls_e);                                                             \
211 }                                                                                    \
212 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
213 _ls_tail = _ls_e;                                                                    \
214 }                                                                                      \
215 _ls_p = _ls_q;                                                                         \
216 }                                                                                        \
217 _CASTASGN(list->prev, _ls_tail);                                                         \
218 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                       \
219 if (_ls_nmerges <= 1) {                                                                  \
220 _ls_looping=0;                                                                         \
221 }                                                                                        \
222 _ls_insize *= 2;                                                                         \
223 }                                                                                          \
224 }                                                                                            \
225 } while (0)
226
227 #define CDL_SORT(list, cmp)                                                                    \
228 CDL_SORT2(list, cmp, prev, next)
229
230 #define CDL_SORT2(list, cmp, prev, next)                                                       \
231 do {                                                                                           \
232 LDECLTYPE(list) _ls_p;                                                                       \
233 LDECLTYPE(list) _ls_q;                                                                       \
234 LDECLTYPE(list) _ls_e;                                                                       \
235 LDECLTYPE(list) _ls_tail;                                                                    \
236 LDECLTYPE(list) _ls_oldhead;                                                                 \
237 LDECLTYPE(list) _tmp;                                                                        \
238 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
239 if (list) {                                                                                  \
240 _ls_insize = 1;                                                                            \
241 _ls_looping = 1;                                                                           \
242 while (_ls_looping) {                                                                      \
243 _CASTASGN(_ls_p,list);                                                                   \
244 _CASTASGN(_ls_oldhead,list);                                                             \
245 list = NULL;                                                                             \
246 _ls_tail = NULL;                                                                         \
247 _ls_nmerges = 0;                                                                         \
248 while (_ls_p) {                                                                          \
249 _ls_nmerges++;                                                                         \
250 _ls_q = _ls_p;                                                                         \
251 _ls_psize = 0;                                                                         \
252 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
253 _ls_psize++;                                                                         \
254 _SV(_ls_q,list);                                                                     \
255 if (_NEXT(_ls_q,list,next) == _ls_oldhead) {                                         \
256 _ls_q = NULL;                                                                      \
257 } else {                                                                             \
258 _ls_q = _NEXT(_ls_q,list,next);                                                    \
259 }                                                                                    \
260 _RS(list);                                                                           \
261 if (!_ls_q) break;                                                                   \
262 }                                                                                      \
263 _ls_qsize = _ls_insize;                                                                \
264 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
265 if (_ls_psize == 0) {                                                                \
266 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
267 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
268 if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
269 } else if (_ls_qsize == 0 || !_ls_q) {                                               \
270 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
271 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
272 if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
273 } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
274 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
275 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
276 if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
277 } else {                                                                             \
278 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
279 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
280 if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
281 }                                                                                    \
282 if (_ls_tail) {                                                                      \
283 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
284 } else {                                                                             \
285 _CASTASGN(list,_ls_e);                                                             \
286 }                                                                                    \
287 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
288 _ls_tail = _ls_e;                                                                    \
289 }                                                                                      \
290 _ls_p = _ls_q;                                                                         \
291 }                                                                                        \
292 _CASTASGN(list->prev,_ls_tail);                                                          \
293 _CASTASGN(_tmp,list);                                                                    \
294 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list);                       \
295 if (_ls_nmerges <= 1) {                                                                  \
296 _ls_looping=0;                                                                         \
297 }                                                                                        \
298 _ls_insize *= 2;                                                                         \
299 }                                                                                          \
300 }                                                                                            \
301 } while (0)
302
303 /******************************************************************************
304  * singly linked list macros (non-circular)                                   *
305  *****************************************************************************/
306 #define LL_PREPEND(head,add)                                                                   \
307 LL_PREPEND2(head,add,next)
308
309 #define LL_PREPEND2(head,add,next)                                                             \
310 do {                                                                                           \
311 (add)->next = head;                                                                          \
312 head = add;                                                                                  \
313 } while (0)
314
315 #define LL_CONCAT(head1,head2)                                                                 \
316 LL_CONCAT2(head1,head2,next)
317
318 #define LL_CONCAT2(head1,head2,next)                                                           \
319 do {                                                                                           \
320 LDECLTYPE(head1) _tmp;                                                                       \
321 if (head1) {                                                                                 \
322 _tmp = head1;                                                                              \
323 while (_tmp->next) { _tmp = _tmp->next; }                                                  \
324 _tmp->next=(head2);                                                                        \
325 } else {                                                                                     \
326 (head1)=(head2);                                                                           \
327 }                                                                                            \
328 } while (0)
329
330 #define LL_APPEND(head,add)                                                                    \
331 LL_APPEND2(head,add,next)
332
333 #define LL_APPEND2(head,add,next)                                                              \
334 do {                                                                                           \
335 LDECLTYPE(head) _tmp;                                                                        \
336 (add)->next=NULL;                                                                            \
337 if (head) {                                                                                  \
338 _tmp = head;                                                                               \
339 while (_tmp->next) { _tmp = _tmp->next; }                                                  \
340 _tmp->next=(add);                                                                          \
341 } else {                                                                                     \
342 (head)=(add);                                                                              \
343 }                                                                                            \
344 } while (0)
345
346 #define LL_DELETE(head,del)                                                                    \
347 LL_DELETE2(head,del,next)
348
349 #define LL_DELETE2(head,del,next)                                                              \
350 do {                                                                                           \
351 LDECLTYPE(head) _tmp;                                                                        \
352 if ((head) == (del)) {                                                                       \
353 (head)=(head)->next;                                                                       \
354 } else {                                                                                     \
355 _tmp = head;                                                                               \
356 while (_tmp->next && (_tmp->next != (del))) {                                              \
357 _tmp = _tmp->next;                                                                       \
358 }                                                                                          \
359 if (_tmp->next) {                                                                          \
360 _tmp->next = ((del)->next);                                                              \
361 }                                                                                          \
362 }                                                                                            \
363 } while (0)
364
365 /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
366 #define LL_APPEND_VS2008(head,add)                                                             \
367 LL_APPEND2_VS2008(head,add,next)
368
369 #define LL_APPEND2_VS2008(head,add,next)                                                       \
370 do {                                                                                           \
371 if (head) {                                                                                  \
372 (add)->next = head;     /* use add->next as a temp variable */                             \
373 while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
374 (add)->next->next=(add);                                                                   \
375 } else {                                                                                     \
376 (head)=(add);                                                                              \
377 }                                                                                            \
378 (add)->next=NULL;                                                                            \
379 } while (0)
380
381 #define LL_DELETE_VS2008(head,del)                                                             \
382 LL_DELETE2_VS2008(head,del,next)
383
384 #define LL_DELETE2_VS2008(head,del,next)                                                       \
385 do {                                                                                           \
386 if ((head) == (del)) {                                                                       \
387 (head)=(head)->next;                                                                       \
388 } else {                                                                                     \
389 char *_tmp = (char*)(head);                                                                \
390 while ((head)->next && ((head)->next != (del))) {                                          \
391 head = (head)->next;                                                                     \
392 }                                                                                          \
393 if ((head)->next) {                                                                        \
394 (head)->next = ((del)->next);                                                            \
395 }                                                                                          \
396 {                                                                                          \
397 char **_head_alias = (char**)&(head);                                                    \
398 *_head_alias = _tmp;                                                                     \
399 }                                                                                          \
400 }                                                                                            \
401 } while (0)
402 #ifdef NO_DECLTYPE
403 #undef LL_APPEND
404 #define LL_APPEND LL_APPEND_VS2008
405 #undef LL_DELETE
406 #define LL_DELETE LL_DELETE_VS2008
407 #undef LL_DELETE2
408 #define LL_DELETE2 LL_DELETE2_VS2008
409 #undef LL_APPEND2
410 #define LL_APPEND2 LL_APPEND2_VS2008
411 #undef LL_CONCAT /* no LL_CONCAT_VS2008 */
412 #undef DL_CONCAT /* no DL_CONCAT_VS2008 */
413 #endif
414 /* end VS2008 replacements */
415
416 #define LL_COUNT(head,el,counter)                                                              \
417 LL_COUNT2(head,el,counter,next)                                                            \
418
419 #define LL_COUNT2(head,el,counter,next)                                                        \
420 {                                                                                              \
421 counter = 0;                                                                               \
422 LL_FOREACH2(head,el,next){ ++counter; }                                                    \
423 }
424
425 #define LL_FOREACH(head,el)                                                                    \
426 LL_FOREACH2(head,el,next)
427
428 #define LL_FOREACH2(head,el,next)                                                              \
429 for(el=head;el;el=(el)->next)
430
431 #define LL_FOREACH_SAFE(head,el,tmp)                                                           \
432 LL_FOREACH_SAFE2(head,el,tmp,next)
433
434 #define LL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
435 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
436
437 #define LL_SEARCH_SCALAR(head,out,field,val)                                                   \
438 LL_SEARCH_SCALAR2(head,out,field,val,next)
439
440 #define LL_SEARCH_SCALAR2(head,out,field,val,next)                                             \
441 do {                                                                                           \
442 LL_FOREACH2(head,out,next) {                                                               \
443 if ((out)->field == (val)) break;                                                        \
444 }                                                                                          \
445 } while(0)
446
447 #define LL_SEARCH(head,out,elt,cmp)                                                            \
448 LL_SEARCH2(head,out,elt,cmp,next)
449
450 #define LL_SEARCH2(head,out,elt,cmp,next)                                                      \
451 do {                                                                                           \
452 LL_FOREACH2(head,out,next) {                                                               \
453 if ((cmp(out,elt))==0) break;                                                            \
454 }                                                                                          \
455 } while(0)
456
457 #define LL_REPLACE_ELEM(head, el, add)                                                         \
458 do {                                                                                           \
459 LDECLTYPE(head) _tmp;                                                                         \
460 assert(head != NULL);                                                                         \
461 assert(el != NULL);                                                                           \
462 assert(add != NULL);                                                                          \
463 (add)->next = (el)->next;                                                                     \
464 if ((head) == (el)) {                                                                         \
465 (head) = (add);                                                                              \
466 } else {                                                                                      \
467 _tmp = head;                                                                                 \
468 while (_tmp->next && (_tmp->next != (el))) {                                                 \
469 _tmp = _tmp->next;                                                                          \
470 }                                                                                            \
471 if (_tmp->next) {                                                                            \
472 _tmp->next = (add);                                                                        \
473 }                                                                                            \
474 }                                                                                             \
475 } while (0)
476
477 #define LL_PREPEND_ELEM(head, el, add)                                                         \
478 do {                                                                                           \
479 LDECLTYPE(head) _tmp;                                                                         \
480 assert(head != NULL);                                                                         \
481 assert(el != NULL);                                                                           \
482 assert(add != NULL);                                                                          \
483 (add)->next = (el);                                                                           \
484 if ((head) == (el)) {                                                                         \
485 (head) = (add);                                                                              \
486 } else {                                                                                      \
487 _tmp = head;                                                                                 \
488 while (_tmp->next && (_tmp->next != (el))) {                                                 \
489 _tmp = _tmp->next;                                                                          \
490 }                                                                                            \
491 if (_tmp->next) {                                                                            \
492 _tmp->next = (add);                                                                        \
493 }                                                                                            \
494 }                                                                                             \
495 } while (0)                                                                                    \
496
497
498 /******************************************************************************
499  * doubly linked list macros (non-circular)                                   *
500  *****************************************************************************/
501 #define DL_PREPEND(head,add)                                                                   \
502 DL_PREPEND2(head,add,prev,next)
503
504 #define DL_PREPEND2(head,add,prev,next)                                                        \
505 do {                                                                                           \
506 (add)->next = head;                                                                           \
507 if (head) {                                                                                   \
508 (add)->prev = (head)->prev;                                                                 \
509 (head)->prev = (add);                                                                       \
510 } else {                                                                                      \
511 (add)->prev = (add);                                                                        \
512 }                                                                                             \
513 (head) = (add);                                                                               \
514 } while (0)
515
516 #define DL_APPEND(head,add)                                                                    \
517 DL_APPEND2(head,add,prev,next)
518
519 #define DL_APPEND2(head,add,prev,next)                                                         \
520 do {                                                                                           \
521 if (head) {                                                                                  \
522 (add)->prev = (head)->prev;                                                              \
523 (head)->prev->next = (add);                                                              \
524 (head)->prev = (add);                                                                    \
525 (add)->next = NULL;                                                                      \
526 } else {                                                                                     \
527 (head)=(add);                                                                            \
528 (head)->prev = (head);                                                                   \
529 (head)->next = NULL;                                                                     \
530 }                                                                                            \
531 } while (0)
532
533 #define DL_CONCAT(head1,head2)                                                                 \
534 DL_CONCAT2(head1,head2,prev,next)
535
536 #define DL_CONCAT2(head1,head2,prev,next)                                                      \
537 do {                                                                                           \
538 LDECLTYPE(head1) _tmp;                                                                       \
539 if (head2) {                                                                                 \
540 if (head1) {                                                                               \
541 _tmp = (head2)->prev;                                                                  \
542 (head2)->prev = (head1)->prev;                                                         \
543 (head1)->prev->next = (head2);                                                         \
544 (head1)->prev = _tmp;                                                                  \
545 } else {                                                                                   \
546 (head1)=(head2);                                                                       \
547 }                                                                                          \
548 }                                                                                            \
549 } while (0)
550
551 #define DL_DELETE(head,del)                                                                    \
552 DL_DELETE2(head,del,prev,next)
553
554 #define DL_DELETE2(head,del,prev,next)                                                         \
555 do {                                                                                           \
556 assert((del)->prev != NULL);                                                                 \
557 if ((del)->prev == (del)) {                                                                  \
558 (head)=NULL;                                                                             \
559 } else if ((del)==(head)) {                                                                  \
560 (del)->next->prev = (del)->prev;                                                         \
561 (head) = (del)->next;                                                                    \
562 } else {                                                                                     \
563 (del)->prev->next = (del)->next;                                                         \
564 if ((del)->next) {                                                                       \
565 (del)->next->prev = (del)->prev;                                                     \
566 } else {                                                                                 \
567 (head)->prev = (del)->prev;                                                          \
568 }                                                                                        \
569 }                                                                                            \
570 } while (0)
571
572 #define DL_COUNT(head,el,counter)                                                              \
573 DL_COUNT2(head,el,counter,next)                                                            \
574
575 #define DL_COUNT2(head,el,counter,next)                                                        \
576 {                                                                                              \
577 counter = 0;                                                                               \
578 DL_FOREACH2(head,el,next){ ++counter; }                                                    \
579 }
580
581 #define DL_FOREACH(head,el)                                                                    \
582 DL_FOREACH2(head,el,next)
583
584 #define DL_FOREACH2(head,el,next)                                                              \
585 for(el=head;el;el=(el)->next)
586
587 /* this version is safe for deleting the elements during iteration */
588 #define DL_FOREACH_SAFE(head,el,tmp)                                                           \
589 DL_FOREACH_SAFE2(head,el,tmp,next)
590
591 #define DL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
592 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
593
594 /* these are identical to their singly-linked list counterparts */
595 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
596 #define DL_SEARCH LL_SEARCH
597 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
598 #define DL_SEARCH2 LL_SEARCH2
599
600 #define DL_REPLACE_ELEM(head, el, add)                                                         \
601 do {                                                                                           \
602 assert(head != NULL);                                                                         \
603 assert(el != NULL);                                                                           \
604 assert(add != NULL);                                                                          \
605 if ((head) == (el)) {                                                                         \
606 (head) = (add);                                                                              \
607 (add)->next = (el)->next;                                                                    \
608 if ((el)->next == NULL) {                                                                    \
609 (add)->prev = (add);                                                                        \
610 } else {                                                                                     \
611 (add)->prev = (el)->prev;                                                                   \
612 (add)->next->prev = (add);                                                                  \
613 }                                                                                            \
614 } else {                                                                                      \
615 (add)->next = (el)->next;                                                                    \
616 (add)->prev = (el)->prev;                                                                    \
617 (add)->prev->next = (add);                                                                   \
618 if ((el)->next == NULL) {                                                                    \
619 (head)->prev = (add);                                                                       \
620 } else {                                                                                     \
621 (add)->next->prev = (add);                                                                  \
622 }                                                                                            \
623 }                                                                                             \
624 } while (0)
625
626 #define DL_PREPEND_ELEM(head, el, add)                                                         \
627 do {                                                                                           \
628 assert(head != NULL);                                                                         \
629 assert(el != NULL);                                                                           \
630 assert(add != NULL);                                                                          \
631 (add)->next = (el);                                                                           \
632 (add)->prev = (el)->prev;                                                                     \
633 (el)->prev = (add);                                                                           \
634 if ((head) == (el)) {                                                                         \
635 (head) = (add);                                                                              \
636 } else {                                                                                      \
637 (add)->prev->next = (add);                                                                   \
638 }                                                                                             \
639 } while (0)                                                                                    \
640
641
642 /******************************************************************************
643  * circular doubly linked list macros                                         *
644  *****************************************************************************/
645 #define CDL_PREPEND(head,add)                                                                  \
646 CDL_PREPEND2(head,add,prev,next)
647
648 #define CDL_PREPEND2(head,add,prev,next)                                                       \
649 do {                                                                                           \
650 if (head) {                                                                                   \
651 (add)->prev = (head)->prev;                                                                 \
652 (add)->next = (head);                                                                       \
653 (head)->prev = (add);                                                                       \
654 (add)->prev->next = (add);                                                                  \
655 } else {                                                                                      \
656 (add)->prev = (add);                                                                        \
657 (add)->next = (add);                                                                        \
658 }                                                                                             \
659 (head)=(add);                                                                                  \
660 } while (0)
661
662 #define CDL_DELETE(head,del)                                                                   \
663 CDL_DELETE2(head,del,prev,next)
664
665 #define CDL_DELETE2(head,del,prev,next)                                                        \
666 do {                                                                                           \
667 if ( ((head)==(del)) && ((head)->next == (head))) {                                          \
668 (head) = 0L;                                                                             \
669 } else {                                                                                     \
670 (del)->next->prev = (del)->prev;                                                          \
671 (del)->prev->next = (del)->next;                                                          \
672 if ((del) == (head)) (head)=(del)->next;                                                  \
673 }                                                                                            \
674 } while (0)
675
676 #define CDL_COUNT(head,el,counter)                                                             \
677 CDL_COUNT2(head,el,counter,next)                                                           \
678
679 #define CDL_COUNT2(head, el, counter,next)                                                     \
680 {                                                                                              \
681 counter = 0;                                                                               \
682 CDL_FOREACH2(head,el,next){ ++counter; }                                                   \
683 }
684
685 #define CDL_FOREACH(head,el)                                                                   \
686 CDL_FOREACH2(head,el,next)
687
688 #define CDL_FOREACH2(head,el,next)                                                             \
689 for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
690
691 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
692 CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
693
694 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)                                         \
695 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL);                                        \
696 (el) && ((tmp2)=(el)->next, 1);                                                          \
697 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
698
699 #define CDL_SEARCH_SCALAR(head,out,field,val)                                                  \
700 CDL_SEARCH_SCALAR2(head,out,field,val,next)
701
702 #define CDL_SEARCH_SCALAR2(head,out,field,val,next)                                            \
703 do {                                                                                           \
704 CDL_FOREACH2(head,out,next) {                                                              \
705 if ((out)->field == (val)) break;                                                        \
706 }                                                                                          \
707 } while(0)
708
709 #define CDL_SEARCH(head,out,elt,cmp)                                                           \
710 CDL_SEARCH2(head,out,elt,cmp,next)
711
712 #define CDL_SEARCH2(head,out,elt,cmp,next)                                                     \
713 do {                                                                                           \
714 CDL_FOREACH2(head,out,next) {                                                              \
715 if ((cmp(out,elt))==0) break;                                                            \
716 }                                                                                          \
717 } while(0)
718
719 #define CDL_REPLACE_ELEM(head, el, add)                                                        \
720 do {                                                                                           \
721 assert(head != NULL);                                                                         \
722 assert(el != NULL);                                                                           \
723 assert(add != NULL);                                                                          \
724 if ((el)->next == (el)) {                                                                     \
725 (add)->next = (add);                                                                         \
726 (add)->prev = (add);                                                                         \
727 (head) = (add);                                                                              \
728 } else {                                                                                      \
729 (add)->next = (el)->next;                                                                    \
730 (add)->prev = (el)->prev;                                                                    \
731 (add)->next->prev = (add);                                                                   \
732 (add)->prev->next = (add);                                                                   \
733 if ((head) == (el)) {                                                                        \
734 (head) = (add);                                                                             \
735 }                                                                                            \
736 }                                                                                             \
737 } while (0)
738
739 #define CDL_PREPEND_ELEM(head, el, add)                                                        \
740 do {                                                                                           \
741 assert(head != NULL);                                                                         \
742 assert(el != NULL);                                                                           \
743 assert(add != NULL);                                                                          \
744 (add)->next = (el);                                                                           \
745 (add)->prev = (el)->prev;                                                                     \
746 (el)->prev = (add);                                                                           \
747 (add)->prev->next = (add);                                                                    \
748 if ((head) == (el)) {                                                                         \
749 (head) = (add);                                                                              \
750 }                                                                                             \
751 } while (0)                                                                                    \
752
753 #endif /* UTLIST_H */
This page took 0.077222 seconds and 4 git commands to generate.