Add macro to mark parameters as unused
[notion.git] / libtu / objlist.c
blob4867e29081771abe341e55e0756b4a09bdc1a537
1 /*
2 * libtu/objlist.c
4 * Copyright (c) Tuomo Valkonen 1999-2005.
6 * You may distribute and modify this library under the terms of either
7 * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
8 */
10 #include "obj.h"
11 #include "types.h"
12 #include "objlist.h"
13 #include "dlist.h"
14 #include "misc.h"
17 static ObjList *reuse_first(ObjList **objlist)
19 ObjList *node=*objlist;
21 if(node!=NULL && node->watch.obj==NULL){
22 UNLINK_ITEM(*objlist, node, next, prev);
23 return node;
26 return NULL;
30 static ObjList *reuse_last(ObjList **objlist)
32 ObjList *node=*objlist;
34 if(node==NULL)
35 return NULL;
37 node=node->prev;
39 if(node!=NULL && node->watch.obj==NULL){
40 UNLINK_ITEM(*objlist, node, next, prev);
41 return node;
44 return NULL;
48 static ObjList *reuse(ObjList **objlist)
50 ObjList *first=reuse_first(objlist);
51 ObjList *last=reuse_first(objlist);
53 if(first==NULL){
54 return last;
55 }else{
56 if(last!=NULL)
57 free(last);
58 return first;
63 static void optimise(ObjList **objlist)
65 ObjList *first=reuse_first(objlist);
66 ObjList *last=reuse_first(objlist);
68 if(first!=NULL)
69 free(first);
70 if(last!=NULL)
71 free(last);
75 void watch_handler(Watch *watch, Obj *UNUSED(obj))
77 ObjList *node=(ObjList*)watch;
79 assert(node->prev!=NULL);
81 if(node->next==NULL){
82 /* Last item - can't free */
83 }else if(node->prev->next==NULL){
84 /* First item - can't free cheaply */
85 }else{
86 ObjList *tmp=node->prev;
87 node->next->prev=node->prev;
88 tmp->next=node->next;
89 free(node);
94 static void free_node(ObjList **objlist, ObjList *node)
96 watch_reset(&(node->watch));
97 UNLINK_ITEM(*objlist, node, next, prev);
98 free(node);
102 static ObjList *mknode(void *obj)
104 ObjList *node;
106 if(obj==NULL)
107 return NULL;
109 node=ALLOC(ObjList);
111 if(node==NULL)
112 return FALSE;
114 watch_init(&(node->watch));
116 if(!watch_setup(&(node->watch), obj, watch_handler)){
117 free(node);
118 return NULL;
121 return node;
125 static ObjList *objlist_find_node(ObjList *objlist, Obj *obj)
127 ObjList *node=objlist;
129 while(node!=NULL){
130 if(node->watch.obj==obj)
131 break;
132 node=node->next;
135 return node;
139 bool objlist_contains(ObjList *objlist, Obj *obj)
141 return (objlist_find_node(objlist, obj)!=NULL);
145 bool objlist_insert_last(ObjList **objlist, Obj *obj)
147 ObjList *node=reuse(objlist);
149 if(node==NULL)
150 node=mknode(obj);
152 if(node==NULL)
153 return FALSE;
155 LINK_ITEM_LAST(*objlist, node, next, prev);
157 return TRUE;
161 bool objlist_insert_first(ObjList **objlist, Obj *obj)
163 ObjList *node=reuse(objlist);
165 if(node==NULL)
166 node=mknode(obj);
168 if(node==NULL)
169 return FALSE;
171 LINK_ITEM_FIRST(*objlist, node, next, prev);
173 return TRUE;
177 bool objlist_reinsert_last(ObjList **objlist, Obj *obj)
179 ObjList *node;
181 optimise(objlist);
183 node=objlist_find_node(*objlist, obj);
185 if(node==NULL)
186 return objlist_insert_last(objlist, obj);
188 UNLINK_ITEM(*objlist, node, next, prev);
189 LINK_ITEM_LAST(*objlist, node, next, prev);
191 return TRUE;
195 bool objlist_reinsert_first(ObjList **objlist, Obj *obj)
197 ObjList *node;
199 optimise(objlist);
201 node=objlist_find_node(*objlist, obj);
203 if(node==NULL)
204 return objlist_insert_first(objlist, obj);
206 UNLINK_ITEM(*objlist, node, next, prev);
207 LINK_ITEM_FIRST(*objlist, node, next, prev);
209 return TRUE;
213 bool objlist_remove(ObjList **objlist, Obj *obj)
215 ObjList *node=objlist_find_node(*objlist, obj);
217 if(node!=NULL)
218 free_node(objlist, node);
220 optimise(objlist);
222 return (node!=NULL);
226 void objlist_clear(ObjList **objlist)
228 while(*objlist!=NULL)
229 free_node(objlist, *objlist);
233 ObjListIterTmp objlist_iter_tmp=NULL;
236 void objlist_iter_init(ObjListIterTmp *state, ObjList *objlist)
238 *state=objlist;
242 Obj *objlist_iter(ObjListIterTmp *state)
244 Obj *obj=NULL;
246 while(obj==NULL && *state!=NULL){
247 obj=(*state)->watch.obj;
248 (*state)=(*state)->next;
251 return obj;
255 void objlist_iter_rev_init(ObjListIterTmp *state, ObjList *objlist)
257 *state=(objlist==NULL ? NULL : objlist->prev);
261 Obj *objlist_iter_rev(ObjListIterTmp *state)
263 Obj *obj=NULL;
265 while(obj==NULL && *state!=NULL){
266 obj=(*state)->watch.obj;
267 *state=(*state)->prev;
268 if((*state)->next==NULL)
269 *state=NULL;
272 return obj;
276 bool objlist_empty(ObjList *objlist)
278 ObjListIterTmp tmp;
279 Obj *obj;
281 FOR_ALL_ON_OBJLIST(Obj*, obj, objlist, tmp){
282 return FALSE;
285 return TRUE;
289 Obj *objlist_take_first(ObjList **objlist)
291 ObjList *node;
292 Obj*obj;
294 optimise(objlist);
296 node=*objlist;
298 if(node==NULL)
299 return NULL;
301 obj=node->watch.obj;
303 assert(obj!=NULL);
305 free_node(objlist, node);
307 return obj;
311 Obj *objlist_take_last(ObjList **objlist)
313 ObjList *node;
314 Obj*obj;
316 optimise(objlist);
318 node=*objlist;
320 if(node==NULL)
321 return NULL;
323 node=node->prev;
325 obj=node->watch.obj;
327 assert(obj!=NULL);
329 free_node(objlist, node);
331 return obj;