/[zanavi_public1]/navit/navit/maptool/libcfu-0.03-zanavi/src/cfulist.c
ZANavi

Contents of /navit/navit/maptool/libcfu-0.03-zanavi/src/cfulist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 2 months ago) by zoff99
File MIME type: text/plain
File size: 11831 byte(s)
new map version, lots of fixes and experimental new features
1 /* Creation date: 2005-07-02 22:25:39
2 * Authors: Don
3 * Change log:
4 */
5
6 /* Copyright (c) 2005 Don Owens
7 All rights reserved.
8
9 This code is released under the BSD license:
10
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
13 are met:
14
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the following
20 disclaimer in the documentation and/or other materials provided
21 with the distribution.
22
23 * Neither the name of the author nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38 OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include "cfu.h"
42
43 #include <stdlib.h>
44
45 #include "cfulist.h"
46 #include "cfustring.h"
47
48 #ifdef CFU_DEBUG
49 #ifdef NDEBUG
50 #undef NDEBUG
51 #endif
52 #else
53 #ifndef NDEBUG
54 #define NDEBUG 1
55 #endif
56 #endif
57 #include <assert.h>
58
59 typedef struct cfulist_entry {
60 void *data;
61 size_t data_size;
62 struct cfulist_entry *next;
63 struct cfulist_entry *prev;
64 } cfulist_entry;
65
66 struct cfulist {
67 libcfu_type type;
68 cfulist_entry *entries;
69 cfulist_entry *tail;
70 size_t num_entries;
71 pthread_mutex_t mutex;
72 cfulist_entry *each_ptr;
73 cfulist_free_fn_t free_fn;
74 };
75
76 extern cfulist_t *
77 cfulist_new() {
78 cfulist_t *list = (cfulist_t *)calloc(1, sizeof(cfulist_t));
79 pthread_mutex_init(&list->mutex, NULL);
80 list->type = libcfu_t_list;
81 return list;
82 }
83
84 extern cfulist_t *
85 cfulist_new_with_free_fn(cfulist_free_fn_t free_fn) {
86 cfulist_t *list = cfulist_new();
87 list->free_fn = free_fn;
88 return list;
89 }
90
91 extern size_t
92 cfulist_num_entries(cfulist_t *list) {
93 return list->num_entries;
94 }
95
96 static inline void
97 lock_list(cfulist_t *list) {
98 pthread_mutex_lock(&list->mutex);
99 }
100
101 static inline void
102 unlock_list(cfulist_t *list) {
103 pthread_mutex_unlock(&list->mutex);
104 }
105
106 static inline cfulist_entry *
107 new_list_entry() {
108 return (cfulist_entry *)calloc(1, sizeof(cfulist_entry));
109 }
110
111 extern int
112 cfulist_push_data(cfulist_t *list, void *data, size_t data_size) {
113 cfulist_entry *entry = new_list_entry();
114 if (!entry) return 0;
115
116 if (data_size == (size_t)-1) data_size = strlen((char *)data) + 1;
117
118 entry->data = data;
119 entry->data_size = data_size;
120
121 lock_list(list);
122
123 if (list->tail) {
124 entry->prev = list->tail;
125 list->tail->next = entry;
126 list->tail = entry;
127 } else {
128 list->tail = list->entries = entry;
129 }
130 list->num_entries++;
131
132 unlock_list(list);
133
134 return 1;
135 }
136
137 extern int
138 cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size) {
139 if (!list) {
140 *data = NULL;
141 *data_size = 0;
142 return 0;
143 }
144 lock_list(list);
145
146 if (list->tail) {
147 if (list->tail->prev) {
148 cfulist_entry *new_tail = list->tail->prev;
149 assert(list->num_entries > 1);
150 new_tail->next = NULL;
151 *data = list->tail->data;
152 if (data_size) *data_size = list->tail->data_size;
153 free(list->tail);
154 list->tail = new_tail;
155 } else {
156 /* there is only one entry in the list */
157 assert(list->num_entries == 1);
158 *data = list->tail->data;
159 if (data_size) *data_size = list->tail->data_size;
160 free(list->tail);
161 list->tail = NULL;
162 list->entries = NULL;
163 }
164 list->num_entries--;
165 unlock_list(list);
166 return 1;
167 }
168
169 unlock_list(list);
170
171 if (data_size) *data_size = 0;
172 return 0;
173 }
174
175 extern int
176 cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size) {
177 cfulist_entry *entry = new_list_entry();
178 if (!entry) return 0;
179
180 if (data_size == (size_t)-1) data_size = strlen((char *)data) + 1;
181
182 entry->data = data;
183 entry->data_size = data_size;
184
185 lock_list(list);
186
187 if (list->entries) {
188 entry->next = list->entries;
189 list->entries->prev = entry;
190 list->entries = entry;
191 } else {
192 list->tail = list->entries = entry;
193 }
194 list->num_entries++;
195
196 unlock_list(list);
197
198 return 1;
199 }
200
201 extern int
202 cfulist_shift_data(cfulist_t *list, void **data, size_t *data_size) {
203 int rv = 0;
204 if (!list) {
205 if (data_size) *data_size = 0;
206 *data = NULL;
207 return rv;
208 }
209
210 lock_list(list);
211
212 if (list->entries) {
213 cfulist_entry *entry = list->entries;
214 assert(list->num_entries >= 1);
215 rv = 1;
216 *data = entry->data;
217 if (data_size) *data_size = entry->data_size;
218 if (entry->next) {
219 assert(list->num_entries > 1);
220 list->entries = entry->next;
221 list->entries->prev = NULL;
222 } else {
223 assert(list->num_entries == 1);
224 list->tail = NULL;
225 list->entries = NULL;
226 }
227 free(entry);
228 list->num_entries--;
229 } else {
230 assert(list->num_entries == 0);
231 rv = 0;
232 if (data_size) *data_size = 0;
233 *data = NULL;
234 }
235
236 unlock_list(list);
237 return rv;
238 }
239
240 extern int
241 cfulist_enqueue_data(cfulist_t *list, void *data, size_t data_size) {
242 return cfulist_push_data(list, data, data_size);
243 }
244
245
246 extern int
247 cfulist_dequeue_data(cfulist_t *list, void **data, size_t *data_size) {
248 return cfulist_shift_data(list, data, data_size);
249 }
250
251 extern int
252 cfulist_first_data(cfulist_t *list, void **data, size_t *data_size) {
253 int rv = 0;
254 if (!list) {
255 return 0;
256 }
257
258 lock_list(list);
259 if (list->entries) {
260 rv = 1;
261 *data = list->entries->data;
262 if (data_size) *data_size = list->entries->data_size;
263 } else {
264 rv = 0;
265 *data = NULL;
266 *data_size = 0;
267 }
268 unlock_list(list);
269
270 return rv;
271 }
272
273 extern int
274 cfulist_last_data(cfulist_t *list, void **data, size_t *data_size) {
275 int rv = 0;
276 if (!list) {
277 return 0;
278 }
279
280 lock_list(list);
281 if (list->tail) {
282 rv = 1;
283 *data = list->tail->data;
284 if (data_size) *data_size = list->tail->data_size;
285 } else {
286 rv = 0;
287 *data = NULL;
288 *data_size = 0;
289 }
290 unlock_list(list);
291
292 return rv;
293 }
294
295 extern int
296 cfulist_nth_data(cfulist_t *list, void **data, size_t *data_size, size_t n) {
297 int rv = 0;
298 size_t i = 0;
299 cfulist_entry *ptr = NULL;
300
301 if (!list) {
302 return 0;
303 }
304
305 lock_list(list);
306 if (list->entries) {
307 for (i = 0, ptr = list->entries; ptr && i < n; i++, ptr = ptr->next);
308 if (ptr && i == n) {
309 rv = 1;
310 *data = ptr->data;
311 if (data_size) *data_size = list->entries->data_size;
312 }
313 } else {
314 rv = 0;
315 *data = NULL;
316 *data_size = 0;
317 }
318 unlock_list(list);
319
320 return rv;
321 }
322
323 extern void
324 cfulist_reset_each(cfulist_t *list) {
325 if (!list) return;
326 list->each_ptr = list->entries;
327 }
328
329 extern int
330 cfulist_each_data(cfulist_t *list, void **data, size_t *data_size) {
331 if (!list) return 0;
332 cfulist_reset_each(list);
333 return cfulist_next_data(list, data, data_size);
334 }
335
336 extern int
337 cfulist_next_data(cfulist_t *list, void **data, size_t *data_size) {
338 if (!list) return 0;
339 *data = NULL;
340 if (list->each_ptr) {
341 *data = list->each_ptr->data;
342 *data_size = list->each_ptr->data_size;
343 list->each_ptr = list->each_ptr->next;
344 return 1;
345 }
346 return 0;
347 }
348
349 extern size_t
350 cfulist_foreach(cfulist_t *list, cfulist_foreach_fn_t fe_fn, void *arg) {
351 cfulist_entry *entry = NULL;
352 size_t num_processed = 0;
353 int rv = 0;
354
355 if (!list) return 0;
356
357 lock_list(list);
358 for (entry = list->entries; entry && !rv; entry = entry->next) {
359 rv = fe_fn(entry->data, entry->data_size, arg);
360 num_processed++;
361 }
362
363 unlock_list(list);
364
365 return num_processed;
366 }
367
368 typedef struct _cfulist_map_struct {
369 cfulist_t *list;
370 void *arg;
371 cfulist_map_fn_t map_fn;
372 } _cfulist_map_ds;
373
374 static int
375 _cfulist_map_foreach(void *data, size_t data_size, void *arg) {
376 _cfulist_map_ds *ds = (_cfulist_map_ds *)arg;
377 size_t new_data_size = 0;
378 void *rv = ds->map_fn(data, data_size, ds->arg, &new_data_size);
379 cfulist_push_data(ds->list, rv, new_data_size);
380 return 0;
381 }
382
383 extern cfulist_t *
384 cfulist_map(cfulist_t *list, cfulist_map_fn_t map_fn, void *arg) {
385 cfulist_t *new_list = cfulist_new();
386 _cfulist_map_ds ds;
387 ds.list = new_list;
388 ds.arg = arg;
389 ds.map_fn = map_fn;
390
391 cfulist_foreach(list, _cfulist_map_foreach, (void *)&ds);
392 return new_list;
393 }
394
395 /* For when you don't care about the data size */
396
397 extern int
398 cfulist_push(cfulist_t *list, void *data) {
399 return cfulist_push_data(list, data, 0);
400 }
401
402 extern void *
403 cfulist_pop(cfulist_t *list) {
404 void *data = NULL;
405 if (cfulist_pop_data(list, &data, NULL)) {
406 return data;
407 }
408 return NULL;
409 }
410
411 extern int
412 cfulist_unshift(cfulist_t *list, void *data) {
413 return cfulist_unshift_data(list, data, 0);
414 }
415
416 extern void *
417 cfulist_shift(cfulist_t *list) {
418 void *data = NULL;
419 if (cfulist_shift_data(list, &data, NULL)) {
420 return data;
421 }
422 return NULL;
423 }
424
425 extern int
426 cfulist_enqueue(cfulist_t *list, void *data) {
427 return cfulist_push(list, data);
428 }
429
430 extern void *
431 cfulist_dequeue(cfulist_t *list) {
432 return cfulist_shift(list);
433 }
434
435 /* Dealing with strings */
436
437 extern int
438 cfulist_push_string(cfulist_t *list, char *data) {
439 return cfulist_push_data(list, (void *)data, -1);
440 }
441
442 extern char *
443 cfulist_pop_string(cfulist_t *list) {
444 void *data = NULL;
445 if (cfulist_pop_data(list, &data, NULL)) {
446 return (char *)data;
447 }
448 return NULL;
449 }
450
451 extern int
452 cfulist_unshift_string(cfulist_t *list, char *data) {
453 return cfulist_unshift_data(list, (void *)data, -1);
454 }
455
456 extern char *
457 cfulist_shift_string(cfulist_t *list) {
458 void *data = NULL;
459 if (cfulist_shift_data(list, &data, NULL)) {
460 return (char *)data;
461 }
462 return NULL;
463 }
464
465 extern int
466 cfulist_enqueue_string(cfulist_t *list, char *data) {
467 return cfulist_push_string(list, data);
468 }
469
470 extern char *
471 cfulist_dequeue_string(cfulist_t *list) {
472 return cfulist_shift_string(list);
473 }
474
475 typedef struct _join_foreach_struct {
476 size_t count;
477 const char *delimiter;
478 cfustring_t *string;
479 } _join_foreach_struct;
480
481 static int
482 _join_foreach_fn(void *data, size_t data_size, void *arg) {
483 _join_foreach_struct *stuff = (_join_foreach_struct *)arg;
484
485 data_size = data_size;
486 if (stuff->count) cfustring_append(stuff->string, stuff->delimiter);
487 stuff->count++;
488 cfustring_append(stuff->string, (char *)data);
489 return 0;
490 }
491
492 extern char *
493 cfulist_join(cfulist_t *list, const char *delimiter) {
494 _join_foreach_struct *arg = (_join_foreach_struct *)calloc(1, sizeof(_join_foreach_struct));
495 char *str = NULL;
496
497 arg->delimiter = delimiter;
498 arg->string = cfustring_new();
499 cfulist_foreach(list, _join_foreach_fn, (void *)arg);
500
501 str = cfustring_get_buffer_copy(arg->string);
502 cfustring_destroy(arg->string);
503 free(arg);
504
505 return str;
506 }
507
508 extern void
509 cfulist_destroy(cfulist_t *list) {
510 if (!list) return;
511
512 if (list->free_fn) {
513 cfulist_destroy_with_free_fn(list, list->free_fn);
514 return;
515 }
516
517 lock_list(list);
518 if (list->entries) {
519 cfulist_entry *entry = NULL;
520 cfulist_entry *tmp = NULL;
521 entry = list->entries;
522 while (entry) {
523 tmp = entry->next;
524 free(entry);
525 entry = tmp;
526 }
527 }
528 unlock_list(list);
529 pthread_mutex_destroy(&list->mutex);
530 free(list);
531 }
532
533 extern void
534 cfulist_destroy_with_free_fn(cfulist_t *list, cfulist_free_fn_t free_fn) {
535 if (!list) return;
536
537 lock_list(list);
538 if (list->entries) {
539 cfulist_entry *entry = NULL;
540 cfulist_entry *tmp = NULL;
541 entry = list->entries;
542 while (entry) {
543 tmp = entry->next;
544 if (free_fn) free_fn(entry->data);
545 free(entry);
546 entry = tmp;
547 }
548 }
549 unlock_list(list);
550 pthread_mutex_destroy(&list->mutex);
551 free(list);
552 }

   
Visit the ZANavi Wiki