pcb 4.1.1
An interactive printed circuit board layout editor.

lists.h

Go to the documentation of this file.
00001 
00036 /* lists.h 147 2007-04-09 00:44:09Z selinger */
00037 
00038 #ifndef PCB_HID_GCODE_LISTS_H
00039 #define PCB_HID_GCODE_LISTS_H
00040 
00048 #define MACRO_BEGIN do {
00049 #define MACRO_END   } while (0)
00050 
00051 /* ---------------------------------------------------------------------- */
00052 /* macros for singly-linked lists */
00053 
00056 #define list_forall(elt, list)   for (elt=list; elt!=NULL; elt=elt->next)
00057 
00061 #define list_find(elt, list, c) \
00062   MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
00063 
00067 #define list_forall2(elt, list, hook) \
00068   for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
00069 
00073 #define list_find2(elt, list, c, hook) \
00074   MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
00075 
00079 #define _list_forall_hook(list, hook) \
00080   for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
00081 
00087 #define _list_find_hook(list, c, hook) \
00088   MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
00089 
00093 #define list_insert_athook(elt, hook) \
00094   MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
00095 
00099 #define list_insert_beforehook(elt, hook) \
00100   MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
00101 
00106 #define list_unlink_athook(list, elt, hook) \
00107   MACRO_BEGIN \
00108   elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
00109   MACRO_END
00110 
00115 #define list_unlink(listtype, list, elt)      \
00116   MACRO_BEGIN                                 \
00117   listtype **_hook;                           \
00118   _list_find_hook(list, *_hook==elt, _hook);  \
00119   list_unlink_athook(list, elt, _hook);       \
00120   MACRO_END
00121 
00125 #define list_prepend(list, elt) \
00126   MACRO_BEGIN elt->next = list; list = elt; MACRO_END
00127 
00131 #define list_append(listtype, list, elt)     \
00132   MACRO_BEGIN                                \
00133   listtype **_hook;                          \
00134   _list_forall_hook(list, _hook) {}          \
00135   list_insert_athook(elt, _hook);            \
00136   MACRO_END
00137 
00141 #define list_unlink_cond(listtype, list, elt, c)     \
00142   MACRO_BEGIN                                        \
00143   listtype **_hook;                                  \
00144   list_find2(elt, list, c, _hook);                   \
00145   list_unlink_athook(list, elt, _hook);              \
00146   MACRO_END
00147 
00154 #define list_nth(elt, list, n)                                \
00155   MACRO_BEGIN                                                 \
00156   int _x;  /* only evaluate n once */                         \
00157   for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {}   \
00158   MACRO_END
00159 
00166 #define list_nth_hook(elt, list, n, hook)                     \
00167   MACRO_BEGIN                                                 \
00168   int _x;  /* only evaluate n once */                         \
00169   for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {}   \
00170   MACRO_END
00171 
00175 #define list_length(listtype, list, n)                   \
00176   MACRO_BEGIN                                            \
00177   listtype *_elt;                                        \
00178   n=0;                                                   \
00179   list_forall(_elt, list)                                \
00180     n++;                                                 \
00181   MACRO_END
00182 
00189 #define list_index(list, n, elt, c)                      \
00190   MACRO_BEGIN                                            \
00191   n=0;                                                   \
00192   list_forall(elt, list) {                               \
00193     if (c) break;                                        \
00194     n++;                                                 \
00195   }                                                      \
00196   if (!elt)                                              \
00197     n=-1;                                                \
00198   MACRO_END
00199 
00204 #define list_count(list, n, elt, c)                      \
00205   MACRO_BEGIN                                            \
00206   n=0;                                                   \
00207   list_forall(elt, list) {                               \
00208     if (c) n++;                                          \
00209   }                                                      \
00210   MACRO_END
00211 
00217 #define list_forall_unlink(elt, list) \
00218   for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
00219 
00223 #define list_reverse(listtype, list)            \
00224   MACRO_BEGIN                                   \
00225   listtype *_list1=NULL, *elt;                  \
00226   list_forall_unlink(elt, list)                 \
00227     list_prepend(_list1, elt);                  \
00228   list = _list1;                                \
00229   MACRO_END
00230 
00249 #define list_insert_ordered(listtype, list, elt, tmp, cond) \
00250   MACRO_BEGIN                                               \
00251   listtype **_hook;                                         \
00252   _list_find_hook(list, (tmp=*_hook, (cond)), _hook);       \
00253   list_insert_athook(elt, _hook);                           \
00254   MACRO_END
00255 
00267 #define list_sort(listtype, list, a, b, cond)            \
00268   MACRO_BEGIN                                            \
00269   listtype *_newlist=NULL;                               \
00270   list_forall_unlink(a, list)                            \
00271     list_insert_ordered(listtype, _newlist, a, b, cond); \
00272   list = _newlist;                                       \
00273   MACRO_END
00274 
00284 #define list_mergesort(listtype, list, a, b, cond)              \
00285   MACRO_BEGIN                                                   \
00286   listtype *_elt, **_hook1;                                     \
00287                                                                 \
00288   for (_elt=list; _elt; _elt=_elt->next1) {                     \
00289     _elt->next1 = _elt->next;                                   \
00290     _elt->next = NULL;                                          \
00291   }                                                             \
00292   do {                                                          \
00293     _hook1 = &(list);                                           \
00294     while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) {  \
00295       _elt = b->next1;                                          \
00296       _list_merge_cond(listtype, a, b, cond, *_hook1);          \
00297       _hook1 = &((*_hook1)->next1);                             \
00298       *_hook1 = _elt;                                           \
00299     }                                                           \
00300   } while (_hook1 != &(list));                                  \
00301   MACRO_END
00302 
00308 #define _list_merge_cond(listtype, a, b, cond, result)   \
00309   MACRO_BEGIN                                            \
00310   listtype **_hook;                                      \
00311   _hook = &(result);                                     \
00312   while (1) {                                            \
00313      if (a==NULL) {                                      \
00314        *_hook = b;                                       \
00315        break;                                            \
00316      } else if (b==NULL) {                               \
00317        *_hook = a;                                       \
00318        break;                                            \
00319      } else if (cond) {                                  \
00320        *_hook = a;                                       \
00321        _hook = &(a->next);                               \
00322        a = a->next;                                      \
00323      } else {                                            \
00324        *_hook = b;                                       \
00325        _hook = &(b->next);                               \
00326        b = b->next;                                      \
00327      }                                                   \
00328   }                                                      \
00329   MACRO_END
00330 
00331 /* ---------------------------------------------------------------------- */
00332 /* macros for doubly-linked lists */
00333 
00334 #define dlist_append(head, end, elt)                    \
00335   MACRO_BEGIN                                            \
00336   elt->prev = end;                                       \
00337   elt->next = NULL;                                      \
00338   if (end) {                                             \
00339     end->next = elt;                                     \
00340   } else {                                               \
00341     head = elt;                                          \
00342   }                                                      \
00343   end = elt;                                             \
00344   MACRO_END
00345 
00351 #define dlist_forall_unlink(elt, head, end) \
00352   for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
00353 
00357 #define dlist_unlink_first(head, end, elt)               \
00358   MACRO_BEGIN                                            \
00359   elt = head;                                            \
00360   if (head) {                                            \
00361     head = head->next;                                   \
00362     if (head) {                                          \
00363       head->prev = NULL;                                 \
00364     } else {                                             \
00365       end = NULL;                                        \
00366     }                                                    \
00367     elt->prev = NULL;                                    \
00368     elt->next = NULL;                                    \
00369   }                                                      \
00370   MACRO_END
00371 
00372 #endif /* PCB_HID_GCODE_LISTS_H */