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 without 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 } else {
111 ptr->entryCount += 1;
112 ptr->tail->next = entry;
113 }
114 ptr->tail = entry;
115 ptr->foundEntryNumber = ptr->entryCount - 1;
116 ptr->foundEntry = entry;
117 return GF_OK;
118 }
119
120 GF_EXPORT
gf_list_count(const GF_List * ptr)121 u32 gf_list_count(const GF_List *ptr)
122 {
123 if (!ptr) return 0;
124 return ptr->entryCount;
125 }
126
127 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)128 void *gf_list_get(GF_List *ptr, u32 itemNumber)
129 {
130 ItemSlot *entry;
131 u32 i;
132
133 if (!ptr || (itemNumber >= ptr->entryCount) ) return NULL;
134
135 if (!ptr->foundEntry || (itemNumber < (u32) ptr->foundEntryNumber) ) {
136 ptr->foundEntryNumber = 0;
137 ptr->foundEntry = ptr->head;
138 }
139 entry = ptr->foundEntry;
140 for (i = ptr->foundEntryNumber; i < itemNumber; i++ ) {
141 entry = entry->next;
142 }
143 ptr->foundEntryNumber = itemNumber;
144 ptr->foundEntry = entry;
145 return (void *) entry->data;
146 }
147
148 GF_EXPORT
gf_list_last(GF_List * ptr)149 void *gf_list_last(GF_List *ptr)
150 {
151 ItemSlot *entry;
152 if (!ptr || !ptr->entryCount) return NULL;
153 entry = ptr->head;
154 while (entry->next) entry = entry->next;
155 return entry->data;
156 }
157
158 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)159 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
160 {
161 ItemSlot *tmp, *tmp2;
162 u32 i;
163
164 /* !! if head is null (empty list)*/
165 if ( (! ptr) || (! ptr->head) || (ptr->head && !ptr->entryCount) || (itemNumber >= ptr->entryCount) )
166 return GF_BAD_PARAM;
167
168 /*we delete the head*/
169 if (! itemNumber) {
170 tmp = ptr->head;
171 ptr->head = ptr->head->next;
172 ptr->entryCount --;
173 ptr->foundEntry = ptr->head;
174 ptr->foundEntryNumber = 0;
175 gf_free(tmp);
176 /*that was the last entry, reset the tail*/
177 if (!ptr->entryCount) {
178 ptr->tail = ptr->head = ptr->foundEntry = NULL;
179 ptr->foundEntryNumber = -1;
180 }
181 return GF_OK;
182 }
183
184 tmp = ptr->head;
185 i = 0;
186 while (i < itemNumber - 1) {
187 tmp = tmp->next;
188 i++;
189 }
190 tmp2 = tmp->next;
191 tmp->next = tmp2->next;
192 /*if we deleted the last entry, update the tail !!!*/
193 if (! tmp->next || (ptr->tail == tmp2) ) {
194 ptr->tail = tmp;
195 tmp->next = NULL;
196 }
197
198 gf_free(tmp2);
199 ptr->entryCount --;
200 ptr->foundEntry = ptr->head;
201 ptr->foundEntryNumber = 0;
202
203 return GF_OK;
204 }
205
206 GF_EXPORT
gf_list_rem_last(GF_List * ptr)207 GF_Err gf_list_rem_last(GF_List *ptr)
208 {
209 return gf_list_rem(ptr, ptr->entryCount-1);
210 }
211
212 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)213 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
214 {
215 u32 i;
216 ItemSlot *tmp, *tmp2;
217
218 if (!ptr || !item) return GF_BAD_PARAM;
219 /*if last entry or first of an empty array...*/
220 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
221
222 tmp2 = (ItemSlot *) gf_malloc(sizeof(ItemSlot));
223 tmp2->data = item;
224 tmp2->next = NULL;
225 /*special case for the head*/
226 if (position == 0) {
227 tmp2->next = ptr->head;
228 ptr->head = tmp2;
229 ptr->entryCount ++;
230 ptr->foundEntry = tmp2;
231 ptr->foundEntryNumber = 0;
232 return GF_OK;
233 }
234 tmp = ptr->head;
235 for (i = 1; i < position; i++) {
236 tmp = tmp->next;
237 if (!tmp)
238 break;
239 }
240 tmp2->next = tmp->next;
241 tmp->next = tmp2;
242 ptr->entryCount ++;
243 ptr->foundEntry = tmp2;
244 ptr->foundEntryNumber = i;
245 return GF_OK;
246 }
247
248 #elif defined(GF_LIST_DOUBLE_LINKED)
249
250
251 typedef struct tagIS
252 {
253 struct tagIS *next;
254 struct tagIS *prev;
255 void *data;
256 } ItemSlot;
257
258 struct _tag_array
259 {
260 struct tagIS *head;
261 struct tagIS *tail;
262 u32 entryCount;
263 s32 foundEntryNumber;
264 struct tagIS *foundEntry;
265 };
266
267
268 GF_EXPORT
gf_list_new()269 GF_List * gf_list_new()
270 {
271 GF_List *nlist = (GF_List *) gf_malloc(sizeof(GF_List));
272 if (! nlist) return NULL;
273 nlist->head = nlist->foundEntry = NULL;
274 nlist->tail = NULL;
275 nlist->foundEntryNumber = -1;
276 nlist->entryCount = 0;
277 return nlist;
278 }
279
280 GF_EXPORT
gf_list_del(GF_List * ptr)281 void gf_list_del(GF_List *ptr)
282 {
283 if (!ptr) return;
284 while (ptr->entryCount) {
285 gf_list_rem(ptr, 0);
286 }
287 gf_free(ptr);
288 }
289
290 GF_EXPORT
gf_list_reset(GF_List * ptr)291 void gf_list_reset(GF_List *ptr)
292 {
293 while (ptr && ptr->entryCount) gf_list_rem(ptr, 0);
294 }
295
296 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)297 GF_Err gf_list_add(GF_List *ptr, void* item)
298 {
299 ItemSlot *entry;
300 if (! ptr) return GF_BAD_PARAM;
301 entry = (ItemSlot *) gf_malloc(sizeof(ItemSlot));
302 if (!entry) return GF_OUT_OF_MEM;
303 entry->data = item;
304 entry->next = entry->prev = NULL;
305
306 if (! ptr->head) {
307 ptr->head = entry;
308 ptr->entryCount = 1;
309 } else {
310 ptr->entryCount += 1;
311 entry->prev = ptr->tail;
312 ptr->tail->next = entry;
313 }
314 ptr->tail = entry;
315 ptr->foundEntryNumber = ptr->entryCount - 1;
316 ptr->foundEntry = entry;
317 return GF_OK;
318 }
319
320
321 GF_EXPORT
gf_list_count(GF_List * ptr)322 u32 gf_list_count(GF_List *ptr)
323 {
324 if (! ptr) return 0;
325 return ptr->entryCount;
326 }
327
328 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)329 void *gf_list_get(GF_List *ptr, u32 itemNumber)
330 {
331 ItemSlot *entry;
332 u32 i;
333
334 if (!ptr || !ptr->head || (itemNumber >= ptr->entryCount) ) return NULL;
335
336 if (!itemNumber) {
337 ptr->foundEntry = ptr->head;
338 ptr->foundEntryNumber = 0;
339 return ptr->head->data;
340 }
341
342 entry = ptr->foundEntry;
343 if ( itemNumber < (u32) ptr->foundEntryNumber ) {
344 for (i = ptr->foundEntryNumber; i > itemNumber; i-- ) {
345 entry = entry->prev;
346 }
347 } else {
348 for (i = ptr->foundEntryNumber; i < itemNumber; i++ ) {
349 entry = entry->next;
350 }
351 }
352 ptr->foundEntryNumber = itemNumber;
353 ptr->foundEntry = entry;
354 return (void *) entry->data;
355 }
356
357 GF_EXPORT
gf_list_last(GF_List * ptr)358 void *gf_list_last(GF_List *ptr)
359 {
360 if(!ptr || !ptr->tail) return NULL;
361 return ptr->tail->data;
362 }
363
364 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)365 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
366 {
367 ItemSlot *tmp;
368 u32 i;
369
370 /* !! if head is null (empty list)*/
371 if ( (! ptr) || (! ptr->head) || (ptr->head && !ptr->entryCount) || (itemNumber >= ptr->entryCount) )
372 return GF_BAD_PARAM;
373
374 /*we delete the head*/
375 if (! itemNumber) {
376 tmp = ptr->head;
377 ptr->head = ptr->head->next;
378
379 ptr->entryCount --;
380 ptr->foundEntry = ptr->head;
381 ptr->foundEntryNumber = 0;
382 gf_free(tmp);
383
384 /*that was the last entry, reset the tail*/
385 if (!ptr->entryCount) {
386 ptr->tail = ptr->head = ptr->foundEntry = NULL;
387 ptr->foundEntryNumber = -1;
388 } else {
389 ptr->head->prev = NULL;
390 }
391 return GF_OK;
392 }
393 else if (itemNumber==ptr->entryCount-1) {
394 tmp = ptr->tail;
395 ptr->tail = tmp->prev;
396 ptr->tail->next = NULL;
397 ptr->entryCount--;
398 if (ptr->foundEntry==tmp) {
399 ptr->foundEntry = ptr->tail;
400 ptr->foundEntryNumber = ptr->entryCount-1;
401 }
402 gf_free(tmp);
403 return GF_OK;
404 }
405
406 tmp = ptr->foundEntry;
407 if ( itemNumber < (u32) ptr->foundEntryNumber ) {
408 for (i = ptr->foundEntryNumber; i > itemNumber; i-- ) {
409 tmp = tmp->prev;
410 }
411 } else {
412 for (i = ptr->foundEntryNumber; i < itemNumber; i++ ) {
413 tmp = tmp->next;
414 }
415 }
416 tmp->prev->next = tmp->next;
417 tmp->next->prev = tmp->prev;
418 if (tmp==ptr->foundEntry) ptr->foundEntry = tmp->next;
419 gf_free(tmp);
420 ptr->entryCount--;
421 return GF_OK;
422 }
423
424 GF_EXPORT
gf_list_rem_last(GF_List * ptr)425 GF_Err gf_list_rem_last(GF_List *ptr)
426 {
427 return gf_list_rem(ptr, ptr->entryCount-1);
428 }
429
430 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)431 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
432 {
433 u32 i;
434 ItemSlot *tmp, *tmp2;
435
436 if (!ptr || !item) return GF_BAD_PARAM;
437 /*if last entry or first of an empty array...*/
438 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
439 tmp2 = (ItemSlot *) gf_malloc(sizeof(ItemSlot));
440 tmp2->data = item;
441 tmp2->next = tmp2->prev = NULL;
442 /*special case for the head*/
443 if (position == 0) {
444 ptr->head->prev = tmp2;
445 tmp2->next = ptr->head;
446 ptr->head = tmp2;
447 ptr->entryCount ++;
448 ptr->foundEntry = tmp2;
449 ptr->foundEntryNumber = 0;
450 return GF_OK;
451 }
452
453 tmp = ptr->foundEntry;
454 if ( position < (u32) ptr->foundEntryNumber ) {
455 for (i = ptr->foundEntryNumber; i >= position; i-- ) {
456 tmp = tmp->prev;
457 }
458 tmp = tmp->prev;
459 } else {
460 for (i = ptr->foundEntryNumber; i < position; i++ ) {
461 tmp = tmp->next;
462 }
463 }
464 tmp2->next = tmp->next;
465 tmp2->next->prev = tmp2;
466 tmp2->prev = tmp;
467 tmp2->prev->next = tmp2;
468 ptr->entryCount ++;
469 ptr->foundEntry = tmp2;
470 ptr->foundEntryNumber = position;
471 return GF_OK;
472 }
473
474 #elif defined(GF_LIST_ARRAY)
475
476 struct _tag_array
477 {
478 void **slots;
479 u32 entryCount;
480 };
481
482
483 GF_EXPORT
gf_list_new()484 GF_List * gf_list_new()
485 {
486 GF_List *nlist = (GF_List *) gf_malloc(sizeof(GF_List));
487 if (! nlist) return NULL;
488 nlist->slots = NULL;
489 nlist->entryCount = 0;
490 return nlist;
491 }
492
493 GF_EXPORT
gf_list_del(GF_List * ptr)494 void gf_list_del(GF_List *ptr)
495 {
496 if (!ptr) return;
497 gf_free(ptr->slots);
498 gf_free(ptr);
499 }
500
501 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)502 GF_Err gf_list_add(GF_List *ptr, void* item)
503 {
504 if (! ptr) return GF_BAD_PARAM;
505
506 ptr->slots = (void **) gf_realloc(ptr->slots, (ptr->entryCount+1)*sizeof(void*));
507 if (!ptr->slots) {
508 return GF_OUT_OF_MEM;
509 }
510 ptr->slots[ptr->entryCount] = item;
511 ptr->entryCount ++;
512 return GF_OK;
513 }
514
515 GF_EXPORT
gf_list_count(GF_List * ptr)516 u32 gf_list_count(GF_List *ptr)
517 {
518 return ptr ? ptr->entryCount : 0;
519 }
520
521 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)522 void *gf_list_get(GF_List *ptr, u32 itemNumber)
523 {
524 if(!ptr || (itemNumber >= ptr->entryCount)) return NULL;
525 return ptr->slots[itemNumber];
526 }
527
528 GF_EXPORT
gf_list_last(GF_List * ptr)529 void *gf_list_last(GF_List *ptr)
530 {
531 if(!ptr || !ptr->entryCount) return NULL;
532 return ptr->slots[ptr->entryCount-1];
533 }
534
535
536 /*WARNING: itemNumber is from 0 to entryCount - 1*/
537 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)538 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
539 {
540 u32 i;
541 if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
542 i = ptr->entryCount - itemNumber - 1;
543 if (i) memmove(&ptr->slots[itemNumber], & ptr->slots[itemNumber +1], sizeof(void *)*i);
544 ptr->slots[ptr->entryCount-1] = NULL;
545 ptr->entryCount -= 1;
546 ptr->slots = (void **) gf_realloc(ptr->slots, sizeof(void*)*ptr->entryCount);
547 return GF_OK;
548 }
549
550 GF_EXPORT
gf_list_rem_last(GF_List * ptr)551 GF_Err gf_list_rem_last(GF_List *ptr)
552 {
553 if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
554 ptr->entryCount -= 1;
555 ptr->slots = (void **) gf_realloc(ptr->slots, sizeof(void*)*ptr->entryCount);
556 return GF_OK;
557 }
558
559
560 /*WARNING: position is from 0 to entryCount - 1*/
561 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)562 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
563 {
564 u32 i;
565 if (!ptr || !item) return GF_BAD_PARAM;
566 /*if last entry or first of an empty array...*/
567 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
568 ptr->slots = (void **) gf_realloc(ptr->slots, (ptr->entryCount+1)*sizeof(void*));
569 i = ptr->entryCount - position;
570 memmove(&ptr->slots[position + 1], &ptr->slots[position], sizeof(void *)*i);
571 ptr->entryCount++;
572 ptr->slots[position] = item;
573 return GF_OK;
574 }
575
576 GF_EXPORT
gf_list_reset(GF_List * ptr)577 void gf_list_reset(GF_List *ptr)
578 {
579 if (ptr) {
580 ptr->entryCount = 0;
581 gf_free(ptr->slots);
582 ptr->slots = NULL;
583 }
584 }
585
586 #else /*GF_LIST_ARRAY_GROW*/
587
588
589 struct _tag_array
590 {
591 void **slots;
592 u32 entryCount;
593 u32 allocSize;
594 };
595
596 GF_EXPORT
gf_list_new()597 GF_List * gf_list_new()
598 {
599 GF_List *nlist;
600
601 nlist = (GF_List *) gf_malloc(sizeof(GF_List));
602 if (! nlist) return NULL;
603
604 nlist->slots = NULL;
605 nlist->entryCount = 0;
606 nlist->allocSize = 0;
607 return nlist;
608 }
609
610 GF_EXPORT
gf_list_del(GF_List * ptr)611 void gf_list_del(GF_List *ptr)
612 {
613 if (!ptr) return;
614 gf_free(ptr->slots);
615 gf_free(ptr);
616 }
617
realloc_chain(GF_List * ptr)618 static void realloc_chain(GF_List *ptr)
619 {
620 GF_LIST_REALLOC(ptr->allocSize);
621 ptr->slots = (void**)gf_realloc(ptr->slots, ptr->allocSize*sizeof(void*));
622 }
623
624 GF_EXPORT
gf_list_add(GF_List * ptr,void * item)625 GF_Err gf_list_add(GF_List *ptr, void* item)
626 {
627 if (! ptr) return GF_BAD_PARAM;
628 if (! item)
629 return GF_BAD_PARAM;
630 if (ptr->allocSize==ptr->entryCount) realloc_chain(ptr);
631 if (!ptr->slots) return GF_OUT_OF_MEM;
632
633 ptr->slots[ptr->entryCount] = item;
634 ptr->entryCount ++;
635 return GF_OK;
636 }
637
638 GF_EXPORT
gf_list_count(const GF_List * ptr)639 u32 gf_list_count(const GF_List *ptr)
640 {
641 if (!ptr) return 0;
642 return ptr->entryCount;
643 }
644
645 GF_EXPORT
gf_list_get(GF_List * ptr,u32 itemNumber)646 void *gf_list_get(GF_List *ptr, u32 itemNumber)
647 {
648 if(!ptr || (itemNumber >= ptr->entryCount))
649 return NULL;
650 return ptr->slots[itemNumber];
651 }
652
653 GF_EXPORT
gf_list_last(GF_List * ptr)654 void *gf_list_last(GF_List *ptr)
655 {
656 if(!ptr || !ptr->entryCount) return NULL;
657 return ptr->slots[ptr->entryCount-1];
658 }
659
660
661 /*WARNING: itemNumber is from 0 to entryCount - 1*/
662 GF_EXPORT
gf_list_rem(GF_List * ptr,u32 itemNumber)663 GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
664 {
665 u32 i;
666 if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
667 if (ptr->entryCount < itemNumber) return GF_BAD_PARAM;
668
669 i = ptr->entryCount - itemNumber - 1;
670 if (i) memmove(&ptr->slots[itemNumber], & ptr->slots[itemNumber +1], sizeof(void *)*i);
671 ptr->slots[ptr->entryCount-1] = NULL;
672 ptr->entryCount -= 1;
673 return GF_OK;
674 }
675
676 GF_EXPORT
gf_list_rem_last(GF_List * ptr)677 GF_Err gf_list_rem_last(GF_List *ptr)
678 {
679 if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
680 ptr->slots[ptr->entryCount-1] = NULL;
681 ptr->entryCount -= 1;
682 return GF_OK;
683 }
684
685 /*WARNING: position is from 0 to entryCount - 1*/
686 GF_EXPORT
gf_list_insert(GF_List * ptr,void * item,u32 position)687 GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
688 {
689 u32 i;
690 if (!ptr || !item) return GF_BAD_PARAM;
691 /*if last entry or first of an empty array...*/
692 if (position >= ptr->entryCount) return gf_list_add(ptr, item);
693 if (ptr->allocSize==ptr->entryCount) realloc_chain(ptr);
694
695 i = ptr->entryCount - position;
696 memmove(&ptr->slots[position + 1], &ptr->slots[position], sizeof(void *)*i);
697 ptr->entryCount++;
698 ptr->slots[position] = item;
699 return GF_OK;
700 }
701
702 GF_EXPORT
gf_list_reset(GF_List * ptr)703 void gf_list_reset(GF_List *ptr)
704 {
705 if (ptr) ptr->entryCount = 0;
706 }
707
708 #endif
709
710 GF_EXPORT
gf_list_find(GF_List * ptr,void * item)711 s32 gf_list_find(GF_List *ptr, void *item)
712 {
713 u32 i, count;
714 count = gf_list_count(ptr);
715 for (i=0; i<count; i++) {
716 if (gf_list_get(ptr, i) == item) return (s32) i;
717 }
718 return -1;
719 }
720
721 GF_EXPORT
gf_list_del_item(GF_List * ptr,void * item)722 s32 gf_list_del_item(GF_List *ptr, void *item)
723 {
724 s32 i = gf_list_find(ptr, item);
725 if (i>=0) gf_list_rem(ptr, (u32) i);
726 return i;
727 }
728
729 GF_EXPORT
gf_list_enum(GF_List * ptr,u32 * pos)730 void *gf_list_enum(GF_List *ptr, u32 *pos)
731 {
732 void *res;
733 if (!ptr || !pos) return NULL;
734 res = gf_list_get(ptr, *pos);
735 (*pos)++;
736 return res;
737 }
738
739 //unused
740 #if 0
741 GF_EXPORT
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 #endif
750
751 GF_EXPORT
gf_list_swap(GF_List * l1,GF_List * l2)752 GF_Err gf_list_swap(GF_List *l1, GF_List *l2)
753 {
754 GF_Err e;
755 u32 count = gf_list_count(l1);
756 if (!l1 || !l2) return GF_BAD_PARAM;
757 if (l1 == l2) return GF_OK;
758
759 while (gf_list_count(l2)) {
760 void *ptr = gf_list_get(l2, 0);
761 e = gf_list_rem(l2, 0);
762 if (e) return e;
763 e = gf_list_add(l1, ptr);
764 if (e) return e;
765 }
766 while (count) {
767 void *ptr = gf_list_get(l1, 0);
768 e = gf_list_rem(l1, 0);
769 if (e) return e;
770 count--;
771 e = gf_list_add(l2, ptr);
772 if (e) return e;
773 }
774 return GF_OK;
775 }
776
777 GF_EXPORT
gf_list_transfer(GF_List * dst,GF_List * src)778 GF_Err gf_list_transfer(GF_List *dst, GF_List *src)
779 {
780 GF_Err e;
781 if (!dst || !src) return GF_BAD_PARAM;
782 if (dst == src) return GF_OK;
783
784 while (gf_list_count(src)) {
785 void *ptr = gf_list_get(src, 0);
786 e = gf_list_rem(src, 0);
787 if (e) return e;
788 e = gf_list_add(dst, ptr);
789 if (e) return e;
790 }
791 return GF_OK;
792 }
793
794 GF_EXPORT
gf_list_clone(GF_List * ptr)795 GF_List* gf_list_clone(GF_List *ptr) {
796 GF_List* new_list;
797 u32 i = 0;
798 void* item;
799 if (!ptr) return NULL;
800 new_list = gf_list_new();
801 while ((item = gf_list_enum(ptr, &i)))
802 gf_list_add(new_list, item);
803
804 return new_list;
805 }
806
807 //unused
808 #if 0
809 void gf_list_reverse(GF_List *ptr) {
810 GF_List* saved_order;
811 void* item;
812 u32 i = 0;
813 if (!ptr) return;
814 saved_order = gf_list_clone(ptr);
815 gf_list_reset(ptr);
816
817 while ((item = gf_list_enum(saved_order, &i))) {
818 gf_list_insert(ptr, item, 0);
819 }
820
821 gf_list_del(saved_order);
822 }
823 #endif
824
825 GF_EXPORT
gf_list_pop_front(GF_List * ptr)826 void* gf_list_pop_front(GF_List *ptr) {
827 void * item;
828 if (!ptr) return NULL;
829
830 item = gf_list_get(ptr, 0);
831 gf_list_rem(ptr, 0);
832
833 return item;
834 }
835
836 GF_EXPORT
gf_list_pop_back(GF_List * ptr)837 void* gf_list_pop_back(GF_List *ptr) {
838 void * item;
839 if (!ptr) return NULL;
840
841 item = gf_list_last(ptr);
842 gf_list_rem_last(ptr);
843
844 return item;
845 }
846