1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / common tools sub-project
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/list.h>
27
28 /* GF_List modes, ONLY ONE CAN BE DEFINED
29
30 linked-list
31 #define GF_LIST_LINKED
32
33 double navigation linked-list
34 #define GF_LIST_DOUBLE_LINKED
35
36 single step memory array
37 #define GF_LIST_ARRAY
38
39 multi-step memory array withou gf_realloc on remove, using the GF_LIST_REALLOC macro
40 GF_LIST_ARRAY_GROW
41 */
42
43 /*after some tuning, this seems to be the fastest mode on WINCE*/
44 #ifdef _WIN32_WCE
45 #define GF_LIST_LINKED
46 #else
47 #define GF_LIST_ARRAY_GROW
48 #endif
49
50 #define GF_LIST_REALLOC(a) (a = a ? (3*a/2) : 10)
51 //#define GF_LIST_REALLOC(a) (a++)
52
53
54 #if defined(GF_LIST_LINKED)
55
56 typedef struct tagIS
57 {
58 struct tagIS *next;
59 void *data;
60 } ItemSlot;
61
62 struct _tag_array
63 {
64 struct tagIS *head;
65 struct tagIS *tail;
66 u32 entryCount;
67 s32 foundEntryNumber;
68 struct tagIS *foundEntry;
69 };
70
71
72 GF_EXPORT
gf_list_new()73 GF_List * gf_list_new()
74 {
75 GF_List *nlist = (GF_List *)gf_malloc(sizeof(GF_List));
76 if (!nlist) return NULL;
77 nlist->head = nlist->foundEntry = NULL;
78 nlist->tail = NULL;
79 nlist->foundEntryNumber = -1;
80 nlist->entryCount = 0;
81 return nlist;
82 }
83
84 GF_EXPORT
gf_list_del(GF_List * ptr)85 void gf_list_del(GF_List *ptr)
86 {
87 if (!ptr) return;
88 while (ptr->entryCount) gf_list_rem(ptr, 0);
89 gf_free(ptr);
90 }
91
92 GF_EXPORT
gf_list_reset(GF_List * ptr)93 void gf_list_reset(GF_List *ptr)
94 {
95 while (ptr && ptr->entryCount) gf_list_rem(ptr, 0);
96 }
97
98 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)99 GF_Err gf_list_add(GF_List *ptr, void* item)
100 {
101 ItemSlot *entry;
102 if (!ptr) return GF_BAD_PARAM;
103 entry = (ItemSlot *)gf_malloc(sizeof(ItemSlot));
104 if (!entry) return GF_OUT_OF_MEM;
105 entry->data = item;
106 entry->next = NULL;
107 if (!ptr->head) {
108 ptr->head = entry;
109 ptr->entryCount = 1;
110 }
111 else {
112 ptr->entryCount += 1;
113 ptr->tail->next = entry;
114 }
115 ptr->tail = entry;
116 ptr->foundEntryNumber = ptr->entryCount - 1;
117 ptr->foundEntry = entry;
118 return GF_OK;
119 }
120
121 GF_EXPORT
gf_list_count(const GF_List * ptr)122 u32 gf_list_count(const GF_List *ptr)
123 {
124 if (!ptr) return 0;
125 return ptr->entryCount;
126 }
127
128 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)129 void *gf_list_get(GF_List *ptr, u32 itemNumber)
130 {
131 ItemSlot *entry;
132 u32 i;
133
134 if (!ptr || (itemNumber >= ptr->entryCount)) return NULL;
135
136 if (!ptr->foundEntry || (itemNumber < (u32)ptr->foundEntryNumber)) {
137 ptr->foundEntryNumber = 0;
138 ptr->foundEntry = ptr->head;
139 }
140 entry = ptr->foundEntry;
141 for (i = ptr->foundEntryNumber; i < itemNumber; i++) {
142 entry = entry->next;
143 }
144 ptr->foundEntryNumber = itemNumber;
145 ptr->foundEntry = entry;
146 return (void *)entry->data;
147 }
148
149 GF_EXPORT
gf_list_last(GF_List * ptr)150 void *gf_list_last(GF_List *ptr)
151 {
152 ItemSlot *entry;
153 if (!ptr || !ptr->entryCount) return NULL;
154 entry = ptr->head;
155 while (entry->next) entry = entry->next;
156 return entry->data;
157 }
158
159 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)160 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
161 {
162 ItemSlot *tmp, *tmp2;
163 u32 i;
164
165 /* !! if head is null (empty list)*/
166 if ((!ptr) || (!ptr->head) || (ptr->head && !ptr->entryCount) || (itemNumber >= ptr->entryCount))
167 return GF_BAD_PARAM;
168
169 /*we delete the head*/
170 if (!itemNumber) {
171 tmp = ptr->head;
172 ptr->head = ptr->head->next;
173 ptr->entryCount--;
174 ptr->foundEntry = ptr->head;
175 ptr->foundEntryNumber = 0;
176 gf_free(tmp);
177 /*that was the last entry, reset the tail*/
178 if (!ptr->entryCount) {
179 ptr->tail = ptr->head = ptr->foundEntry = NULL;
180 ptr->foundEntryNumber = -1;
181 }
182 return GF_OK;
183 }
184
185 tmp = ptr->head;
186 i = 0;
187 while (i < itemNumber - 1) {
188 tmp = tmp->next;
189 i++;
190 }
191 tmp2 = tmp->next;
192 tmp->next = tmp2->next;
193 /*if we deleted the last entry, update the tail !!!*/
194 if (!tmp->next || (ptr->tail == tmp2)) {
195 ptr->tail = tmp;
196 tmp->next = NULL;
197 }
198
199 gf_free(tmp2);
200 ptr->entryCount--;
201 ptr->foundEntry = ptr->head;
202 ptr->foundEntryNumber = 0;
203
204 return GF_OK;
205 }
206
207 GF_EXPORT
gf_list_rem_last(GF_List * ptr)208 GF_Err gf_list_rem_last(GF_List *ptr)
209 {
210 return gf_list_rem(ptr, ptr->entryCount - 1);
211 }
212
213 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)214 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
215 {
216 u32 i;
217 ItemSlot *tmp, *tmp2;
218
219 if (!ptr || !item) return GF_BAD_PARAM;
220 /*if last entry or first of an empty array...*/
221 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
222
223 tmp2 = (ItemSlot *)gf_malloc(sizeof(ItemSlot));
224 tmp2->data = item;
225 tmp2->next = NULL;
226 /*special case for the head*/
227 if (position == 0) {
228 tmp2->next = ptr->head;
229 ptr->head = tmp2;
230 ptr->entryCount++;
231 ptr->foundEntry = tmp2;
232 ptr->foundEntryNumber = 0;
233 return GF_OK;
234 }
235 tmp = ptr->head;
236 for (i = 1; i < position; i++) {
237 tmp = tmp->next;
238 if (!tmp)
239 break;
240 }
241 tmp2->next = tmp->next;
242 tmp->next = tmp2;
243 ptr->entryCount++;
244 ptr->foundEntry = tmp2;
245 ptr->foundEntryNumber = i;
246 return GF_OK;
247 }
248
249 #elif defined(GF_LIST_DOUBLE_LINKED)
250
251
252 typedef struct tagIS
253 {
254 struct tagIS *next;
255 struct tagIS *prev;
256 void *data;
257 } ItemSlot;
258
259 struct _tag_array
260 {
261 struct tagIS *head;
262 struct tagIS *tail;
263 u32 entryCount;
264 s32 foundEntryNumber;
265 struct tagIS *foundEntry;
266 };
267
268
269 GF_EXPORT
gf_list_new()270 GF_List * gf_list_new()
271 {
272 GF_List *nlist = (GF_List *)gf_malloc(sizeof(GF_List));
273 if (!nlist) return NULL;
274 nlist->head = nlist->foundEntry = NULL;
275 nlist->tail = NULL;
276 nlist->foundEntryNumber = -1;
277 nlist->entryCount = 0;
278 return nlist;
279 }
280
281 GF_EXPORT
gf_list_del(GF_List * ptr)282 void gf_list_del(GF_List *ptr)
283 {
284 if (!ptr) return;
285 while (ptr->entryCount) {
286 gf_list_rem(ptr, 0);
287 }
288 gf_free(ptr);
289 }
290
291 GF_EXPORT
gf_list_reset(GF_List * ptr)292 void gf_list_reset(GF_List *ptr)
293 {
294 while (ptr && ptr->entryCount) gf_list_rem(ptr, 0);
295 }
296
297 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)298 GF_Err gf_list_add(GF_List *ptr, void* item)
299 {
300 ItemSlot *entry;
301 if (!ptr) return GF_BAD_PARAM;
302 entry = (ItemSlot *)gf_malloc(sizeof(ItemSlot));
303 if (!entry) return GF_OUT_OF_MEM;
304 entry->data = item;
305 entry->next = entry->prev = NULL;
306
307 if (!ptr->head) {
308 ptr->head = entry;
309 ptr->entryCount = 1;
310 }
311 else {
312 ptr->entryCount += 1;
313 entry->prev = ptr->tail;
314 ptr->tail->next = entry;
315 }
316 ptr->tail = entry;
317 ptr->foundEntryNumber = ptr->entryCount - 1;
318 ptr->foundEntry = entry;
319 return GF_OK;
320 }
321
322
323 GF_EXPORT
gf_list_count(GF_List * ptr)324 u32 gf_list_count(GF_List *ptr)
325 {
326 if (!ptr) return 0;
327 return ptr->entryCount;
328 }
329
330 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)331 void *gf_list_get(GF_List *ptr, u32 itemNumber)
332 {
333 ItemSlot *entry;
334 u32 i;
335
336 if (!ptr || !ptr->head || (itemNumber >= ptr->entryCount)) return NULL;
337
338 if (!itemNumber) {
339 ptr->foundEntry = ptr->head;
340 ptr->foundEntryNumber = 0;
341 return ptr->head->data;
342 }
343
344 entry = ptr->foundEntry;
345 if (itemNumber < (u32)ptr->foundEntryNumber) {
346 for (i = ptr->foundEntryNumber; i > itemNumber; i--) {
347 entry = entry->prev;
348 }
349 }
350 else {
351 for (i = ptr->foundEntryNumber; i < itemNumber; i++) {
352 entry = entry->next;
353 }
354 }
355 ptr->foundEntryNumber = itemNumber;
356 ptr->foundEntry = entry;
357 return (void *)entry->data;
358 }
359
360 GF_EXPORT
gf_list_last(GF_List * ptr)361 void *gf_list_last(GF_List *ptr)
362 {
363 if (!ptr || !ptr->tail) return NULL;
364 return ptr->tail->data;
365 }
366
367 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)368 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
369 {
370 ItemSlot *tmp;
371 u32 i;
372
373 /* !! if head is null (empty list)*/
374 if ((!ptr) || (!ptr->head) || (ptr->head && !ptr->entryCount) || (itemNumber >= ptr->entryCount))
375 return GF_BAD_PARAM;
376
377 /*we delete the head*/
378 if (!itemNumber) {
379 tmp = ptr->head;
380 ptr->head = ptr->head->next;
381
382 ptr->entryCount--;
383 ptr->foundEntry = ptr->head;
384 ptr->foundEntryNumber = 0;
385 gf_free(tmp);
386
387 /*that was the last entry, reset the tail*/
388 if (!ptr->entryCount) {
389 ptr->tail = ptr->head = ptr->foundEntry = NULL;
390 ptr->foundEntryNumber = -1;
391 }
392 else {
393 ptr->head->prev = NULL;
394 }
395 return GF_OK;
396 }
397 else if (itemNumber == ptr->entryCount - 1) {
398 tmp = ptr->tail;
399 ptr->tail = tmp->prev;
400 ptr->tail->next = NULL;
401 ptr->entryCount--;
402 if (ptr->foundEntry == tmp) {
403 ptr->foundEntry = ptr->tail;
404 ptr->foundEntryNumber = ptr->entryCount - 1;
405 }
406 gf_free(tmp);
407 return GF_OK;
408 }
409
410 tmp = ptr->foundEntry;
411 if (itemNumber < (u32)ptr->foundEntryNumber) {
412 for (i = ptr->foundEntryNumber; i > itemNumber; i--) {
413 tmp = tmp->prev;
414 }
415 }
416 else {
417 for (i = ptr->foundEntryNumber; i < itemNumber; i++) {
418 tmp = tmp->next;
419 }
420 }
421 tmp->prev->next = tmp->next;
422 tmp->next->prev = tmp->prev;
423 if (tmp == ptr->foundEntry) ptr->foundEntry = tmp->next;
424 gf_free(tmp);
425 ptr->entryCount--;
426 return GF_OK;
427 }
428
429 GF_EXPORT
gf_list_rem_last(GF_List * ptr)430 GF_Err gf_list_rem_last(GF_List *ptr)
431 {
432 return gf_list_rem(ptr, ptr->entryCount - 1);
433 }
434
435 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)436 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
437 {
438 u32 i;
439 ItemSlot *tmp, *tmp2;
440
441 if (!ptr || !item) return GF_BAD_PARAM;
442 /*if last entry or first of an empty array...*/
443 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
444 tmp2 = (ItemSlot *)gf_malloc(sizeof(ItemSlot));
445 tmp2->data = item;
446 tmp2->next = tmp2->prev = NULL;
447 /*special case for the head*/
448 if (position == 0) {
449 ptr->head->prev = tmp2;
450 tmp2->next = ptr->head;
451 ptr->head = tmp2;
452 ptr->entryCount++;
453 ptr->foundEntry = tmp2;
454 ptr->foundEntryNumber = 0;
455 return GF_OK;
456 }
457
458 tmp = ptr->foundEntry;
459 if (position < (u32)ptr->foundEntryNumber) {
460 for (i = ptr->foundEntryNumber; i >= position; i--) {
461 tmp = tmp->prev;
462 }
463 tmp = tmp->prev;
464 }
465 else {
466 for (i = ptr->foundEntryNumber; i < position; i++) {
467 tmp = tmp->next;
468 }
469 }
470 tmp2->next = tmp->next;
471 tmp2->next->prev = tmp2;
472 tmp2->prev = tmp;
473 tmp2->prev->next = tmp2;
474 ptr->entryCount++;
475 ptr->foundEntry = tmp2;
476 ptr->foundEntryNumber = position;
477 return GF_OK;
478 }
479
480 #elif defined(GF_LIST_ARRAY)
481
482 struct _tag_array
483 {
484 void **slots;
485 u32 entryCount;
486 };
487
488
489 GF_EXPORT
gf_list_new()490 GF_List * gf_list_new()
491 {
492 GF_List *nlist = (GF_List *)gf_malloc(sizeof(GF_List));
493 if (!nlist) return NULL;
494 nlist->slots = NULL;
495 nlist->entryCount = 0;
496 return nlist;
497 }
498
499 GF_EXPORT
gf_list_del(GF_List * ptr)500 void gf_list_del(GF_List *ptr)
501 {
502 if (!ptr) return;
503 gf_free(ptr->slots);
504 gf_free(ptr);
505 }
506
507 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)508 GF_Err gf_list_add(GF_List *ptr, void* item)
509 {
510 if (!ptr) return GF_BAD_PARAM;
511
512 ptr->entryCount++;
513 ptr->slots = (void **)gf_realloc(ptr->slots, ptr->entryCount * sizeof(void*));
514 if (!ptr->slots) {
515 ptr->entryCount = 0;
516 return GF_OUT_OF_MEM;
517 }
518 ptr->slots[ptr->entryCount - 1] = item;
519 return GF_OK;
520 }
521
522 GF_EXPORT
gf_list_count(GF_List * ptr)523 u32 gf_list_count(GF_List *ptr)
524 {
525 return ptr ? ptr->entryCount : 0;
526 }
527
528 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)529 void *gf_list_get(GF_List *ptr, u32 itemNumber)
530 {
531 if (!ptr || (itemNumber >= ptr->entryCount)) return NULL;
532 return ptr->slots[itemNumber];
533 }
534
535 GF_EXPORT
gf_list_last(GF_List * ptr)536 void *gf_list_last(GF_List *ptr)
537 {
538 if (!ptr || !ptr->entryCount) return NULL;
539 return ptr->slots[ptr->entryCount - 1];
540 }
541
542
543 /*WARNING: itemNumber is from 0 to entryCount - 1*/
544 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)545 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
546 {
547 u32 i;
548 if (!ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
549 i = ptr->entryCount - itemNumber - 1;
550 if (i) memmove(&ptr->slots[itemNumber], &ptr->slots[itemNumber + 1], sizeof(void *)*i);
551 ptr->slots[ptr->entryCount - 1] = NULL;
552 ptr->entryCount -= 1;
553 ptr->slots = (void **)gf_realloc(ptr->slots, sizeof(void*)*ptr->entryCount);
554 return GF_OK;
555 }
556
557 GF_EXPORT
gf_list_rem_last(GF_List * ptr)558 GF_Err gf_list_rem_last(GF_List *ptr)
559 {
560 if (!ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
561 ptr->entryCount -= 1;
562 ptr->slots = (void **)gf_realloc(ptr->slots, sizeof(void*)*ptr->entryCount);
563 return GF_OK;
564 }
565
566
567 /*WARNING: position is from 0 to entryCount - 1*/
568 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)569 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
570 {
571 u32 i;
572 if (!ptr || !item) return GF_BAD_PARAM;
573 /*if last entry or first of an empty array...*/
574 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
575 ptr->slots = (void **)gf_realloc(ptr->slots, (ptr->entryCount + 1) * sizeof(void*));
576 i = ptr->entryCount - position;
577 memmove(&ptr->slots[position + 1], &ptr->slots[position], sizeof(void *)*i);
578 ptr->entryCount++;
579 ptr->slots[position] = item;
580 return GF_OK;
581 }
582
583 GF_EXPORT
gf_list_reset(GF_List * ptr)584 void gf_list_reset(GF_List *ptr)
585 {
586 if (ptr) {
587 ptr->entryCount = 0;
588 gf_free(ptr->slots);
589 ptr->slots = NULL;
590 }
591 }
592
593 #else /*GF_LIST_ARRAY_GROW*/
594
595
596 struct _tag_array
597 {
598 void **slots;
599 u32 entryCount;
600 u32 allocSize;
601 };
602
603 GF_EXPORT
gf_list_new()604 GF_List * gf_list_new()
605 {
606 GF_List *nlist;
607
608 nlist = (GF_List *)gf_malloc(sizeof(GF_List));
609 if (!nlist) return NULL;
610
611 nlist->slots = NULL;
612 nlist->entryCount = 0;
613 nlist->allocSize = 0;
614 return nlist;
615 }
616
617 GF_EXPORT
gf_list_del(GF_List * ptr)618 void gf_list_del(GF_List *ptr)
619 {
620 if (!ptr) return;
621 gf_free(ptr->slots);
622 gf_free(ptr);
623 }
624
realloc_chain(GF_List * ptr)625 static void realloc_chain(GF_List *ptr)
626 {
627 GF_LIST_REALLOC(ptr->allocSize);
628 ptr->slots = (void**)gf_realloc(ptr->slots, ptr->allocSize * sizeof(void*));
629 }
630
631 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)632 GF_Err gf_list_add(GF_List *ptr, void* item)
633 {
634 if (!ptr) return GF_BAD_PARAM;
635 if (ptr->allocSize == ptr->entryCount) realloc_chain(ptr);
636 if (!ptr->slots) return GF_OUT_OF_MEM;
637
638 ptr->slots[ptr->entryCount] = item;
639 ptr->entryCount++;
640 return GF_OK;
641 }
642
643 GF_EXPORT
gf_list_count(const GF_List * ptr)644 u32 gf_list_count(const GF_List *ptr)
645 {
646 if (!ptr) return 0;
647 return ptr->entryCount;
648 }
649
650 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)651 void *gf_list_get(GF_List *ptr, u32 itemNumber)
652 {
653 if (!ptr || (itemNumber >= ptr->entryCount)) return NULL;
654 return ptr->slots[itemNumber];
655 }
656
657 GF_EXPORT
gf_list_last(GF_List * ptr)658 void *gf_list_last(GF_List *ptr)
659 {
660 if (!ptr || !ptr->entryCount) return NULL;
661 return ptr->slots[ptr->entryCount - 1];
662 }
663
664
665 /*WARNING: itemNumber is from 0 to entryCount - 1*/
666 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)667 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
668 {
669 u32 i;
670 if (!ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
671 i = ptr->entryCount - itemNumber - 1;
672 if (i) memmove(&ptr->slots[itemNumber], &ptr->slots[itemNumber + 1], sizeof(void *)*i);
673 ptr->slots[ptr->entryCount - 1] = NULL;
674 ptr->entryCount -= 1;
675 return GF_OK;
676 }
677
678 GF_EXPORT
gf_list_rem_last(GF_List * ptr)679 GF_Err gf_list_rem_last(GF_List *ptr)
680 {
681 if (!ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
682 ptr->slots[ptr->entryCount - 1] = NULL;
683 ptr->entryCount -= 1;
684 return GF_OK;
685 }
686
687 /*WARNING: position is from 0 to entryCount - 1*/
688 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)689 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
690 {
691 u32 i;
692 if (!ptr || !item) return GF_BAD_PARAM;
693 /*if last entry or first of an empty array...*/
694 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
695 if (ptr->allocSize == ptr->entryCount) realloc_chain(ptr);
696
697 i = ptr->entryCount - position;
698 memmove(&ptr->slots[position + 1], &ptr->slots[position], sizeof(void *)*i);
699 ptr->entryCount++;
700 ptr->slots[position] = item;
701 return GF_OK;
702 }
703
704 GF_EXPORT
gf_list_reset(GF_List * ptr)705 void gf_list_reset(GF_List *ptr)
706 {
707 if (ptr) ptr->entryCount = 0;
708 }
709
710 #endif
711
712 GF_EXPORT
gf_list_find(GF_List * ptr,void * item)713 s32 gf_list_find(GF_List *ptr, void *item)
714 {
715 u32 i, count;
716 count = gf_list_count(ptr);
717 for (i = 0; i<count; i++) {
718 if (gf_list_get(ptr, i) == item) return (s32)i;
719 }
720 return -1;
721 }
722
723 GF_EXPORT
gf_list_del_item(GF_List * ptr,void * item)724 s32 gf_list_del_item(GF_List *ptr, void *item)
725 {
726 s32 i = gf_list_find(ptr, item);
727 if (i >= 0) gf_list_rem(ptr, (u32)i);
728 return i;
729 }
730
731 GF_EXPORT
gf_list_enum(GF_List * ptr,u32 * pos)732 void *gf_list_enum(GF_List *ptr, u32 *pos)
733 {
734 void *res;
735 if (!ptr || !pos) return NULL;
736 res = gf_list_get(ptr, *pos);
737 (*pos)++;
738 return res;
739 }
740
741 GF_EXPORT
gf_list_rev_enum(GF_List * ptr,u32 * pos)742 void *gf_list_rev_enum(GF_List *ptr, u32 *pos) {
743 void *res;
744 if (!ptr || !pos) return NULL;
745 res = gf_list_get(ptr, gf_list_count(ptr) - *pos - 1);
746 (*pos)++;
747 return res;
748 }
749
750 GF_EXPORT
gf_list_swap(GF_List * l1,GF_List * l2)751 GF_Err gf_list_swap(GF_List *l1, GF_List *l2)
752 {
753 GF_Err e;
754 u32 count = gf_list_count(l1);
755 if (!l1 || !l2) return GF_BAD_PARAM;
756 if (l1 == l2) return GF_OK;
757
758 while (gf_list_count(l2)) {
759 void *ptr = gf_list_get(l2, 0);
760 e = gf_list_rem(l2, 0);
761 if (e) return e;
762 e = gf_list_add(l1, ptr);
763 if (e) return e;
764 }
765 while (count) {
766 void *ptr = gf_list_get(l1, 0);
767 e = gf_list_rem(l1, 0);
768 if (e) return e;
769 count--;
770 e = gf_list_add(l2, ptr);
771 if (e) return e;
772 }
773 return GF_OK;
774 }
775
776 GF_EXPORT
gf_list_transfer(GF_List * l1,GF_List * l2)777 GF_Err gf_list_transfer(GF_List *l1, GF_List *l2)
778 {
779 GF_Err e;
780 if (!l1 || !l2) return GF_BAD_PARAM;
781 if (l1 == l2) return GF_OK;
782
783 while (gf_list_count(l2)) {
784 void *ptr = gf_list_get(l2, 0);
785 e = gf_list_rem(l2, 0);
786 if (e) return e;
787 e = gf_list_add(l1, ptr);
788 if (e) return e;
789 }
790 return GF_OK;
791 }
792
793 GF_EXPORT
gf_list_clone(GF_List * ptr)794 GF_List* gf_list_clone(GF_List *ptr) {
795 GF_List* new_list;
796 u32 i = 0;
797 void* item;
798 if (!ptr) return NULL;
799 new_list = gf_list_new();
800 while ((item = gf_list_enum(ptr, &i)))
801 gf_list_add(new_list, item);
802
803 return new_list;
804 }
805
806 GF_EXPORT
gf_list_reverse(GF_List * ptr)807 void gf_list_reverse(GF_List *ptr) {
808 GF_List* saved_order;
809 void* item;
810 u32 i = 0;
811 if (!ptr) return;
812 saved_order = gf_list_clone(ptr);
813 gf_list_reset(ptr);
814
815 while ((item = gf_list_enum(saved_order, &i))) {
816 gf_list_insert(ptr, item, 0);
817 }
818
819 gf_list_del(saved_order);
820 }
821
822 GF_EXPORT
gf_list_pop_front(GF_List * ptr)823 void* gf_list_pop_front(GF_List *ptr) {
824 void * item;
825 if (!ptr) return NULL;
826
827 item = gf_list_get(ptr, 0);
828 gf_list_rem(ptr, 0);
829
830 return item;
831 }
832
833 GF_EXPORT
gf_list_pop_back(GF_List * ptr)834 void* gf_list_pop_back(GF_List *ptr) {
835 void * item;
836 if (!ptr) return NULL;
837
838 item = gf_list_last(ptr);
839 gf_list_rem_last(ptr);
840
841 return item;
842 }
843