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