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
35static 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{
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);
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
248static 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
258static 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
280void 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
351static 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
386GWEN_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
398void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
399{
400 if (ctx) {
401 GWEN_FREE_OBJECT(ctx);
402 }
403}
404
405
406
407GWEN_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
419void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
420{
421 if (e) {
423 }
424}
425
426
427
428void 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
#define NULL
Definition: binreloc.c:300
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define GWEN_UNUSED
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
GWEN_LIST1 * GWEN_List1_new(void)
Definition: list1.c:43
void * GWEN_List1Element_GetPrevious(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:229
int GWEN_List1_Insert(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:114
void * GWEN_List1_GetFirst(const GWEN_LIST1 *l)
Definition: list1.c:178
int GWEN_List1_Add(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el)
Definition: list1.c:70
void GWEN_List1_SortCtx_free(GWEN_LIST1_SORT_CTX *ctx)
Definition: list1.c:398
void GWEN_List1_free(GWEN_LIST1 *l)
Definition: list1.c:53
int GWEN_List1_AddList(GWEN_LIST1 *dest, GWEN_LIST1 *l)
Definition: list1.c:97
int GWEN_List1_GetCount(const GWEN_LIST1 *l)
Definition: list1.c:62
int GWEN_List1_Del(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:141
void GWEN_List1_SortElem_free(GWEN_LIST1_SORT_ELEM *e)
Definition: list1.c:419
void * GWEN_List1_GetLast(const GWEN_LIST1 *l)
Definition: list1.c:187
GWEN_LIST1_SORT_FN GWEN_List1_SetSortFn(GWEN_LIST1 *l, GWEN_LIST1_SORT_FN fn)
Definition: list1.c:365
GWEN_LIST1_ELEMENT * GWEN_List1Element_new(void *d)
Definition: list1.c:199
static int GWEN_List1__compar(const void *a, const void *b)
Definition: list1.c:351
void * GWEN_List1Element_GetNext(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:238
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
void * GWEN_List1Element_GetData(const GWEN_LIST1_ELEMENT *el)
Definition: list1.c:222
void GWEN_List1Element_free(GWEN_LIST1_ELEMENT *el)
Definition: list1.c:211
void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending)
Definition: list1.c:428
GWEN_LIST1_SORT_CTX * GWEN_List1_SortCtx_new(GWEN_LIST1 *list, int param)
Definition: list1.c:386
GWEN_LIST1_SORT_ELEM * GWEN_List1_SortElem_new(GWEN_LIST1_SORT_CTX *ctx, GWEN_LIST1_ELEMENT *elem)
Definition: list1.c:407
int GWENHYWFAR_CB(* GWEN_LIST1_SORT_FN)(const void *a, const void *b, int ascending)
Definition: list1.h:158
struct GWEN_LIST1 GWEN_LIST1
Definition: list1.h:155
struct GWEN_LIST1_ELEMENT GWEN_LIST1_ELEMENT
Definition: list1.h:156
#define GWEN_LOGDOMAIN
Definition: logger.h:35
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55