1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     nlib_queue.h
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 46347 $
14  *---------------------------------------------------------------------------*/
15 
16 /* Please see man pages for details
17 
18  */
19 
20 #ifndef __NLIB_QUEUE_H__
21 #define __NLIB_QUEUE_H__
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 typedef struct NLIBQueue  NLIBQueue, NLIBLink;
28 
29 /* Please see man pages for details
30 
31  */
32 struct NLIBQueue {
33     struct NLIBQueue *next;   /* Please see man pages for details */
34     struct NLIBQueue *prev;   /* Please see man pages for details */
35 };
36 
37 /* Please see man pages for details
38 
39  */
40 #define NLIB_Queue_Init(queue)          ((queue)->next = (queue)->prev = NULL)
41 
42 /* Please see man pages for details
43 
44  */
45 #define NLIB_Queue_QueryHead(queue)     ((queue)->next)
46 
47 /* Please see man pages for details
48 
49  */
50 #define NLIB_Queue_QueryTail(queue)     ((queue)->prev)
51 
52 /* Please see man pages for details
53 
54  */
55 #define NLIB_Queue_QueryLinkPrev(item, link) ((item)->link.prev)
56 
57 /* Please see man pages for details
58 
59  */
60 #define NLIB_Queue_QueryLinkNext(item, link) ((item)->link.next)
61 
62 /* Please see man pages for details
63 
64  */
65 #define NLIB_Queue_IsEmpty(queue)       ((queue)->next == NULL)
66 
67 /* Please see man pages for details
68 
69  */
70 #define NLIB_Queue_IsEnd(queue, item)   ((item) == NULL)
71 
72 /* Please see man pages for details
73 
74  */
75 #define NLIB_Queue_EnqueueAfter(type, queue, previtem, item, link)           \
76 do {                                                                \
77     (item)->link.prev = (NLIBQueue*) (previtem);                      \
78     (item)->link.next = (previtem)->link.next;                      \
79     (previtem)->link.next = (NLIBQueue*) (item);                      \
80     if (NLIB_Queue_IsEnd(queue, (item)->link.next))                     \
81         (queue)->prev = (NLIBQueue*) (item);                          \
82     else                                                            \
83         ((type) (item)->link.next)->link.prev = (NLIBQueue*) (item);  \
84 } while (0)
85 
86 /* Please see man pages for details
87 
88  */
89 #define NLIB_Queue_EnqueueBefore(type, queue, item, afteritem, link)         \
90 do {                                                                \
91     (item)->link.prev = (afteritem)->link.prev;                     \
92     (item)->link.next = (NLIBQueue*) (afteritem);                     \
93     (afteritem)->link.prev = (NLIBQueue*) (item);                     \
94     if (NLIB_Queue_IsEnd(queue, (item)->link.prev))                     \
95         (queue)->next = (NLIBQueue*) (item);                          \
96     else                                                            \
97         ((type) (item)->link.prev)->link.next = (NLIBQueue*) (item);  \
98 } while (0)
99 
100 /* Please see man pages for details
101 
102  */
103 #define NLIB_Queue_EnqueueTail(type, queue, item, link)                      \
104 do {                                                                \
105     register NLIBQueue* ___prev;                                      \
106                                                                     \
107     ___prev = (queue)->prev;                                        \
108     if (NLIB_Queue_IsEnd(queue, ___prev))                               \
109         (queue)->next = (NLIBQueue*) (item);                          \
110     else                                                            \
111         ((type) ___prev)->link.next = (NLIBQueue*) (item);            \
112     (item)->link.prev = ___prev;                                    \
113     (item)->link.next = NULL;                                       \
114     (queue)->prev = (NLIBQueue*) item;                                \
115 } while (0)
116 
117 /* Please see man pages for details
118 
119  */
120 #define NLIB_Queue_EnqueueHead(type, queue, item, link)                      \
121 do {                                                                \
122     register NLIBQueue* ___next;                                      \
123                                                                     \
124     ___next = (queue)->next;                                        \
125     if (NLIB_Queue_IsEnd(queue, ___next))                               \
126         (queue)->prev = (NLIBQueue*) (item);                          \
127     else                                                            \
128         ((type) ___next)->link.prev = (NLIBQueue*) (item);            \
129     (item)->link.next = ___next;                                    \
130     (item)->link.prev = NULL;                                       \
131     (queue)->next = (NLIBQueue*) item;                                \
132 } while (0)
133 
134 /* Please see man pages for details
135 
136  */
137 #define NLIB_Queue_DequeueItem(type, queue, item, link)                      \
138 do {                                                                \
139     register NLIBQueue* ___next;                                      \
140     register NLIBQueue* ___prev;                                      \
141                                                                     \
142     ___next = (item)->link.next;                                    \
143     ___prev = (item)->link.prev;                                    \
144                                                                     \
145     if (NLIB_Queue_IsEnd(queue, ___next))                               \
146         (queue)->prev = ___prev;                                    \
147     else                                                            \
148         ((type) ___next)->link.prev = ___prev;                      \
149                                                                     \
150     if (NLIB_Queue_IsEnd(queue, ___prev))                               \
151         (queue)->next = ___next;                                    \
152     else                                                            \
153         ((type) ___prev)->link.next = ___next;                      \
154 } while (0)
155 
156 /* Please see man pages for details
157 
158 
159  */
160 #define NLIB_Queue_DequeueHead(type, queue, item, link)                      \
161 do {                                                                \
162     register NLIBQueue* ___next;                                      \
163                                                                     \
164     (item) = (type) NLIB_Queue_QueryHead(queue);                        \
165     ___next = (item)->link.next;                                    \
166                                                                     \
167     if (NLIB_Queue_IsEnd(queue, ___next))                               \
168         (queue)->prev = NULL;                                       \
169     else                                                            \
170         ((type) ___next)->link.prev = NULL;                         \
171     (queue)->next = ___next;                                        \
172 } while (0)
173 
174 /* Please see man pages for details
175 
176 
177  */
178 #define NLIB_Queue_DequeueTail(type, queue, item, link)                      \
179 do {                                                                \
180     register NLIBQueue* ___prev;                                      \
181                                                                     \
182     (item) = (type) NLIB_Queue_QueryTail(queue);                        \
183     ___prev = (item)->link.prev;                                    \
184                                                                     \
185     if (NLIB_Queue_IsEnd(queue, ___prev))                               \
186         (queue)->next = NULL;                                       \
187     else                                                            \
188         ((type) ___prev)->link.next = NULL;                         \
189     (queue)->prev = ___prev;                                        \
190 } while (0)
191 
192 /* Please see man pages for details
193 
194  */
195 #define NLIB_Queue_IterateQueue(type, queue, item, next, link)               \
196     for ((item) = (type) NLIB_Queue_QueryHead(queue),                   \
197          (next) = NLIB_Queue_IsEnd(queue, item) ? NULL : (type) NLIB_Queue_QueryLinkNext(item, link);    \
198          !NLIB_Queue_IsEnd(queue, item);                                 \
199          (item) = (next),                                           \
200          (next) = NLIB_Queue_IsEnd(queue, item) ? NULL : (type) NLIB_Queue_QueryLinkNext(item, link))
201 
202 /* Please see man pages for details
203 
204  */
205 #define NLIB_Queue_IterateQueueReverse(type, queue, item, prev, link)        \
206     for ((item) = (type) NLIB_Queue_QueryTail(queue),                   \
207          (prev) = NLIB_Queue_IsEnd(queue, item) ? NULL : (type) NLIB_Queue_QueryLinkPrev(item, link);    \
208          !NLIB_Queue_IsEnd(queue, item);                                 \
209          (item) = (prev),                                           \
210          (prev) = NLIB_Queue_IsEnd(queue, item) ? NULL : (type) NLIB_Queue_QueryLinkPrev(item, link))
211 
212 #ifdef __cplusplus
213 }
214 #endif
215 
216 /* __NLIB_QUEUE_H__ */
217 #endif
218