1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     nlib_queue.h
4 
5   Copyright (C)2009 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: 14703 $
14  *---------------------------------------------------------------------------*/
15 
16 /**
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 /**
30  * NLIBキューエントリ構造体
31  */
32 struct NLIBQueue {
33     struct NLIBQueue *next;   /**< next (or head) item */
34     struct NLIBQueue *prev;   /**< previous (or tail) item */
35 };
36 
37 /**
38  * Init - make queue empty
39  */
40 #define NLIB_Queue_Init(queue)          ((queue)->next = (queue)->prev = NULL)
41 
42 /**
43  * QueryFirst - returns first item in the queue
44  */
45 #define NLIB_Queue_QueryHead(queue)     ((queue)->next)
46 
47 /**
48  * QueryLast - returns last item in the queue
49  */
50 #define NLIB_Queue_QueryTail(queue)     ((queue)->prev)
51 
52 /**
53  * QueryLinkPrev- returns previous item in the queue
54  */
55 #define NLIB_Queue_QueryLinkPrev(item, link) ((item)->link.prev)
56 
57 /**
58  * QueryLinkNext- returns next item in the queue
59  */
60 #define NLIB_Queue_QueryLinkNext(item, link) ((item)->link.next)
61 
62 /**
63  * IsEmtpty - tests whether a queue is empty
64  */
65 #define NLIB_Queue_IsEmpty(queue)       ((queue)->next == NULL)
66 
67 /**
68  * IsEnd - tests whether the item is the end of the queue
69  */
70 #define NLIB_Queue_IsEnd(queue, item)   ((item) == NULL)
71 
72 /**
73  * EnqueueAfter - insert the item after previtem in the queue
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 /**
87  * EnqueueBefore - insert the item before afteritem in the queue
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 /**
101  * EnqueueTail - insert the item at the tail of the queue
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 /**
118  * EnqueueHead - insert the item at the head of the queue
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 /**
135  * DequeueItem - remove the item form the queue
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 /**
157  * NLIB_Queue_DequeueHead - remove and return the item at the head of the queue
158  * note: item is returned by reference
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 /**
175  * NLIB_Queue_DequeueTail - remove and return the item at the tail of the queue
176  * note: item is returned by reference
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 /**
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 /**
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