858f24de4b93522b865b1eb0044525d720b990ad
[com/asn1c.git] / libasn1parser / asn1p_list.h
1 /*
2  * Singly linked tail queue support.
3  */
4 #ifndef ASN1_PARSER_LIST_H
5 #define ASN1_PARSER_LIST_H
6
7 #define TQ_HEAD(type)                                   \
8         struct {                                        \
9                 type *tq_head;                          \
10                 type**tq_tail;                          \
11         }
12
13 #define TQ_MOVE(to, from)       do {                    \
14         if(&(TQ_FIRST(from)) == (from)->tq_tail) {      \
15                 TQ_INIT(to);                            \
16         } else {                                        \
17                 (to)->tq_head = (from)->tq_head;        \
18                 (to)->tq_tail = (from)->tq_tail;        \
19         }                                               \
20         TQ_INIT(from);                                  \
21         } while(0)
22
23 #define TQ_ENTRY(type)                                  \
24         struct {                                        \
25                 type *tq_next;                          \
26         }
27
28 #define TQ_FIRST(headp)         ((headp)->tq_head)
29 #define TQ_NEXT(el, field)      ((el)->field.tq_next)
30
31 #define TQ_INIT(head) do {                              \
32         TQ_FIRST((head)) = 0;                           \
33         (head)->tq_tail = &TQ_FIRST((head));            \
34         } while(0)
35
36 #define TQ_FOR(var, head, field)                        \
37         for((var) = TQ_FIRST((head));                   \
38                 (var); (var) = TQ_NEXT((var), field))
39
40 /* MSVC does not have typeof(), cannot prevent side effects! */
41 #define TQ_ADD(head, xel, field) do {                   \
42         typeof(xel) __el = (xel);                       \
43         assert(TQ_NEXT((__el), field) == 0);            \
44         *(head)->tq_tail = (__el);                      \
45         (head)->tq_tail = &TQ_NEXT((__el), field);      \
46         } while(0)
47
48 #define TQ_CONCAT(head1, head2, field) do {             \
49         if(TQ_FIRST(head2)) {                           \
50                 *(head1)->tq_tail = (head2)->tq_head;   \
51                 (head1)->tq_tail = (head2)->tq_tail;    \
52                 TQ_INIT(head2);                         \
53         }                                               \
54         } while(0)
55
56 /*
57  * Remove the first element and return it.
58  */
59 #define TQ_REMOVE(head, field)  ({                      \
60         typeof(TQ_FIRST((head))) __fel;                 \
61         __fel = TQ_FIRST((head));                       \
62         if(__fel == 0                                   \
63         || (TQ_FIRST((head)) = TQ_NEXT(__fel, field))   \
64                 == 0) {                                 \
65                 (head)->tq_tail = &TQ_FIRST((head));    \
66         } else {                                        \
67                 TQ_NEXT(__fel, field) = 0;              \
68         }                                               \
69         __fel; })
70
71
72 #endif  /* ASN1_PARSER_LIST_H */