gwenhywfar  4.99.15beta
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(const void *a, const void *b, int ascending)
36 {
37  return 0;
38 }
39 
40 
41 
43 {
44  GWEN_LIST1 *l;
45 
47  l->sortFunction=GWEN_List1__defaultSortFn;
48  return l;
49 }
50 
51 
53 {
54  if (l) {
56  }
57 }
58 
59 
60 
62 {
63  assert(l);
64  return l->count;
65 }
66 
67 
68 
70 {
71  assert(l);
72  assert(el);
73  if (el->listPtr) {
74  /* element is already part of another list */
75  DBG_ERROR(GWEN_LOGDOMAIN, "Element is already part of a list");
76  assert(0);
77  return -1;
78  }
79 
80  if (l->firstElement==0)
81  l->firstElement=el;
82 
83  el->prevElement=l->lastElement;
84  if (l->lastElement)
85  l->lastElement->nextElement=el;
86  l->lastElement=el;
87 
88  el->listPtr=l;
89  l->count++;
90 
91  return 0;
92 }
93 
94 
95 
97 {
99 
100  assert(dest);
101  assert(l);
102 
103  while ((el=l->firstElement)) {
104  GWEN_List1_Del(el);
105  GWEN_List1_Add(dest, el);
106  }
107 
108  return 0;
109 }
110 
111 
112 
114 {
115  assert(l);
116  assert(el);
117  if (el->listPtr) {
118  /* element is already part of another list */
119  DBG_ERROR(GWEN_LOGDOMAIN, "Element is already part of a list");
120  return -1;
121  }
122 
123  el->nextElement=l->firstElement;
124  l->firstElement=el;
125 
126  if (l->lastElement==0)
127  l->lastElement=el;
128 
129  if (el->nextElement)
130  el->nextElement->prevElement=el;
131 
132  el->listPtr=l;
133  l->count++;
134 
135  return 0;
136 }
137 
138 
139 
141 {
142  GWEN_LIST1 *l;
143 
144  assert(el);
145  l=el->listPtr;
146 
147  if (l==0) {
148  /* not part of any list */
149  DBG_ERROR(GWEN_LOGDOMAIN, "Element is not part of any list");
150  return -1;
151  }
152 
153  /* unlink from previous */
154  if (el->prevElement)
155  el->prevElement->nextElement=el->nextElement;
156 
157  /* unlink from next */
158  if (el->nextElement)
159  el->nextElement->prevElement=el->prevElement;
160 
161  /* unlink from list */
162  if (l->firstElement==el)
163  l->firstElement=el->nextElement;
164  if (l->lastElement==el)
165  l->lastElement=el->prevElement;
166  l->count--;
167 
168  el->nextElement=0;
169  el->prevElement=0;
170  el->listPtr=0;
171 
172  return 0;
173 }
174 
175 
176 
178 {
179  if (l->firstElement)
180  return l->firstElement->data;
181  return 0;
182 }
183 
184 
185 
187 {
188  if (l->lastElement)
189  return l->lastElement->data;
190  return 0;
191 }
192 
193 
194 
195 
196 
197 
199 {
200  GWEN_LIST1_ELEMENT *el;
201 
203  el->data=d;
204 
205  return el;
206 }
207 
208 
209 
211 {
212  if (el) {
213  if (el->listPtr)
214  GWEN_List1_Del(el);
215  GWEN_FREE_OBJECT(el);
216  }
217 }
218 
219 
220 
222 {
223  return el->data;
224 }
225 
226 
227 
229 {
230  if (el->prevElement)
231  return el->prevElement->data;
232  return 0;
233 }
234 
235 
236 
238 {
239  if (el->nextElement)
240  return el->nextElement->data;
241  return 0;
242 }
243 
244 
245 
246 #if 0
247 static int GWEN_List1__compar_asc(const void *a, const void *b)
248 {
249  const GWEN_LIST1_ELEMENT *const *pse1 = a, * const * pse2 = b;
250  const GWEN_LIST1_ELEMENT *se1 = *pse1, *se2 = *pse2;
251 
252  return (se1->listPtr->sortFunction)(se1->data, se2->data, 1);
253 }
254 
255 
256 
257 static int GWEN_List1__compar_desc(const void *a, const void *b)
258 {
259  const GWEN_LIST1_ELEMENT *const *pse1 = a, * const * pse2 = b;
260  const GWEN_LIST1_ELEMENT *se1 = *pse1, *se2 = *pse2;
261 
262  return (se1->listPtr->sortFunction)(se1->data, se2->data, 0);
263 }
264 
265 
266 
268 {
269  GWEN_LIST1_SORT_FN oldFn;
270 
271  assert(l);
272  oldFn=l->sortFunction;
273  l->sortFunction=fn;
274  return oldFn;
275 }
276 
277 
278 
279 void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
280 {
281  GWEN_LIST1_ELEMENT **tmpEntries;
282  GWEN_LIST1_ELEMENT *sentry;
283  GWEN_LIST1_ELEMENT **psentry;
284  uint32_t count;
285  uint32_t i;
286 
287  if (l->count<1)
288  return;
289 
290  count=l->count;
291 
292  /* sort entries into a linear pointer list */
293  tmpEntries=(GWEN_LIST1_ELEMENT **)malloc((count+1)* sizeof(GWEN_LIST1_ELEMENT *));
294  assert(tmpEntries);
295  psentry=tmpEntries;
296 
297  sentry=l->firstElement;
298  while (sentry) {
299  GWEN_LIST1_ELEMENT *next;
300 
301  *(psentry++)=sentry;
302  next=sentry->nextElement;
303  sentry->prevElement=NULL;
304  sentry->nextElement=NULL;
305  sentry->listPtr=l;
306  sentry=next;
307  } /* while */
308  *psentry=NULL;
309 
310  /* clear list */
311  l->count=0;
312  l->firstElement=NULL;
313  l->lastElement=NULL;
314 
315  /* sort */
316  if (ascending)
317  qsort(tmpEntries, count, sizeof(GWEN_LIST1_ELEMENT *), GWEN_List1__compar_asc);
318  else
319  qsort(tmpEntries, count, sizeof(GWEN_LIST1_ELEMENT *), GWEN_List1__compar_desc);
320 
321  /* sort entries back into GWEN_LIST1 according to temporary list */
322  psentry=tmpEntries;
323  /* we use "<=count" because the list contains count+1 elements */
324  for (i=0; i<=count; i++) {
325  if (*psentry) {
326  (*psentry)->listPtr=NULL;
327  GWEN_List1_Add(l, *psentry);
328  }
329  psentry++;
330  } /* for */
331 
332  free(tmpEntries);
333 }
334 #endif
335 
336 
337 
338 
339 
340 
341 
342 
343 
344 /* -------------------------------------------------------------------------------------------------
345  * Sort
346  * -------------------------------------------------------------------------------------------------
347  */
348 
349 
350 static int GWEN_List1__compar(const void *a, const void *b)
351 {
352  const GWEN_LIST1_SORT_ELEM *const *pse1 = a, * const * pse2 = b;
353  const GWEN_LIST1_SORT_ELEM *se1 = *pse1, *se2 = *pse2;
354  const GWEN_LIST1_SORT_CTX *ctx=se1->context;
355 
356  const GWEN_LIST1_ELEMENT *e1=se1->element;
357  const GWEN_LIST1_ELEMENT *e2=se2->element;
358 
359  return (ctx->list->sortFunction)(e1->data, e2->data, ctx->param);
360 }
361 
362 
363 
365 {
366  GWEN_LIST1_SORT_FN oldFn;
367 
368  assert(l);
369  oldFn=l->sortFunction;
370  l->sortFunction=fn;
371  return oldFn;
372 }
373 
374 
375 
376 
377 
378 
379 
380 
381 
382 
383 
384 
385 GWEN_LIST1_SORT_CTX *GWEN_List1_SortCtx_new(GWEN_LIST1 *list, int param)
386 {
387  GWEN_LIST1_SORT_CTX *ctx;
388 
389  GWEN_NEW_OBJECT(GWEN_LIST1_SORT_CTX, ctx);
390  ctx->list=list;
391  ctx->param=param;
392  return ctx;
393 }
394 
395 
396 
397 void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
398 {
399  if (ctx) {
400  GWEN_FREE_OBJECT(ctx);
401  }
402 }
403 
404 
405 
406 GWEN_LIST1_SORT_ELEM *GWEN_List1_SortElem_new(GWEN_LIST1_SORT_CTX *ctx, GWEN_LIST1_ELEMENT *elem)
407 {
408  GWEN_LIST1_SORT_ELEM *e;
409 
410  GWEN_NEW_OBJECT(GWEN_LIST1_SORT_ELEM, e);
411  e->context=ctx;
412  e->element=elem;
413  return e;
414 }
415 
416 
417 
418 void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
419 {
420  if (e) {
421  GWEN_FREE_OBJECT(e);
422  }
423 }
424 
425 
426 
427 void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
428 {
429  GWEN_LIST1_SORT_ELEM **tmpEntries;
430  GWEN_LIST1_SORT_ELEM **psentry;
431  GWEN_LIST1_ELEMENT *sentry;
432  uint32_t count;
433  uint32_t i;
434  GWEN_LIST1_SORT_CTX *sortContext;
435 
436  if (l->count<1)
437  return;
438 
439  count=l->count;
440 
441  sortContext=GWEN_List1_SortCtx_new(l, ascending);
442 
443  /* sort entries into a linear pointer list */
444  tmpEntries=(GWEN_LIST1_SORT_ELEM **)malloc((count+1)* sizeof(GWEN_LIST1_SORT_ELEM *));
445  assert(tmpEntries);
446  psentry=tmpEntries;
447 
448  sentry=l->firstElement;
449  while (sentry) {
450  GWEN_LIST1_ELEMENT *next;
451  GWEN_LIST1_SORT_ELEM *se;
452 
453  se=GWEN_List1_SortElem_new(sortContext, sentry);
454  *(psentry++)=se;
455  next=sentry->nextElement;
456  sentry->prevElement=NULL;
457  sentry->nextElement=NULL;
458  sentry->listPtr=l;
459  sentry=next;
460  } /* while */
461  *psentry=NULL;
462 
463  /* clear list */
464  l->count=0;
465  l->firstElement=NULL;
466  l->lastElement=NULL;
467 
468  /* sort */
469  qsort(tmpEntries, count, sizeof(GWEN_LIST1_SORT_ELEM *), GWEN_List1__compar);
470 
471  /* sort entries back into GWEN_LIST1 according to temporary list */
472  psentry=tmpEntries;
473  /* we use "<=count" because the list contains count+1 elements */
474  for (i=0; i<=count; i++) {
475  GWEN_LIST1_SORT_ELEM *se;
476 
477  se=*psentry;
478  if (se) {
479  sentry=se->element;
480  sentry->listPtr=NULL;
481  GWEN_List1_Add(l, sentry);
483  *psentry=NULL;
484  }
485  psentry++;
486  } /* for */
487 
488  free(tmpEntries);
489  GWEN_List1_SortCtx_free(sortContext);
490 }
491 
492 
493 
494 
495 
496 
int GWEN_List1_Add(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:69
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:186
void * GWEN_List1_GetFirst(const GWEN_LIST1 *l)
Definition: list1.c:177
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#define NULL
Definition: binreloc.c:297
int GWEN_List1_Del(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:140
#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:42
void GWEN_List1Element_free(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:210
GWEN_LIST1_ELEMENT * GWEN_List1Element_new(void *d)
Definition: list1.c:198
static GWENHYWFAR_CB int GWEN_List1__defaultSortFn(const void *a, const void *b, int ascending)
Definition: list1.c:35
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:86
GWEN_LIST1_SORT_FN GWEN_List1_SetSortFn(GWEN_LIST1 *l, GWEN_LIST1_SORT_FN fn)
Definition: list1.c:364
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
Definition: list1.c:397
int GWEN_List1_AddList(GWEN_LIST1 *dest, GWEN_LIST1 *l)
Definition: list1.c:96
void GWEN_List1_free(GWEN_LIST1 *l)
Definition: list1.c:52
void * GWEN_List1Element_GetPrevious(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:228
void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
Definition: list1.c:418
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:350
GWEN_LIST1_SORT_ELEM * GWEN_List1_SortElem_new(GWEN_LIST1_SORT_CTX *ctx, GWEN_LIST1_ELEMENT *elem)
Definition: list1.c:406
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
Definition: list1.c:427
int GWEN_List1_Insert(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:113
void * GWEN_List1Element_GetNext(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:237
GWEN_LIST1_SORT_CTX * GWEN_List1_SortCtx_new(GWEN_LIST1 *list, int param)
Definition: list1.c:385
void * GWEN_List1Element_GetData(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:221
int GWEN_List1_GetCount(const GWEN_LIST1 *l)
Definition: list1.c:61