Freeciv-3.2
Loading...
Searching...
No Matches
genlist.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdlib.h>
19
20/* utility */
21#include "fcthread.h"
22#include "log.h"
23#include "mem.h"
24#include "shared.h" /* array_shuffle */
25
26#include "genlist.h"
27
28/************************************************************************/
31struct genlist *genlist_new(void)
32{
33 return genlist_new_full(NULL);
34}
35
36/************************************************************************/
40{
41 struct genlist *pgenlist = fc_calloc(1, sizeof(*pgenlist));
42
43#ifdef ZERO_VARIABLES_FOR_SEARCHING
44 pgenlist->nelements = 0;
45 pgenlist->head_link = NULL;
46 pgenlist->tail_link = NULL;
47#endif /* ZERO_VARIABLES_FOR_SEARCHING */
48 fc_mutex_init(&pgenlist->mutex);
49 pgenlist->free_data_func = free_data_func;
50
51 return pgenlist;
52}
53
54/************************************************************************/
58{
59 if (pgenlist == NULL) {
60 return;
61 }
62
66}
67
68/************************************************************************/
71static void genlist_link_new(struct genlist *pgenlist, void *dataptr,
72 struct genlist_link *prev,
73 struct genlist_link *next)
74{
75 struct genlist_link *plink = fc_malloc(sizeof(*plink));
76
77 plink->dataptr = dataptr;
78 plink->prev = prev;
79 if (NULL != prev) {
80 prev->next = plink;
81 } else {
82 pgenlist->head_link = plink;
83 }
84 plink->next = next;
85 if (NULL != next) {
86 next->prev = plink;
87 } else {
88 pgenlist->tail_link = plink;
89 }
90 pgenlist->nelements++;
91}
92
93/************************************************************************/
97 struct genlist_link *plink)
98{
99 if (pgenlist->head_link == plink) {
100 pgenlist->head_link = plink->next;
101 } else {
102 plink->prev->next = plink->next;
103 }
104
105 if (pgenlist->tail_link == plink) {
106 pgenlist->tail_link = plink->prev;
107 } else {
108 plink->next->prev = plink->prev;
109 }
110
111 pgenlist->nelements--;
112
113 /* NB: detach the link before calling the free function for avoiding
114 * re-entrant code. */
115 if (NULL != pgenlist->free_data_func) {
116 pgenlist->free_data_func(plink->dataptr);
117 }
118 free(plink);
119}
120
121/************************************************************************/
127static struct genlist_link *
129{
130 struct genlist_link *plink;
131
132 if (pos == 0) {
133 return pgenlist->head_link;
134 } else if (pos == -1) {
135 return pgenlist->tail_link;
136 } else if (pos < -1 || pos >= pgenlist->nelements) {
137 return NULL;
138 }
139
140 if (pos < pgenlist->nelements / 2) { /* fastest to do forward search */
141 for (plink = pgenlist->head_link; pos != 0; pos--) {
142 plink = plink->next;
143 }
144 } else { /* fastest to do backward search */
145 for (plink = pgenlist->tail_link, pos = pgenlist->nelements-pos - 1;
146 pos != 0; pos--) {
147 plink = plink->prev;
148 }
149 }
150
151 return plink;
152}
153
154/************************************************************************/
157struct genlist *genlist_copy(const struct genlist *pgenlist)
158{
159 return genlist_copy_full(pgenlist, NULL, pgenlist->free_data_func);
160}
161
162/************************************************************************/
168{
170
171 if (pgenlist) {
172 struct genlist_link *plink;
173
174 if (NULL != copy_data_func) {
175 for (plink = pgenlist->head_link; plink; plink = plink->next) {
177 pcopy->tail_link, NULL);
178 }
179 } else {
180 for (plink = pgenlist->head_link; plink; plink = plink->next) {
181 genlist_link_new(pcopy, plink->dataptr, pcopy->tail_link, NULL);
182 }
183 }
184 }
185
186 return pcopy;
187}
188
189/************************************************************************/
192int genlist_size(const struct genlist *pgenlist)
193{
195 return pgenlist->nelements;
196}
197
198/************************************************************************/
203struct genlist_link *genlist_link_get(const struct genlist *pgenlist, int idx)
204{
206
207 return genlist_link_at_pos(pgenlist, idx);
208}
209
210/************************************************************************/
214{
215 return (NULL != pgenlist ? pgenlist->tail_link : NULL);
216}
217
218/************************************************************************/
224void *genlist_get(const struct genlist *pgenlist, int idx)
225{
227}
228
229/************************************************************************/
232void *genlist_front(const struct genlist *pgenlist)
233{
235}
236
237/************************************************************************/
240void *genlist_back(const struct genlist *pgenlist)
241{
243}
244
245/************************************************************************/
251{
253
254 if (0 < pgenlist->nelements) {
255 genlist_free_fn_t free_data_func = pgenlist->free_data_func;
256 struct genlist_link *plink = pgenlist->head_link, *plink2;
257
258 pgenlist->head_link = NULL;
259 pgenlist->tail_link = NULL;
260
261 pgenlist->nelements = 0;
262
263 if (NULL != free_data_func) {
264 do {
265 plink2 = plink->next;
266 free_data_func(plink->dataptr);
267 free(plink);
268 } while (NULL != (plink = plink2));
269 } else {
270 do {
271 plink2 = plink->next;
272 free(plink);
273 } while (NULL != (plink = plink2));
274 }
275 }
276}
277
278/************************************************************************/
286
287/************************************************************************/
294{
296
297 if (2 <= pgenlist->nelements) {
298 struct genlist_link *plink = pgenlist->head_link, *plink2;
299
300 if (NULL != comp_data_func) {
301 do {
302 plink2 = plink->next;
303 if (NULL != plink2 && comp_data_func(plink->dataptr,
304 plink2->dataptr)) {
305 /* Remove this element. */
307 }
308 } while ((plink = plink2) != NULL);
309 } else {
310 do {
311 plink2 = plink->next;
312 if (NULL != plink2 && plink->dataptr == plink2->dataptr) {
313 /* Remove this element. */
315 }
316 } while ((plink = plink2) != NULL);
317 }
318 }
319}
320
321/************************************************************************/
329bool genlist_remove(struct genlist *pgenlist, const void *punlink)
330{
331 struct genlist_link *plink;
332
334
335 for (plink = pgenlist->head_link; NULL != plink; plink = plink->next) {
336 if (plink->dataptr == punlink) {
338 return TRUE;
339 }
340 }
341
342 return FALSE;
343}
344
345/************************************************************************/
352{
353 struct genlist_link *plink;
354 int count = 0;
355
357
358 for (plink = pgenlist->head_link; NULL != plink;) {
359 if (plink->dataptr == punlink) {
360 struct genlist_link *pnext = plink->next;
361
363 count++;
364 plink = pnext;
365 } else {
366 plink = plink->next;
367 }
368 }
369
370 return count;
371}
372
373/************************************************************************/
381{
383
384 if (NULL != cond_data_func) {
385 struct genlist_link *plink = pgenlist->head_link;
386
387 for (; NULL != plink; plink = plink->next) {
388 if (cond_data_func(plink->dataptr)) {
390 return TRUE;
391 }
392 }
393 }
394
395 return FALSE;
396}
397
398/************************************************************************/
406{
408
409 if (NULL != cond_data_func) {
410 struct genlist_link *plink = pgenlist->head_link;
411 int count = 0;
412
413 while (NULL != plink) {
414 if (cond_data_func(plink->dataptr)) {
415 struct genlist_link *pnext = plink->next;
416
418 count++;
419 plink = pnext;
420 } else {
421 plink = plink->next;
422 }
423 }
424 return count;
425 }
426
427 return 0;
428}
429
430/************************************************************************/
436void genlist_erase(struct genlist *pgenlist, struct genlist_link *plink)
437{
439
440 if (NULL != plink) {
442 }
443}
444
445/************************************************************************/
449{
451
452 if (NULL != pgenlist->head_link) {
454 }
455}
456
457/************************************************************************/
461{
463
464 if (NULL != pgenlist->tail_link) {
466 }
467}
468
469/************************************************************************/
477void genlist_insert(struct genlist *pgenlist, void *data, int pos)
478{
480
481 if (0 == pgenlist->nelements) {
482 /* List is empty, ignore pos. */
484 } else if (0 == pos) {
485 /* Prepend. */
486 genlist_link_new(pgenlist, data, NULL, pgenlist->head_link);
487 } else if (-1 >= pos || pos >= pgenlist->nelements) {
488 /* Append. */
489 genlist_link_new(pgenlist, data, pgenlist->tail_link, NULL);
490 } else {
491 /* Insert before plink. */
493
494 fc_assert_ret(NULL != plink);
495 genlist_link_new(pgenlist, data, plink->prev, plink);
496 }
497}
498
499/************************************************************************/
502void genlist_insert_after(struct genlist *pgenlist, void *data,
503 struct genlist_link *plink)
504{
506
507 genlist_link_new(pgenlist, data, plink,
508 NULL != plink ? plink->next : pgenlist->head_link);
509}
510
511/************************************************************************/
514void genlist_insert_before(struct genlist *pgenlist, void *data,
515 struct genlist_link *plink)
516{
518
520 NULL != plink ? plink->prev : pgenlist->tail_link, plink);
521}
522
523/************************************************************************/
526void genlist_prepend(struct genlist *pgenlist, void *data)
527{
529
530 genlist_link_new(pgenlist, data, NULL, pgenlist->head_link);
531}
532
533/************************************************************************/
536void genlist_append(struct genlist *pgenlist, void *data)
537{
539
540 genlist_link_new(pgenlist, data, pgenlist->tail_link, NULL);
541}
542
543/************************************************************************/
549 const void *data)
550{
551 struct genlist_link *plink;
552
554
555 for (plink = pgenlist->head_link; plink; plink = plink->next) {
556 if (plink->dataptr == data) {
557 return plink;
558 }
559 }
560
561 return NULL;
562}
563
564/************************************************************************/
570{
572
573 if (NULL != cond_data_func) {
574 struct genlist_link *plink = pgenlist->head_link;
575
576 for (; NULL != plink; plink = plink->next) {
577 if (cond_data_func(plink->dataptr)) {
578 return plink;
579 }
580 }
581 }
582
583 return NULL;
584}
585
586/************************************************************************/
598 int (*compar) (const void *, const void *))
599{
600 const size_t n = genlist_size(pgenlist);
601 void **sortbuf;
602 struct genlist_link *myiter;
603 unsigned int i;
604
605 if (n <= 1) {
606 return;
607 }
608
609 sortbuf = fc_malloc(n * sizeof(void *));
611 for (i = 0; i < n; i++, myiter = myiter->next) {
612 sortbuf[i] = myiter->dataptr;
613 }
614
615 qsort(sortbuf, n, sizeof(*sortbuf), compar);
616
618 for (i = 0; i < n; i++, myiter = myiter->next) {
619 myiter->dataptr = sortbuf[i];
620 }
622}
623
624/************************************************************************/
630{
631 const int n = genlist_size(pgenlist);
632
633 if (n > 1) {
634 void *sortbuf[n];
635 struct genlist_link *myiter;
636 int i, shuffle[n];
637
639 for (i = 0; i < n; i++, myiter = myiter->next) {
640 sortbuf[i] = myiter->dataptr;
641 /* Also create the shuffle list */
642 shuffle[i] = i;
643 }
644
645 /* Randomize it */
647
648 /* Create the shuffled list */
650 for (i = 0; i < n; i++, myiter = myiter->next) {
651 myiter->dataptr = sortbuf[shuffle[i]];
652 }
653 }
654}
655
656/************************************************************************/
660{
661 struct genlist_link *head, *tail;
662 int counter;
663
665
666 head = pgenlist->head_link;
667 tail = pgenlist->tail_link;
668 for (counter = pgenlist->nelements / 2; 0 < counter; counter--) {
669 /* Swap. */
670 void *temp = head->dataptr;
671 head->dataptr = tail->dataptr;
672 tail->dataptr = temp;
673
674 head = head->next;
675 tail = tail->prev;
676 }
677}
678
679/************************************************************************/
686
687/************************************************************************/
691{
692 fc_mutex_release(&pgenlist->mutex);
693}
#define n
Definition astring.c:77
char * incite_cost
Definition comments.c:75
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_init(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
void fc_mutex_destroy(fc_mutex *mutex)
bool genlist_remove(struct genlist *pgenlist, const void *punlink)
Definition genlist.c:329
void genlist_allocate_mutex(struct genlist *pgenlist)
Definition genlist.c:682
void genlist_insert(struct genlist *pgenlist, void *data, int pos)
Definition genlist.c:477
struct genlist * genlist_copy_full(const struct genlist *pgenlist, genlist_copy_fn_t copy_data_func, genlist_free_fn_t free_data_func)
Definition genlist.c:165
void genlist_release_mutex(struct genlist *pgenlist)
Definition genlist.c:690
struct genlist * genlist_new(void)
Definition genlist.c:31
void * genlist_get(const struct genlist *pgenlist, int idx)
Definition genlist.c:224
int genlist_remove_all(struct genlist *pgenlist, const void *punlink)
Definition genlist.c:351
void genlist_erase(struct genlist *pgenlist, struct genlist_link *plink)
Definition genlist.c:436
struct genlist_link * genlist_search_if(const struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Definition genlist.c:568
void genlist_clear(struct genlist *pgenlist)
Definition genlist.c:250
void genlist_prepend(struct genlist *pgenlist, void *data)
Definition genlist.c:526
bool genlist_remove_if(struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Definition genlist.c:379
void genlist_append(struct genlist *pgenlist, void *data)
Definition genlist.c:536
void genlist_unique_full(struct genlist *pgenlist, genlist_comp_fn_t comp_data_func)
Definition genlist.c:292
static struct genlist_link * genlist_link_at_pos(const struct genlist *pgenlist, int pos)
Definition genlist.c:128
static void genlist_link_new(struct genlist *pgenlist, void *dataptr, struct genlist_link *prev, struct genlist_link *next)
Definition genlist.c:71
struct genlist * genlist_copy(const struct genlist *pgenlist)
Definition genlist.c:157
void genlist_destroy(struct genlist *pgenlist)
Definition genlist.c:57
void genlist_pop_front(struct genlist *pgenlist)
Definition genlist.c:448
void genlist_insert_before(struct genlist *pgenlist, void *data, struct genlist_link *plink)
Definition genlist.c:514
void * genlist_back(const struct genlist *pgenlist)
Definition genlist.c:240
int genlist_remove_all_if(struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Definition genlist.c:404
void genlist_unique(struct genlist *pgenlist)
Definition genlist.c:282
void genlist_insert_after(struct genlist *pgenlist, void *data, struct genlist_link *plink)
Definition genlist.c:502
void genlist_sort(struct genlist *pgenlist, int(*compar)(const void *, const void *))
Definition genlist.c:597
void genlist_reverse(struct genlist *pgenlist)
Definition genlist.c:659
struct genlist_link * genlist_tail(const struct genlist *pgenlist)
Definition genlist.c:213
void * genlist_front(const struct genlist *pgenlist)
Definition genlist.c:232
struct genlist * genlist_new_full(genlist_free_fn_t free_data_func)
Definition genlist.c:39
struct genlist_link * genlist_link_get(const struct genlist *pgenlist, int idx)
Definition genlist.c:203
void genlist_pop_back(struct genlist *pgenlist)
Definition genlist.c:460
struct genlist_link * genlist_search(const struct genlist *pgenlist, const void *data)
Definition genlist.c:548
int genlist_size(const struct genlist *pgenlist)
Definition genlist.c:192
void genlist_shuffle(struct genlist *pgenlist)
Definition genlist.c:629
static void genlist_link_destroy(struct genlist *pgenlist, struct genlist_link *plink)
Definition genlist.c:96
bool(* genlist_cond_fn_t)(const void *)
Definition genlist.h:53
bool(* genlist_comp_fn_t)(const void *, const void *)
Definition genlist.h:54
static struct genlist_link * genlist_head(const struct genlist *pgenlist)
Definition genlist.h:108
static void * genlist_link_data(const struct genlist_link *plink)
Definition genlist.h:140
void *(* genlist_copy_fn_t)(const void *)
Definition genlist.h:52
void(* genlist_free_fn_t)(void *)
Definition genlist.h:51
static struct tile * pos
Definition finddlg.c:53
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
void array_shuffle(int *array, int n)
Definition shared.c:2010
genlist_free_fn_t free_data_func
Definition genlist.h:64
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47