gwenhywfar  5.10.1
list1.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Sat Nov 15 2003
3  copyright : (C) 2003 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include "list1_p.h"
31 #include <gwenhywfar/misc.h>
32 #include <gwenhywfar/debug.h>
33 
34 
35 static GWENHYWFAR_CB int GWEN_List1__defaultSortFn(GWEN_UNUSED const void *a, GWEN_UNUSED const void *b,
36  GWEN_UNUSED int ascending)
37 {
38  return 0;
39 }
40 
41 
42 
44 {
45  GWEN_LIST1 *l;
46 
48  l->sortFunction=GWEN_List1__defaultSortFn;
49  return l;
50 }
51 
52 
54 {
55  if (l) {
57  }
58 }
59 
60 
61 
63 {
64  assert(l);
65  return l->count;
66 }
67 
68 
69 
71 {
72  assert(l);
73  assert(el);
74  if (el->listPtr) {
75  /* element is already part of another list */
76  DBG_ERROR(GWEN_LOGDOMAIN, "Element is already part of a list");
77  assert(0);
78  return -1;
79  }
80 
81  if (l->firstElement==0)
82  l->firstElement=el;
83 
84  el->prevElement=l->lastElement;
85  if (l->lastElement)
86  l->lastElement->nextElement=el;
87  l->lastElement=el;
88 
89  el->listPtr=l;
90  l->count++;
91 
92  return 0;
93 }
94 
95 
96 
98 {
100 
101  assert(dest);
102  assert(l);
103 
104  while ((el=l->firstElement)) {
105  GWEN_List1_Del(el);
106  GWEN_List1_Add(dest, el);
107  }
108 
109  return 0;
110 }
111 
112 
113 
115 {
116  assert(l);
117  assert(el);
118  if (el->listPtr) {
119  /* element is already part of another list */
120  DBG_ERROR(GWEN_LOGDOMAIN, "Element is already part of a list");
121  return -1;
122  }
123 
124  el->nextElement=l->firstElement;
125  l->firstElement=el;
126 
127  if (l->lastElement==0)
128  l->lastElement=el;
129 
130  if (el->nextElement)
131  el->nextElement->prevElement=el;
132 
133  el->listPtr=l;
134  l->count++;
135 
136  return 0;
137 }
138 
139 
140 
142 {
143  GWEN_LIST1 *l;
144 
145  assert(el);
146  l=el->listPtr;
147 
148  if (l==0) {
149  /* not part of any list */
150  DBG_ERROR(GWEN_LOGDOMAIN, "Element is not part of any list");
151  return -1;
152  }
153 
154  /* unlink from previous */
155  if (el->prevElement)
156  el->prevElement->nextElement=el->nextElement;
157 
158  /* unlink from next */
159  if (el->nextElement)
160  el->nextElement->prevElement=el->prevElement;
161 
162  /* unlink from list */
163  if (l->firstElement==el)
164  l->firstElement=el->nextElement;
165  if (l->lastElement==el)
166  l->lastElement=el->prevElement;
167  l->count--;
168 
169  el->nextElement=0;
170  el->prevElement=0;
171  el->listPtr=0;
172 
173  return 0;
174 }
175 
176 
177 
179 {
180  if (l->firstElement)
181  return l->firstElement->data;
182  return 0;
183 }
184 
185 
186 
188 {
189  if (l->lastElement)
190  return l->lastElement->data;
191  return 0;
192 }
193 
194 
195 
196 
197 
198 
200 {
201  GWEN_LIST1_ELEMENT *el;
202 
204  el->data=d;
205 
206  return el;
207 }
208 
209 
210 
212 {
213  if (el) {
214  if (el->listPtr)
215  GWEN_List1_Del(el);
216  GWEN_FREE_OBJECT(el);
217  }
218 }
219 
220 
221 
223 {
224  return el->data;
225 }
226 
227 
228 
230 {
231  if (el->prevElement)
232  return el->prevElement->data;
233  return 0;
234 }
235 
236 
237 
239 {
240  if (el->nextElement)
241  return el->nextElement->data;
242  return 0;
243 }
244 
245 
246 
247 #if 0
248 static int GWEN_List1__compar_asc(const void *a, const void *b)
249 {
250  const GWEN_LIST1_ELEMENT *const *pse1 = a, * const * pse2 = b;
251  const GWEN_LIST1_ELEMENT *se1 = *pse1, *se2 = *pse2;
252 
253  return (se1->listPtr->sortFunction)(se1->data, se2->data, 1);
254 }
255 
256 
257 
258 static int GWEN_List1__compar_desc(const void *a, const void *b)
259 {
260  const GWEN_LIST1_ELEMENT *const *pse1 = a, * const * pse2 = b;
261  const GWEN_LIST1_ELEMENT *se1 = *pse1, *se2 = *pse2;
262 
263  return (se1->listPtr->sortFunction)(se1->data, se2->data, 0);
264 }
265 
266 
267 
269 {
270  GWEN_LIST1_SORT_FN oldFn;
271 
272  assert(l);
273  oldFn=l->sortFunction;
274  l->sortFunction=fn;
275  return oldFn;
276 }
277 
278 
279 
280 void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
281 {
282  GWEN_LIST1_ELEMENT **tmpEntries;
283  GWEN_LIST1_ELEMENT *sentry;
284  GWEN_LIST1_ELEMENT **psentry;
285  uint32_t count;
286  uint32_t i;
287 
288  if (l->count<1)
289  return;
290 
291  count=l->count;
292 
293  /* sort entries into a linear pointer list */
294  tmpEntries=(GWEN_LIST1_ELEMENT **)malloc((count+1)* sizeof(GWEN_LIST1_ELEMENT *));
295  assert(tmpEntries);
296  psentry=tmpEntries;
297 
298  sentry=l->firstElement;
299  while (sentry) {
300  GWEN_LIST1_ELEMENT *next;
301 
302  *(psentry++)=sentry;
303  next=sentry->nextElement;
304  sentry->prevElement=NULL;
305  sentry->nextElement=NULL;
306  sentry->listPtr=l;
307  sentry=next;
308  } /* while */
309  *psentry=NULL;
310 
311  /* clear list */
312  l->count=0;
313  l->firstElement=NULL;
314  l->lastElement=NULL;
315 
316  /* sort */
317  if (ascending)
318  qsort(tmpEntries, count, sizeof(GWEN_LIST1_ELEMENT *), GWEN_List1__compar_asc);
319  else
320  qsort(tmpEntries, count, sizeof(GWEN_LIST1_ELEMENT *), GWEN_List1__compar_desc);
321 
322  /* sort entries back into GWEN_LIST1 according to temporary list */
323  psentry=tmpEntries;
324  /* we use "<=count" because the list contains count+1 elements */
325  for (i=0; i<=count; i++) {
326  if (*psentry) {
327  (*psentry)->listPtr=NULL;
328  GWEN_List1_Add(l, *psentry);
329  }
330  psentry++;
331  } /* for */
332 
333  free(tmpEntries);
334 }
335 #endif
336 
337 
338 
339 
340 
341 
342 
343 
344 
345 /* -------------------------------------------------------------------------------------------------
346  * Sort
347  * -------------------------------------------------------------------------------------------------
348  */
349 
350 
351 static int GWEN_List1__compar(const void *a, const void *b)
352 {
353  const GWEN_LIST1_SORT_ELEM *const *pse1 = a, * const * pse2 = b;
354  const GWEN_LIST1_SORT_ELEM *se1 = *pse1, *se2 = *pse2;
355  const GWEN_LIST1_SORT_CTX *ctx=se1->context;
356 
357  const GWEN_LIST1_ELEMENT *e1=se1->element;
358  const GWEN_LIST1_ELEMENT *e2=se2->element;
359 
360  return (ctx->list->sortFunction)(e1->data, e2->data, ctx->param);
361 }
362 
363 
364 
366 {
367  GWEN_LIST1_SORT_FN oldFn;
368 
369  assert(l);
370  oldFn=l->sortFunction;
371  l->sortFunction=fn;
372  return oldFn;
373 }
374 
375 
376 
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 GWEN_LIST1_SORT_CTX *GWEN_List1_SortCtx_new(GWEN_LIST1 *list, int param)
387 {
388  GWEN_LIST1_SORT_CTX *ctx;
389 
390  GWEN_NEW_OBJECT(GWEN_LIST1_SORT_CTX, ctx);
391  ctx->list=list;
392  ctx->param=param;
393  return ctx;
394 }
395 
396 
397 
398 void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
399 {
400  if (ctx) {
401  GWEN_FREE_OBJECT(ctx);
402  }
403 }
404 
405 
406 
407 GWEN_LIST1_SORT_ELEM *GWEN_List1_SortElem_new(GWEN_LIST1_SORT_CTX *ctx, GWEN_LIST1_ELEMENT *elem)
408 {
409  GWEN_LIST1_SORT_ELEM *e;
410 
411  GWEN_NEW_OBJECT(GWEN_LIST1_SORT_ELEM, e);
412  e->context=ctx;
413  e->element=elem;
414  return e;
415 }
416 
417 
418 
419 void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
420 {
421  if (e) {
422  GWEN_FREE_OBJECT(e);
423  }
424 }
425 
426 
427 
428 void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
429 {
430  GWEN_LIST1_SORT_ELEM **tmpEntries;
431  GWEN_LIST1_SORT_ELEM **psentry;
432  GWEN_LIST1_ELEMENT *sentry;
433  uint32_t count;
434  uint32_t i;
435  GWEN_LIST1_SORT_CTX *sortContext;
436 
437  if (l->count<1)
438  return;
439 
440  count=l->count;
441 
442  sortContext=GWEN_List1_SortCtx_new(l, ascending);
443 
444  /* sort entries into a linear pointer list */
445  tmpEntries=(GWEN_LIST1_SORT_ELEM **)malloc((count+1)* sizeof(GWEN_LIST1_SORT_ELEM *));
446  assert(tmpEntries);
447  psentry=tmpEntries;
448 
449  sentry=l->firstElement;
450  while (sentry) {
451  GWEN_LIST1_ELEMENT *next;
452  GWEN_LIST1_SORT_ELEM *se;
453 
454  se=GWEN_List1_SortElem_new(sortContext, sentry);
455  *(psentry++)=se;
456  next=sentry->nextElement;
457  sentry->prevElement=NULL;
458  sentry->nextElement=NULL;
459  sentry->listPtr=l;
460  sentry=next;
461  } /* while */
462  *psentry=NULL;
463 
464  /* clear list */
465  l->count=0;
466  l->firstElement=NULL;
467  l->lastElement=NULL;
468 
469  /* sort */
470  qsort(tmpEntries, count, sizeof(GWEN_LIST1_SORT_ELEM *), GWEN_List1__compar);
471 
472  /* sort entries back into GWEN_LIST1 according to temporary list */
473  psentry=tmpEntries;
474  /* we use "<=count" because the list contains count+1 elements */
475  for (i=0; i<=count; i++) {
476  GWEN_LIST1_SORT_ELEM *se;
477 
478  se=*psentry;
479  if (se) {
480  sentry=se->element;
481  sentry->listPtr=NULL;
482  GWEN_List1_Add(l, sentry);
484  *psentry=NULL;
485  }
486  psentry++;
487  } /* for */
488 
489  free(tmpEntries);
490  GWEN_List1_SortCtx_free(sortContext);
491 }
492 
493 
494 
495 
496 
497 
int GWEN_List1_Add(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:70
int GWENHYWFAR_CB(* GWEN_LIST1_SORT_FN)(const void *a, const void *b, int ascending)
Definition: list1.h:158
void * GWEN_List1_GetLast(const GWEN_LIST1 *l)
Definition: list1.c:187
void * GWEN_List1_GetFirst(const GWEN_LIST1 *l)
Definition: list1.c:178
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
int GWEN_List1_Del(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:141
#define GWEN_LOGDOMAIN
Definition: logger.h:35
struct GWEN_LIST1 GWEN_LIST1
Definition: list1.h:155
GWEN_LIST1 * GWEN_List1_new(void)
Definition: list1.c:43
void GWEN_List1Element_free(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:211
static GWENHYWFAR_CB int GWEN_List1__defaultSortFn(GWEN_UNUSED const void *a, GWEN_UNUSED const void *b, GWEN_UNUSED int ascending)
Definition: list1.c:35
GWEN_LIST1_ELEMENT * GWEN_List1Element_new(void *d)
Definition: list1.c:199
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
GWEN_LIST1_SORT_FN GWEN_List1_SetSortFn(GWEN_LIST1 *l, GWEN_LIST1_SORT_FN fn)
Definition: list1.c:365
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
Definition: list1.c:398
int GWEN_List1_AddList(GWEN_LIST1 *dest, GWEN_LIST1 *l)
Definition: list1.c:97
void GWEN_List1_free(GWEN_LIST1 *l)
Definition: list1.c:53
void * GWEN_List1Element_GetPrevious(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:229
void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
Definition: list1.c:419
struct GWEN_LIST1_ELEMENT GWEN_LIST1_ELEMENT
Definition: list1.h:156
static int GWEN_List1__compar(const void *a, const void *b)
Definition: list1.c:351
GWEN_LIST1_SORT_ELEM * GWEN_List1_SortElem_new(GWEN_LIST1_SORT_CTX *ctx, GWEN_LIST1_ELEMENT *elem)
Definition: list1.c:407
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
Definition: list1.c:428
int GWEN_List1_Insert(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:114
void * GWEN_List1Element_GetNext(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:238
GWEN_LIST1_SORT_CTX * GWEN_List1_SortCtx_new(GWEN_LIST1 *list, int param)
Definition: list1.c:386
void * GWEN_List1Element_GetData(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:222
int GWEN_List1_GetCount(const GWEN_LIST1 *l)
Definition: list1.c:62
#define GWEN_UNUSED