Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2020
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
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
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
93 : void gf_list_reset(GF_List *ptr)
94 : {
95 : while (ptr && ptr->entryCount) gf_list_rem(ptr, 0);
96 : }
97 :
98 : GF_EXPORT
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
121 : u32 gf_list_count(const GF_List *ptr)
122 : {
123 : if (!ptr) return 0;
124 : return ptr->entryCount;
125 : }
126 :
127 : GF_EXPORT
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
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
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
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
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
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
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
291 : void gf_list_reset(GF_List *ptr)
292 : {
293 : while (ptr && ptr->entryCount) gf_list_rem(ptr, 0);
294 : }
295 :
296 : GF_EXPORT
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
322 : u32 gf_list_count(GF_List *ptr)
323 : {
324 : if (! ptr) return 0;
325 : return ptr->entryCount;
326 : }
327 :
328 : GF_EXPORT
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
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
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
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
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
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
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
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
516 : u32 gf_list_count(GF_List *ptr)
517 : {
518 : return ptr ? ptr->entryCount : 0;
519 : }
520 :
521 : GF_EXPORT
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
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
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
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
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
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
597 963155 : GF_List * gf_list_new()
598 : {
599 : GF_List *nlist;
600 :
601 963155 : nlist = (GF_List *) gf_malloc(sizeof(GF_List));
602 963155 : if (! nlist) return NULL;
603 :
604 963155 : nlist->slots = NULL;
605 963155 : nlist->entryCount = 0;
606 963155 : nlist->allocSize = 0;
607 963155 : return nlist;
608 : }
609 :
610 : GF_EXPORT
611 1006031 : void gf_list_del(GF_List *ptr)
612 : {
613 1006031 : if (!ptr) return;
614 962969 : gf_free(ptr->slots);
615 962969 : gf_free(ptr);
616 : }
617 :
618 710269 : static void realloc_chain(GF_List *ptr)
619 : {
620 710269 : GF_LIST_REALLOC(ptr->allocSize);
621 710269 : ptr->slots = (void**)gf_realloc(ptr->slots, ptr->allocSize*sizeof(void*));
622 710269 : }
623 :
624 : GF_EXPORT
625 5342983 : GF_Err gf_list_add(GF_List *ptr, void* item)
626 : {
627 5342983 : if (! ptr) return GF_BAD_PARAM;
628 5342961 : if (! item)
629 : return GF_BAD_PARAM;
630 5341720 : if (ptr->allocSize==ptr->entryCount) realloc_chain(ptr);
631 5341720 : if (!ptr->slots) return GF_OUT_OF_MEM;
632 :
633 5341720 : ptr->slots[ptr->entryCount] = item;
634 5341720 : ptr->entryCount ++;
635 5341720 : return GF_OK;
636 : }
637 :
638 : GF_EXPORT
639 64805182 : u32 gf_list_count(const GF_List *ptr)
640 : {
641 64805182 : if (!ptr) return 0;
642 64647296 : return ptr->entryCount;
643 : }
644 :
645 : GF_EXPORT
646 343395434 : void *gf_list_get(GF_List *ptr, u32 itemNumber)
647 : {
648 343395434 : if(!ptr || (itemNumber >= ptr->entryCount))
649 : return NULL;
650 328620508 : return ptr->slots[itemNumber];
651 : }
652 :
653 : GF_EXPORT
654 5218727 : void *gf_list_last(GF_List *ptr)
655 : {
656 5218727 : if(!ptr || !ptr->entryCount) return NULL;
657 5195955 : return ptr->slots[ptr->entryCount-1];
658 : }
659 :
660 :
661 : /*WARNING: itemNumber is from 0 to entryCount - 1*/
662 : GF_EXPORT
663 3385618 : GF_Err gf_list_rem(GF_List *ptr, u32 itemNumber)
664 : {
665 : u32 i;
666 3385618 : if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
667 3385615 : if (ptr->entryCount < itemNumber) return GF_BAD_PARAM;
668 :
669 3385615 : i = ptr->entryCount - itemNumber - 1;
670 3385615 : if (i) memmove(&ptr->slots[itemNumber], & ptr->slots[itemNumber +1], sizeof(void *)*i);
671 3385615 : ptr->slots[ptr->entryCount-1] = NULL;
672 3385615 : ptr->entryCount -= 1;
673 3385615 : return GF_OK;
674 : }
675 :
676 : GF_EXPORT
677 1673026 : GF_Err gf_list_rem_last(GF_List *ptr)
678 : {
679 1673026 : if ( !ptr || !ptr->slots || !ptr->entryCount) return GF_BAD_PARAM;
680 1672925 : ptr->slots[ptr->entryCount-1] = NULL;
681 1672925 : ptr->entryCount -= 1;
682 1672925 : return GF_OK;
683 : }
684 :
685 : /*WARNING: position is from 0 to entryCount - 1*/
686 : GF_EXPORT
687 58661 : GF_Err gf_list_insert(GF_List *ptr, void *item, u32 position)
688 : {
689 : u32 i;
690 58661 : if (!ptr || !item) return GF_BAD_PARAM;
691 : /*if last entry or first of an empty array...*/
692 58660 : if (position >= ptr->entryCount) return gf_list_add(ptr, item);
693 56543 : if (ptr->allocSize==ptr->entryCount) realloc_chain(ptr);
694 :
695 56543 : i = ptr->entryCount - position;
696 56543 : memmove(&ptr->slots[position + 1], &ptr->slots[position], sizeof(void *)*i);
697 56543 : ptr->entryCount++;
698 56543 : ptr->slots[position] = item;
699 56543 : return GF_OK;
700 : }
701 :
702 : GF_EXPORT
703 92613 : void gf_list_reset(GF_List *ptr)
704 : {
705 92613 : if (ptr) ptr->entryCount = 0;
706 92613 : }
707 :
708 : #endif
709 :
710 : GF_EXPORT
711 1670092 : s32 gf_list_find(GF_List *ptr, void *item)
712 : {
713 : u32 i, count;
714 1670092 : count = gf_list_count(ptr);
715 27815167 : for (i=0; i<count; i++) {
716 27171784 : if (gf_list_get(ptr, i) == item) return (s32) i;
717 : }
718 : return -1;
719 : }
720 :
721 : GF_EXPORT
722 454329 : s32 gf_list_del_item(GF_List *ptr, void *item)
723 : {
724 454329 : s32 i = gf_list_find(ptr, item);
725 454329 : if (i>=0) gf_list_rem(ptr, (u32) i);
726 454329 : return i;
727 : }
728 :
729 : GF_EXPORT
730 53393396 : void *gf_list_enum(GF_List *ptr, u32 *pos)
731 : {
732 : void *res;
733 53393396 : if (!ptr || !pos) return NULL;
734 53325720 : res = gf_list_get(ptr, *pos);
735 53325720 : (*pos)++;
736 53325720 : 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
752 56 : GF_Err gf_list_swap(GF_List *l1, GF_List *l2)
753 : {
754 : GF_Err e;
755 56 : u32 count = gf_list_count(l1);
756 56 : if (!l1 || !l2) return GF_BAD_PARAM;
757 55 : if (l1 == l2) return GF_OK;
758 :
759 256 : while (gf_list_count(l2)) {
760 201 : void *ptr = gf_list_get(l2, 0);
761 201 : e = gf_list_rem(l2, 0);
762 201 : if (e) return e;
763 201 : e = gf_list_add(l1, ptr);
764 201 : if (e) return e;
765 : }
766 316 : while (count) {
767 261 : void *ptr = gf_list_get(l1, 0);
768 261 : e = gf_list_rem(l1, 0);
769 261 : if (e) return e;
770 261 : count--;
771 261 : e = gf_list_add(l2, ptr);
772 261 : if (e) return e;
773 : }
774 : return GF_OK;
775 : }
776 :
777 : GF_EXPORT
778 64 : GF_Err gf_list_transfer(GF_List *dst, GF_List *src)
779 : {
780 : GF_Err e;
781 64 : if (!dst || !src) return GF_BAD_PARAM;
782 64 : if (dst == src) return GF_OK;
783 :
784 169 : while (gf_list_count(src)) {
785 105 : void *ptr = gf_list_pop_front(src);
786 105 : if (!ptr) return GF_BAD_PARAM;
787 105 : e = gf_list_add(dst, ptr);
788 105 : if (e) return e;
789 : }
790 : return GF_OK;
791 : }
792 :
793 : GF_EXPORT
794 11 : GF_List* gf_list_clone(GF_List *ptr) {
795 : GF_List* new_list;
796 11 : u32 i = 0;
797 : void* item;
798 11 : if (!ptr) return NULL;
799 11 : new_list = gf_list_new();
800 40 : while ((item = gf_list_enum(ptr, &i)))
801 18 : gf_list_add(new_list, item);
802 :
803 : return new_list;
804 : }
805 :
806 : //unused
807 : #if 0
808 : void gf_list_reverse(GF_List *ptr) {
809 : GF_List* saved_order;
810 : void* item;
811 : u32 i = 0;
812 : if (!ptr) return;
813 : saved_order = gf_list_clone(ptr);
814 : gf_list_reset(ptr);
815 :
816 : while ((item = gf_list_enum(saved_order, &i))) {
817 : gf_list_insert(ptr, item, 0);
818 : }
819 :
820 : gf_list_del(saved_order);
821 : }
822 : #endif
823 :
824 : GF_EXPORT
825 17596 : void* gf_list_pop_front(GF_List *ptr) {
826 : void * item;
827 17596 : if (!ptr) return NULL;
828 :
829 17596 : item = gf_list_get(ptr, 0);
830 17596 : gf_list_rem(ptr, 0);
831 :
832 17596 : return item;
833 : }
834 :
835 : GF_EXPORT
836 1552232 : void* gf_list_pop_back(GF_List *ptr) {
837 : void * item;
838 1552232 : if (!ptr) return NULL;
839 :
840 1552235 : item = gf_list_last(ptr);
841 1552235 : gf_list_rem_last(ptr);
842 :
843 1552234 : return item;
844 : }
|