1 /* A queue definition based on sys/queue.h TAILQ definitions 2 * 3 * Copyright 2000 Peter Hunnisett 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 * 19 * NOTES 20 * o Linked list implementation for dplay/dplobby. Based off of the BSD 21 * version found in <sys/queue.h> 22 * o Port it to <wine/list.h> ? 23 * 24 */ 25 26 #ifndef __WINE_DPLAYX_QUEUE_H 27 #define __WINE_DPLAYX_QUEUE_H 28 29 #include <stdarg.h> 30 31 #include "windef.h" 32 #include "winbase.h" 33 34 #define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c) 35 36 /* 37 * Tail queue definitions. 38 */ 39 #define DPQ_HEAD(type) \ 40 struct { \ 41 struct type *lpQHFirst; /* first element */ \ 42 struct type **lpQHLast; /* addr of last next element */ \ 43 } 44 45 #define DPQ_ENTRY(type) \ 46 struct { \ 47 struct type *lpQNext; /* next element */ \ 48 struct type **lpQPrev; /* address of previous next element */ \ 49 } 50 51 /* 52 * Tail queue functions. 53 */ 54 #define DPQ_INIT(head) \ 55 do{ \ 56 (head).lpQHFirst = NULL; \ 57 (head).lpQHLast = &(head).lpQHFirst; \ 58 } while(0) 59 60 /* Front of the queue */ 61 #define DPQ_FIRST( head ) ( (head).lpQHFirst ) 62 63 /* Check if the queue has any elements */ 64 #define DPQ_IS_EMPTY( head ) ( DPQ_FIRST(head) == NULL ) 65 66 /* Next entry -- FIXME: Convert everything over to this macro ... */ 67 #define DPQ_NEXT( elem ) (elem).lpQNext 68 69 #define DPQ_IS_ENDOFLIST( elem ) \ 70 ( DPQ_NEXT(elem) == NULL ) 71 72 /* Insert element at end of queue */ 73 #define DPQ_INSERT_IN_TAIL(head, elm, field) \ 74 do { \ 75 (elm)->field.lpQNext = NULL; \ 76 (elm)->field.lpQPrev = (head).lpQHLast; \ 77 *(head).lpQHLast = (elm); \ 78 (head).lpQHLast = &(elm)->field.lpQNext; \ 79 } while(0) 80 81 /* Remove element from the queue */ 82 #define DPQ_REMOVE(head, elm, field) \ 83 do { \ 84 if (((elm)->field.lpQNext) != NULL) \ 85 (elm)->field.lpQNext->field.lpQPrev = \ 86 (elm)->field.lpQPrev; \ 87 else \ 88 (head).lpQHLast = (elm)->field.lpQPrev; \ 89 *(elm)->field.lpQPrev = (elm)->field.lpQNext; \ 90 } while(0) 91 92 /* head - pointer to DPQ_HEAD struct 93 * elm - how to find the next element 94 * field - to be concatenated to rc to compare with fieldToCompare 95 * fieldToCompare - The value that we're comparing against 96 * fieldCompareOperator - The logical operator to compare field and 97 * fieldToCompare. 98 * rc - Variable to put the return code. Same type as (head).lpQHFirst 99 */ 100 #define DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\ 101 do { \ 102 (rc) = DPQ_FIRST(head); /* NULL head? */ \ 103 \ 104 while( rc ) \ 105 { \ 106 /* What we're searching for? */ \ 107 if( (rc)->field fieldCompareOperator (fieldToCompare) ) \ 108 { \ 109 break; /* rc == correct element */ \ 110 } \ 111 \ 112 /* End of list check */ \ 113 if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \ 114 { \ 115 rc = NULL; \ 116 break; \ 117 } \ 118 } \ 119 } while(0) 120 121 /* head - pointer to DPQ_HEAD struct 122 * elm - how to find the next element 123 * field - to be concatenated to rc to compare with fieldToCompare 124 * fieldToCompare - The value that we're comparing against 125 * compare_cb - Callback to invoke to determine if comparison should continue. 126 * Callback must be defined with DPQ_DECL_COMPARECB. 127 * rc - Variable to put the return code. Same type as (head).lpQHFirst 128 */ 129 #define DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\ 130 do { \ 131 (rc) = DPQ_FIRST(head); /* NULL head? */ \ 132 \ 133 while( rc ) \ 134 { \ 135 /* What we're searching for? */ \ 136 if( compare_cb( &((rc)->field), &(fieldToCompare) ) ) \ 137 { \ 138 break; /* no more */ \ 139 } \ 140 \ 141 /* End of list check */ \ 142 if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \ 143 { \ 144 rc = NULL; \ 145 break; \ 146 } \ 147 } \ 148 } while(0) 149 150 /* How to define the method to be passed to DPQ_DELETEQ */ 151 #define DPQ_DECL_COMPARECB( name, type ) BOOL name( const type* elem1, const type* elem2 ) 152 153 154 /* head - pointer to DPQ_HEAD struct 155 * elm - how to find the next element 156 * field - to be concatenated to rc to compare with fieldToEqual 157 * fieldToCompare - The value that we're comparing against 158 * fieldCompareOperator - The logical operator to compare field and 159 * fieldToCompare. 160 * rc - Variable to put the return code. Same type as (head).lpQHFirst 161 */ 162 #define DPQ_REMOVE_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\ 163 do { \ 164 DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\ 165 \ 166 /* Was the element found? */ \ 167 if( rc ) \ 168 { \ 169 DPQ_REMOVE( head, rc, elm ); \ 170 } \ 171 } while(0) 172 173 /* head - pointer to DPQ_HEAD struct 174 * elm - how to find the next element 175 * field - to be concatenated to rc to compare with fieldToCompare 176 * fieldToCompare - The value that we're comparing against 177 * compare_cb - Callback to invoke to determine if comparison should continue. 178 * Callback must be defined with DPQ_DECL_COMPARECB. 179 * rc - Variable to put the return code. Same type as (head).lpQHFirst 180 */ 181 #define DPQ_REMOVE_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\ 182 do { \ 183 DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc );\ 184 \ 185 /* Was the element found? */ \ 186 if( rc ) \ 187 { \ 188 DPQ_REMOVE( head, rc, elm ); \ 189 } \ 190 } while(0) 191 192 193 /* Delete the entire queue 194 * head - pointer to the head of the queue 195 * field - field to access the next elements of the queue 196 * type - type of the pointer to the element element 197 * df - a delete function to be called. Declared with DPQ_DECL_DELETECB. 198 */ 199 #define DPQ_DELETEQ( head, field, type, df ) \ 200 do \ 201 { \ 202 while( !DPQ_IS_EMPTY(head) ) \ 203 { \ 204 type holder = DPQ_FIRST(head); \ 205 DPQ_REMOVE( head, holder, field ); \ 206 df( holder ); \ 207 } \ 208 } while(0) 209 210 /* How to define the method to be passed to DPQ_DELETEQ */ 211 #define DPQ_DECL_DELETECB( name, type ) void name( type elem ) 212 213 /* Prototype of a method which just performs a HeapFree on the elem */ 214 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID ) DECLSPEC_HIDDEN; 215 216 #endif /* __WINE_DPLAYX_QUEUE_H */ 217