1 /*
2  pblList.c - C implementation of two Lists similar
3              to the Java ArrayList and Java LinkedList.
4 
5  Copyright (C) 2009   Peter Graf
6 
7    This file is part of PBL - The Program Base Library.
8    PBL is free software.
9 
10     This library is free software; you can redistribute it and/or
11     modify it under the terms of the GNU Lesser General Public
12     License as published by the Free Software Foundation; either
13     version 2.1 of the License, or (at your option) any later version.
14 
15     This library 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 GNU
18     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; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 
24    For more information on the Program Base Library or Peter Graf,
25    please see: http://www.mission-base.com/.
26 
27     $Log: pblList.c,v $
28     Revision 1.40  2010/05/30 20:06:45  peter
29     Removed warnings found by 'Microsoft Visual C++ 2010'.
30 
31     Revision 1.39  2009/03/11 23:48:44  peter
32     More tests and clean up.
33 
34     Revision 1.38  2009/03/08 20:56:50  peter
35     port to gcc (Ubuntu 4.3.2-1ubuntu12) 4.3.2.
36     Exposing the hash set and tree set interfaces.
37 
38 
39     Revision 1.21  2009/02/03 16:40:14  peter
40     PBL vesion 1.04, optimizations,
41     MAC OS X port, port to Microsoft Visual C++ 2008 Express Edition,
42     exposing the array list and the linked list interface
43 
44 */
45 
46 /*
47  * Make sure "strings <exe> | grep Id | sort -u" shows the source file versions
48  */
49 char* pblList_c_id = "$Id: pblList.c,v 1.40 2010/05/30 20:06:45 peter Exp $";
50 
51 char * PblArrayListMagic = "PblArrayListMagic";
52 char * PblLinkedListMagic = "PblLinkedListMagic";
53 
54 #include <stdio.h>
55 #include <memory.h>
56 
57 #ifndef __APPLE__
58 #include <stdlib.h>
59 #endif
60 
61 #include <stdlib.h>
62 
63 #include "pbl.h"
64 
65 /*****************************************************************************/
66 /* #defines                                                                  */
67 /*****************************************************************************/
68 #ifndef PBLAL_INITIAL_CAPACITY /* value might be set by compiler switch      */
69 #define PBLAL_INITIAL_CAPACITY 10   /* default initial capacity              */
70 #endif
71 
72 
73 /*****************************************************************************/
74 /* Function declarations                                                     */
75 /*****************************************************************************/
76 
77 static int pblLinkedListAdd(
78 PblLinkedList * list,  /** The list to append to               */
79 void * element         /** Element to be appended to this list */
80 );
81 
82 static void * pblLinkedListRemoveAt(
83 PblLinkedList * list,   /** The list to use                                */
84 int index               /** Index at which the element is to be removed    */
85 );
86 
87 static void ** pblLinkedListToArray(
88 PblLinkedList * list      /** The list to use */
89 );
90 
91 static int pblLinkedListRemoveRange(
92 PblLinkedList * list,     /** The list to use                              */
93 int fromIndex,            /** The index of first element to be removed.    */
94 int toIndex               /** The index after last element to be removed.  */
95 );
96 
97 static PblLinkedNode * pblLinkedListGetNodeAt(
98 PblLinkedList * list,     /** The list to use                */
99 int index                 /** Index of the node to return    */
100 );
101 
102 static int pblLinkedListAddAt(
103 PblLinkedList * list,     /** The list to use                              */
104 int index,                /** Index at which the element is to be inserted */
105 void * element            /** Element to be appended to this list          */
106 );
107 
108 /*****************************************************************************/
109 /* Functions                                                                 */
110 /*****************************************************************************/
111 
112 /**
113  * Creates a new array list.
114  *
115  * This method has a time complexity of O(1).
116  *
117  * @return PblList * retPtr != NULL: A pointer to the new list.
118  * @return PblList * retPtr == NULL: An error, see pbl_errno:
119  *
120  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
121  */
pblListNewArrayList(void)122 PblList * pblListNewArrayList( void )
123 {
124     PblArrayList * pblList = (PblArrayList *)pbl_malloc0( "pblListNewArrayList",
125                                        sizeof(PblArrayList) );
126     if( !pblList )
127     {
128         return NULL;
129     }
130 
131     pblList->genericList.magic = PblArrayListMagic;
132 
133     return (PblList *)pblList;
134 }
135 
136 /**
137  * Creates a new linked list.
138  *
139  * This method has a time complexity of O(1).
140  *
141  * @return PblList * retPtr != NULL: A pointer to the new list.
142  * @return PblList * retPtr == NULL: An error, see pbl_errno:
143  *
144  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
145  */
pblListNewLinkedList(void)146 PblList * pblListNewLinkedList( void )
147 {
148     PblLinkedList * pblList = (PblLinkedList *)pbl_malloc0( "pblListNewLinkedList",
149                                         sizeof(PblLinkedList) );
150     if( !pblList )
151     {
152         return NULL;
153     }
154 
155     pblList->genericList.magic = PblLinkedListMagic;
156 
157     return (PblList *)pblList;
158 }
159 
160 /*
161  * Returns a shallow copy from this linked list of all of the elements
162  * whose index is between fromIndex, inclusive and toIndex, exclusive.
163  *
164  * @return PblList * retPtr != NULL: A pointer to the new list.
165  * @return PblList * retPtr == NULL: An error, see pbl_errno:
166  *
167  * <BR>PBL_ERROR_OUT_OF_MEMORY  - Out of memory.
168  * <BR>PBL_ERROR_OUT_OF_BOUNDS  - fromIndex is out of range (fromIndex < 0 || fromIndex >= size())
169  *                          or toIndex is out of range ( toIndex < 0 || toIndex > size())
170  */
pblLinkedListCloneRange(PblLinkedList * list,int fromIndex,int toIndex)171 static PblList * pblLinkedListCloneRange(
172 PblLinkedList * list,     /** The list to use                              */
173 int fromIndex,            /** The index of first element to be cloned.     */
174 int toIndex               /** The index after last element to be cloned.   */
175 )
176 {
177     int elementsToClone;
178     int distanceToEnd;
179     PblLinkedNode * linkedNode;
180     PblLinkedList * newList = (PblLinkedList *)pblListNewLinkedList();
181 
182     if( !newList )
183     {
184         return NULL;
185     }
186 
187     ( (PblLinkedList *)newList )->genericList.compare
188             = list->genericList.compare;
189 
190     elementsToClone = toIndex - fromIndex;
191     if( elementsToClone < 1 )
192     {
193         return (PblList *)newList;
194     }
195 
196     distanceToEnd = list->genericList.size - toIndex;
197     if( fromIndex <= distanceToEnd )
198     {
199         // Find the first node to clone from the beginning of the list
200         // and clone forward
201         //
202         linkedNode = pblLinkedListGetNodeAt( list, fromIndex );
203         if( !linkedNode )
204         {
205             pblListFree( (PblList *)newList );
206             return NULL;
207         }
208 
209         while( elementsToClone-- > 0 )
210         {
211             if( pblLinkedListAdd( newList, linkedNode->element ) < 0 )
212             {
213                 pblListFree( (PblList *)newList );
214                 return NULL;
215             }
216 
217             linkedNode = linkedNode->next;
218         }
219     }
220     else
221     {
222         // Find the last node to clone from the end of the list
223         // and clone backward
224         //
225         linkedNode = pblLinkedListGetNodeAt( list, toIndex - 1 );
226         if( !linkedNode )
227         {
228             pblListFree( (PblList *)newList );
229             return NULL;
230         }
231 
232         while( elementsToClone-- > 0 )
233         {
234             if( pblLinkedListAddAt( newList, 0, linkedNode->element ) < 0 )
235             {
236                 pblListFree( (PblList *)newList );
237                 return NULL;
238             }
239 
240             linkedNode = linkedNode->prev;
241         }
242     }
243 
244     return (PblList *)newList;
245 }
246 
247 /*
248  * Returns a shallow copy from this array list of all of the elements
249  * whose index is between fromIndex, inclusive and toIndex, exclusive.
250  *
251  * @return PblList * retPtr != NULL: A pointer to the new list.
252  * @return PblList * retPtr == NULL: An error, see pbl_errno:
253  *
254  * <BR>PBL_ERROR_OUT_OF_MEMORY  - Out of memory.
255  * <BR>PBL_ERROR_OUT_OF_BOUNDS  - fromIndex is out of range (fromIndex < 0 || fromIndex >= size())
256  *                          or toIndex is out of range ( toIndex < 0 || toIndex > size())
257  */
pblArrayListCloneRange(PblArrayList * list,int fromIndex,int toIndex)258 static PblList * pblArrayListCloneRange(
259 PblArrayList * list,      /** The list to use                             */
260 int fromIndex,            /** The index of first element to be cloned.    */
261 int toIndex               /** The index after last element to be cloned.  */
262 )
263 {
264     int elementsToClone = toIndex - fromIndex;
265 
266     PblArrayList * newList = (PblArrayList *)pblListNewArrayList();
267     if( !newList )
268     {
269         return NULL;
270     }
271 
272     newList->genericList.compare = list->genericList.compare;
273 
274     if( elementsToClone < 1 )
275     {
276         return (PblList*)newList;
277     }
278 
279     newList->pointerArray = pbl_memdup( "pblArrayListCloneRange pointerArray",
280                                         &( list->pointerArray[ fromIndex ] ),
281                                         sizeof(void*) * elementsToClone );
282 
283     if( !newList->pointerArray )
284     {
285         PBL_FREE( newList );
286         return NULL;
287     }
288 
289     newList->capacity = elementsToClone;
290     newList->genericList.size = elementsToClone;
291 
292     return (PblList*)newList;
293 }
294 
295 /**
296  * Returns a shallow copy from this list of all of the elements
297  * whose index is between fromIndex, inclusive and toIndex, exclusive.
298  *
299  * For array lists cloning has a time complexity
300  * of O(M), with M being the number of elements cloned.
301  *
302  * For linked lists cloning from the beginning or the end of the list has a time complexity
303  * of O(M) with M being the number of elements cloned,
304  * while cloning from a random position in the middle of the list has a time
305  * complexity of O(N) with N being the number of elements in the list.
306  *
307  * This method has a memory complexity of O(M),
308  * with M being the number of elements cloned.
309  *
310  * @return PblList * retPtr != NULL: A pointer to the new list.
311  * @return PblList * retPtr == NULL: An error, see pbl_errno:
312  *
313  * <BR>PBL_ERROR_OUT_OF_MEMORY  - Out of memory.
314  * <BR>PBL_ERROR_OUT_OF_BOUNDS  - fromIndex is out of range (fromIndex < 0 || fromIndex >= size())
315  *                          or toIndex is out of range ( toIndex < 0 || toIndex > size()) or range is negative.
316  */
pblListCloneRange(PblList * list,int fromIndex,int toIndex)317 PblList * pblListCloneRange(
318 PblList * list,           /** The list to use                             */
319 int fromIndex,            /** The index of first element to be cloned.    */
320 int toIndex               /** The index after last element to be cloned.  */
321 )
322 {
323     int elementsToClone = toIndex - fromIndex;
324 
325     if( fromIndex < 0 || fromIndex > list->size )
326     {
327         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
328         return NULL;
329     }
330 
331     if( toIndex < 0 || toIndex > list->size )
332     {
333         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
334         return NULL;
335     }
336 
337     if( elementsToClone < 0 )
338     {
339         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
340         return NULL;
341     }
342 
343     if( PBL_LIST_IS_LINKED_LIST( list ) )
344     {
345         return pblLinkedListCloneRange( (PblLinkedList *)list, fromIndex, toIndex );
346     }
347 
348     return pblArrayListCloneRange( (PblArrayList *)list, fromIndex, toIndex );
349 }
350 
351 /**
352  * Returns a shallow copy of this list instance.
353  *
354  * The elements themselves are not copied.
355  *
356  * This method has a memory and time complexity of O(N),
357  * with N being the number of elements in the list.
358  *
359  * @return PblList * retPtr != NULL: A pointer to the new list.
360  * @return PblList * retPtr == NULL: An error, see pbl_errno:
361  *
362  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
363  */
pblListClone(PblList * list)364 PblList * pblListClone(
365 PblList * list          /** The list to clone */
366 )
367 {
368     if( PBL_LIST_IS_LINKED_LIST( list ) )
369     {
370         return pblLinkedListCloneRange( (PblLinkedList *)list, 0, list->size );
371     }
372 
373     return pblArrayListCloneRange( (PblArrayList *)list, 0, list->size );
374 }
375 
376 /*
377  * Removes all of the elements from this list.
378  *
379  * This method has a time complexity of O(N),
380  * with N being the number of elements in the list.
381  *
382  * @return void
383  */
pblArrayListClear(PblArrayList * list)384 static void pblArrayListClear(
385 PblArrayList * list     /** The list to clear */
386 )
387 {
388     if( list->genericList.size > 0 && list->pointerArray )
389     {
390         memset( list->pointerArray, 0, sizeof(void*) * list->genericList.size );
391     }
392     list->genericList.size = 0;
393     list->genericList.changeCounter++;
394 }
395 
396 /*
397  * Removes all of the elements from this list.
398  *
399  * This method has a time complexity of O(N),
400  * with N being the number of elements in the list.
401  *
402  * @return void
403  */
pblLinkedListClear(PblLinkedList * list)404 static void pblLinkedListClear(
405 PblLinkedList * list     /** The list to clear */
406 )
407 {
408     while( list->head )
409     {
410         PblLinkedNode * nodeToFree = list->head;
411         PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev );
412         PBL_FREE( nodeToFree );
413     }
414     list->genericList.size = 0;
415     list->genericList.changeCounter++;
416 }
417 
418 /**
419  * Removes all of the elements from this list.
420  *
421  * <B>Note:</B> No memory of the elements themselves is freed.
422  *
423  * This method has a time complexity of O(N),
424  * with N being the number of elements in the list.
425  *
426  * @return void
427  */
pblListClear(PblList * list)428 void pblListClear(
429 PblList * list     /** The list to clear */
430 )
431 {
432     if( PBL_LIST_IS_ARRAY_LIST( list ) )
433     {
434         pblArrayListClear( (PblArrayList *)list );
435         return;
436     }
437 
438     pblLinkedListClear( (PblLinkedList *)list );
439 }
440 
441 /*
442  * Reverses the order of the elements of the array list.
443  *
444  * This method has a time complexity of O(N),
445  * with N being the number of elements in the list.
446  *
447  * @return void
448  */
pblArrayListReverse(PblArrayList * list)449 static void pblArrayListReverse(
450 PblArrayList * list /** The list to reverse */
451 )
452 {
453     unsigned char ** leftPointer = list->pointerArray - 1;
454     unsigned char ** rightPointer = list->pointerArray + list->genericList.size;
455     unsigned char * tmp;
456 
457     if( list->genericList.size < 2 )
458     {
459         return;
460     }
461     list->genericList.changeCounter++;
462 
463     while( ++leftPointer < --rightPointer )
464     {
465         tmp = *rightPointer;
466         *rightPointer = *leftPointer;
467         *leftPointer = tmp;
468     }
469 }
470 
471 /*
472  * Reverses the order of the elements of this linked list.
473  *
474  * This method has a time complexity of O(N),
475  * with N being the number of elements in the list.
476  *
477  * @return void
478  */
pblLinkedListReverse(PblLinkedList * list)479 static void pblLinkedListReverse(
480 PblLinkedList * list /** The list to reverse */
481 )
482 {
483     PblLinkedNode * leftNode = list->head;
484     PblLinkedNode * rightNode = list->tail;
485     void * tmp;
486 
487     if( list->genericList.size < 2 )
488     {
489         return;
490     }
491     list->genericList.changeCounter++;
492 
493     while( leftNode != rightNode )
494     {
495         tmp = rightNode->element;
496         rightNode->element = leftNode->element;
497         leftNode->element = tmp;
498 
499         if( leftNode->next == rightNode )
500         {
501             break;
502         }
503         leftNode = leftNode->next;
504         rightNode = rightNode->prev;
505     }
506 }
507 
508 /**
509  * Reverses the order of the elements of this list.
510  *
511  * This method has a time complexity of O(N),
512  * with N being the number of elements in the list.
513  *
514  * @return void
515  */
pblListReverse(PblList * list)516 void pblListReverse(
517 PblList * list /** The list to reverse */
518 )
519 {
520     if( PBL_LIST_IS_ARRAY_LIST( list ))
521     {
522         pblArrayListReverse( (PblArrayList *)list );
523         return;
524     }
525 
526     pblLinkedListReverse( (PblLinkedList *)list );
527 }
528 
529 /*
530  * Free the array list's memory from heap.
531  *
532  * <B>Note:</B> The memory of the elements themselves is not freed.
533  *
534  * This method has a time complexity of O(1).
535  *
536  * @return void
537  */
pblArrayListFree(PblArrayList * list)538 static void pblArrayListFree(
539 PblArrayList * list    /** The list to free */
540 )
541 {
542     PBL_FREE( list->pointerArray );
543     PBL_FREE( list );
544 }
545 
546 
547 /**
548  * Free the list's memory from heap.
549  *
550  * <B>Note:</B> The memory of the elements themselves is not freed.
551  *
552  * For array lists this method has a time complexity of O(1).
553  *
554  * For linked lists this method has a time complexity of O(N),
555  * with N being the number of elements in the list.
556  *
557  * @return void
558  */
pblListFree(PblList * list)559 void pblListFree(
560 PblList * list    /** The list to free */
561 )
562 {
563     if( PBL_LIST_IS_ARRAY_LIST( list ))
564     {
565         pblArrayListFree( (PblArrayList *)list );
566         return;
567     }
568 
569     pblLinkedListClear( (PblLinkedList *)list );
570     PBL_FREE( list );
571 }
572 
573 /*
574  * Increases the capacity of this array list instance, if necessary.
575  *
576  * This method ensures that the list can hold
577  * at least the number of elements specified by the minimum
578  * capacity argument.
579  *
580  * @return int rc >= 0: OK, the list capacity is returned.
581  * @return int rc <  0: An error, see pbl_errno:
582  *
583  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
584  */
pblArrayListEnsureCapacity(PblArrayList * list,int minCapacity)585 static int pblArrayListEnsureCapacity(
586 PblArrayList * list,       /** The list to use              */
587 int minCapacity            /** The desired minimum capacity */
588 )
589 {
590     unsigned char ** pointerArray;
591 
592     if( minCapacity <= list->capacity )
593     {
594         /*
595          * Nothing to do
596          */
597         return list->capacity;
598     }
599 
600     /*
601      * Malloc space for minCapacity pointers
602      */
603     pointerArray = (unsigned char **)pbl_malloc( "pblArrayListEnsureCapacity", sizeof(void*)
604             * minCapacity );
605     if( !pointerArray )
606     {
607         return -1;
608     }
609 
610     if( list->capacity > 0 )
611     {
612         /*
613          * Copy the old values
614          */
615         memcpy( pointerArray, list->pointerArray, sizeof(void*)
616                 * list->capacity );
617     }
618 
619     /*
620      * Make sure all new pointers are NULL
621      */
622     memset( &( pointerArray[ list->capacity ] ), 0, sizeof(void*)
623             * ( minCapacity - list->capacity ) );
624 
625     /*
626      * Remember the new capacity
627      */
628     list->capacity = minCapacity;
629 
630     /*
631      * Free any old data
632      */
633     if( list->pointerArray )
634     {
635         PBL_FREE( list->pointerArray );
636     }
637 
638     /*
639      * Remember the new pointer array
640      */
641     list->pointerArray = pointerArray;
642     list->genericList.changeCounter++;
643 
644     return list->capacity;
645 }
646 
647 /**
648  * Increases the capacity of this list instance, if necessary.
649  *
650  * For array lists this method ensures that the list can hold
651  * at least the number of elements specified by the minimum
652  * capacity argument.
653  *
654  * For linked lists this method does nothing,
655  * it justs returns the value of parameter minCapacity.
656  *
657  * If the list is an array list and if the capacity is actually
658  * increased, this method has a memory and time complexity of O(N),
659  * with N being the new capacity of the list.
660  *
661  * In all other cases this method has a time complexity of O(1).
662  *
663  * @return int rc >= 0: OK, the list capacity is returned.
664  * @return int rc <  0: An error, see pbl_errno:
665  *
666  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
667  */
pblListEnsureCapacity(PblList * list,int minCapacity)668 int pblListEnsureCapacity(
669 PblList * list, /** The list to use              */
670 int minCapacity /** The desired minimum capacity */
671 )
672 {
673     if( PBL_LIST_IS_LINKED_LIST( list ))
674     {
675         return minCapacity;
676     }
677 
678     return pblArrayListEnsureCapacity( (PblArrayList *)list, minCapacity );
679 }
680 
681 /*
682  * Sets the size of a linked list.
683  *
684  * If the size is increased, the new elements are initialized with NULL.
685  *
686  * This method has a time complexity of O(N),
687  * with N being the difference between the old and new size
688  * of the list.
689  *
690  * @return int rc >= 0: OK, the list size is returned.
691  * @return int rc <  0: An error, see pbl_errno:
692  *
693  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
694  */
pblLinkedListSetSize(PblLinkedList * list,int size)695 static int pblLinkedListSetSize(
696 PblLinkedList * list,            /** The list to use         */
697 int size                         /** The desired size to set */
698 )
699 {
700     int nAdded = 0;
701 
702     if( size < 0 || size == list->genericList.size )
703     {
704         /*
705          * Nothing to do
706          */
707         return list->genericList.size;
708     }
709 
710     while( size < list->genericList.size )
711     {
712         pblLinkedListRemoveAt( list, list->genericList.size - 1 );
713     }
714 
715     while( size > list->genericList.size )
716     {
717         if( pblLinkedListAdd( list, NULL ) < 0 )
718         {
719             while( nAdded-- > 0 )
720             {
721                 pblLinkedListRemoveAt( list, list->genericList.size - 1 );
722             }
723             return -1;
724         }
725         nAdded++;
726     }
727 
728     return list->genericList.size;
729 }
730 
731 /*
732  * Sets the size of an array list.
733  *
734  * If the size is increased, the new elements are initialized with NULL.
735  *
736  * This method has a time complexity of O(N),
737  * with N being the difference between the old and new size
738  * of the list.
739  *
740  * @return int rc >= 0: OK, the list size is returned.
741  * @return int rc <  0: An error, see pbl_errno:
742  *
743  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
744  */
pblArrayListSetSize(PblArrayList * list,int size)745 static int pblArrayListSetSize(
746 PblArrayList * list, /** The list to use          */
747 int size             /** The desired size to set  */
748 )
749 {
750     if( size < 0 || size == list->genericList.size )
751     {
752         /*
753          * Nothing to do
754          */
755         return list->genericList.size;
756     }
757 
758     if( size < list->genericList.size )
759     {
760         /*
761          * Make sure all unused pointers are NULL
762          */
763         memset( &( list->pointerArray[ size ] ), 0, sizeof(void*)
764                 * ( list->genericList.size - size ) );
765     }
766     else if( size > list->capacity )
767     {
768         /*
769          * Make some more space
770          */
771         int capacity = list->capacity;
772         if( capacity < PBLAL_INITIAL_CAPACITY )
773         {
774             capacity = PBLAL_INITIAL_CAPACITY;
775         }
776 
777         if( size > capacity * 2 + 1 )
778         {
779             capacity = size;
780         }
781         else
782         {
783             while( size > capacity )
784             {
785                 capacity = capacity * 2 + 1;
786             }
787         }
788 
789         if( pblArrayListEnsureCapacity( list, capacity ) < size )
790         {
791             return size;
792         }
793     }
794 
795     list->genericList.size = size;
796     list->genericList.changeCounter++;
797     return list->genericList.size;
798 }
799 
800 /**
801  * Sets the size of a list.
802  *
803  * Truncates the list if necessary.
804  *
805  * If the size is increased, the new elements are initialized with NULL.
806  *
807  * This method has a time complexity of O(N),
808  * with N being the difference between the old and new size
809  * of the list.
810  *
811  * @return int rc >= 0: OK, the list size is returned.
812  * @return int rc <  0: An error, see pbl_errno:
813  *
814  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
815  */
pblListSetSize(PblList * list,int size)816 int pblListSetSize(
817 PblList * list,     /** The list to use          */
818 int size            /** The desired size to set  */
819 )
820 {
821     if( size < 0 || size == list->size )
822     {
823         /*
824          * Nothing to do
825          */
826         return list->size;
827     }
828 
829     if( size == 0 )
830     {
831         pblListClear( list );
832         return 0;
833     }
834 
835     if( PBL_LIST_IS_LINKED_LIST( list ) )
836     {
837         return pblLinkedListSetSize( (PblLinkedList *)list, size );
838     }
839 
840     return pblArrayListSetSize( (PblArrayList *)list, size );
841 }
842 
843 /**
844  * Returns the capacity of this list instance.
845  *
846  * For linked lists this call returns the list's size.
847  *
848  * For array lists it returns the list's capacity.
849  *
850  * This method has a time complexity of O(1).
851  *
852  * @return int rc: The capacity of this list instance.
853  */
pblListGetCapacity(PblList * list)854 int pblListGetCapacity(
855 PblList * list          /** The list to use */
856 )
857 {
858     if( PBL_LIST_IS_LINKED_LIST( list ) )
859     {
860         return list->size;
861     }
862 
863     return ((PblArrayList *)list)->capacity;
864 }
865 
866 /**
867  * Returns the number of elements in this list.
868  *
869  * This method has a time complexity of O(1).
870  *
871  * @return int rc: The number of elements in this list.
872  */
pblListSize(PblList * list)873 int pblListSize(
874 PblList * list   /** The list to use */
875 )
876 {
877     return list->size;
878 }
879 
880 /**
881  * Tests if this list has no elements.
882  *
883  * This method has a time complexity of O(1).
884  *
885  * @return int rc != 0: This list has no elements.
886  * @return int rc == 0: This list has elements.
887  */
pblListIsEmpty(PblList * list)888 int pblListIsEmpty(
889 PblList * list      /** The list to test */
890 )
891 {
892     return 0 == list->size;
893 }
894 
895 /**
896  * Tests if the object is a list.
897  *
898  * This method has a time complexity of O(1).
899  *
900  * @return int rc != 0: This object is a list.
901  * @return int rc == 0: This object is not a list.
902  */
pblListIsList(void * object)903 int pblListIsList(
904 void * object      /** The object to test */
905 )
906 {
907     return PBL_LIST_IS_LIST(object);
908 }
909 
910 /**
911  * Tests if the object is an array list.
912  *
913  * This method has a time complexity of O(1).
914  *
915  * @return int rc != 0: This object is an array list.
916  * @return int rc == 0: This object is not an array list.
917  */
pblListIsArrayList(void * object)918 int pblListIsArrayList(
919 void * object           /** The object to test */
920 )
921 {
922     return PBL_LIST_IS_ARRAY_LIST(object);
923 }
924 
925 /**
926  * Tests if the object is a linked list.
927  *
928  * This method has a time complexity of O(1).
929  *
930  * @return int rc != 0: This object is a linked list.
931  * @return int rc == 0: This object is not a linked list.
932  */
pblListIsLinkedList(void * object)933 int pblListIsLinkedList(
934 void * object            /** The object to test */
935 )
936 {
937     return PBL_LIST_IS_LINKED_LIST(object);
938 }
939 
940 /*
941  * Trims the capacity of this list instance to be the list's current size.
942  *
943  * If the capacity is actually
944  * decreased, this method has a time complexity of O(N),
945  * with N being the number of elements in the list.
946  *
947  * In all other cases this method has a time complexity of O(1).
948  *
949  * @return int rc >= 0: The capacity of this list instance.
950  * @return int rc <  0: An error, see pbl_errno:
951  *
952  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
953  */
pblArrayListTrimToSize(PblArrayList * list)954 static int pblArrayListTrimToSize(
955 PblArrayList * list         /** The list to use */
956 )
957 {
958     unsigned char ** pointerArray;
959     int nBytes;
960 
961     if( list->genericList.size == list->capacity )
962     {
963         return list->capacity;
964     }
965 
966     if( list->genericList.size == 0 )
967     {
968         PBL_FREE( list->pointerArray );
969         list->capacity = 0;
970         return list->capacity;
971     }
972 
973     nBytes = sizeof(void*) * list->genericList.size;
974 
975     /*
976      * Malloc space for size pointers
977      */
978     pointerArray = (unsigned char **)pbl_malloc( "pblListTrimToSize", nBytes );
979     if( !pointerArray )
980     {
981         return -1;
982     }
983 
984     /*
985      * Copy the values
986      */
987     memcpy( pointerArray, list->pointerArray, nBytes );
988 
989     PBL_FREE( list->pointerArray );
990     list->pointerArray = pointerArray;
991     list->capacity = list->genericList.size;
992 
993     return list->capacity;
994 }
995 
996 /**
997  * Trims the capacity of this list instance to be the list's current size.
998  *
999  * For linked list this call returns the list's size.
1000  *
1001  * If the list is an array list and if the capacity is actually
1002  * decreased, this method has a time complexity of O(N),
1003  * with N being the number of elements in the list.
1004  *
1005  * In all other cases this method has a time complexity of O(1).
1006  *
1007  * @return int rc >= 0: The capacity of this list instance.
1008  * @return int rc <  0: An error, see pbl_errno:
1009  *
1010  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1011  */
pblListTrimToSize(PblList * list)1012 int pblListTrimToSize(
1013 PblList * list         /** The list to use */
1014 )
1015 {
1016     if( PBL_LIST_IS_LINKED_LIST( list ) )
1017     {
1018         return list->size;
1019     }
1020 
1021     return pblArrayListTrimToSize( (PblArrayList *)list );
1022 }
1023 
1024 
1025 /*
1026  * Searches for the first linked node containing the given element.
1027  *
1028  * This method has a time complexity of O(N),
1029  * with N being the number of elements in the list.
1030  *
1031  * @return void * retptr != NULL: The linked node containing the element.
1032  * @return void * retptr == NULL: The specified element is not present.
1033  */
pblLinkedListGetNode(PblLinkedList * list,void * element)1034 static PblLinkedNode * pblLinkedListGetNode(
1035 PblLinkedList * list,     /** The list to use                        */
1036 void * element            /** Element to look for                    */
1037 )
1038 {
1039     PblLinkedNode * linkedNode = list->head;
1040 
1041     while( linkedNode )
1042     {
1043         if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) )
1044         {
1045             return linkedNode;
1046         }
1047         linkedNode = linkedNode->next;
1048     }
1049 
1050     return NULL;
1051 }
1052 
1053 /*
1054  * Returns the linked list node at the specified position in this linked list.
1055  *
1056  * This method has a time complexity of O(N),
1057  * with N being the minimum of the differences between index and
1058  * 0 or index and the size of the list. Therefore retrieving the first
1059  * or last node has a time complexity of O(1),
1060  * but retrieving a random node from the list has O(N).
1061  *
1062  * @return void * retptr != NULL: The node at the specified position in this list.
1063  * @return void * retptr == NULL: An error, see pbl_errno:
1064  *
1065  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size().
1066  */
pblLinkedListGetNodeAt(PblLinkedList * list,int index)1067 static PblLinkedNode * pblLinkedListGetNodeAt(
1068 PblLinkedList * list,     /** The list to use                */
1069 int index                 /** Index of the node to return    */
1070 )
1071 {
1072     PblLinkedNode * linkedNode;
1073 
1074     if( index <= list->genericList.size / 2 )
1075     {
1076         linkedNode = list->head;
1077         while( index-- > 0 )
1078         {
1079             if( !linkedNode )
1080             {
1081                 pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1082                 return NULL;
1083             }
1084             linkedNode = linkedNode->next;
1085         }
1086     }
1087     else
1088     {
1089         index = list->genericList.size - ( index + 1 );
1090 
1091         linkedNode = list->tail;
1092         while( index-- > 0 )
1093         {
1094             if( !linkedNode )
1095             {
1096                 pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1097                 return NULL;
1098             }
1099             linkedNode = linkedNode->prev;
1100         }
1101     }
1102 
1103     return linkedNode;
1104 }
1105 
1106 /*
1107  * Inserts the specified element at the specified position in this
1108  * linked list.
1109  *
1110  * This method has a time complexity of O(N),
1111  * with N being the minimum of the differences between index and
1112  * 0 or index and the size of the list. Therefore adding the first
1113  * or last element has a time complexity of O(1),
1114  * but adding a random element to the list has O(N).
1115  *
1116  * @return int rc >= 0: The size of this list instance.
1117  * @return int rc <  0: An error, see pbl_errno:
1118  *
1119  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1120  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1121  */
pblLinkedListAddAt(PblLinkedList * list,int index,void * element)1122 static int pblLinkedListAddAt(
1123 PblLinkedList * list,     /** The list to use                              */
1124 int index,                /** Index at which the element is to be inserted */
1125 void * element            /** Element to be appended to this list          */
1126 )
1127 {
1128     PblLinkedNode * newNode;
1129     PblLinkedNode * otherNode;
1130 
1131     if( index < 0 || index > list->genericList.size )
1132     {
1133         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1134         return -1;
1135     }
1136 
1137     if( index == list->genericList.size )
1138     {
1139         return pblLinkedListAdd( list, element );
1140     }
1141 
1142     newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAddAt", sizeof(PblLinkedNode) );
1143     if( !newNode )
1144     {
1145         return -1;
1146     }
1147     newNode->element = element;
1148 
1149     if( index == 0 )
1150     {
1151         PBL_LIST_PUSH( list->head, list->tail, newNode, next, prev );
1152     }
1153     else
1154     {
1155         otherNode = pblLinkedListGetNodeAt( list, index );
1156         if( !otherNode )
1157         {
1158             PBL_FREE( newNode );
1159             return -1;
1160         }
1161         PBL_LIST_INSERT( list->head, otherNode, newNode, next, prev );
1162     }
1163 
1164     list->genericList.size++;
1165     list->genericList.changeCounter++;
1166 
1167     return list->genericList.size;
1168 }
1169 
1170 /*
1171  * Inserts the specified element at the specified position in this list.
1172  *
1173  * Shifts the element currently at that position (if any) and any subsequent
1174  * elements to the right (adds one to their indices).
1175  *
1176  * For array lists adding to the end of the list has a time complexity
1177  * of O(1), while adding to the beginning of the list has a time
1178  * complexity of O(N) with N being the number of elements in the list.
1179  *
1180  * @return int rc >= 0: The size of this list instance.
1181  * @return int rc <  0: An error, see pbl_errno:
1182  *
1183  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1184  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1185  */
pblArrayListAddAt(PblArrayList * list,int index,void * element)1186 static int pblArrayListAddAt(
1187 PblArrayList * list, /** The list to use                              */
1188 int index,           /** Index at which the element is to be inserted */
1189 void * element       /** Element to be appended to this list          */
1190 )
1191 {
1192     if( index < 0 || index > list->genericList.size )
1193     {
1194         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1195         return -1;
1196     }
1197 
1198     if( list->genericList.size == list->capacity )
1199     {
1200         /*
1201          * Make some more space
1202          */
1203         int capacity = list->capacity * 2 + 1;
1204         if( capacity < PBLAL_INITIAL_CAPACITY )
1205         {
1206             capacity = PBLAL_INITIAL_CAPACITY;
1207         }
1208 
1209         if( pblArrayListEnsureCapacity( list, capacity ) < 0 )
1210         {
1211             return -1;
1212         }
1213     }
1214 
1215     if( index < list->genericList.size )
1216     {
1217         unsigned char * from = (unsigned char*)&( list->pointerArray[ index ] );
1218         unsigned char * to = from + sizeof(void*);
1219         int length = sizeof(void*) * ( list->genericList.size - index );
1220 
1221         memmove( to, from, length );
1222     }
1223 
1224     list->pointerArray[ index ] = (unsigned char *)element;
1225     list->genericList.size++;
1226     list->genericList.changeCounter++;
1227 
1228     return list->genericList.size;
1229 }
1230 
1231 /**
1232  * Inserts the specified element at the specified position in this list.
1233  *
1234  * Shifts the element currently at that position (if any) and any subsequent
1235  * elements to the right (adds one to their indices).
1236  *
1237  * For array lists adding to the end of the list has a time complexity
1238  * of O(1), while adding to the beginning of the list has a time
1239  * complexity of O(N) with N being the number of elements in the list.
1240  *
1241  * For linked lists adding to beginning or the end of the list has a time complexity
1242  * of O(1), while adding to a random position in the middle of the list has a time
1243  * complexity of O(N) with N being the number of elements in the list.
1244  *
1245  * @return int rc >= 0: The size of this list instance.
1246  * @return int rc <  0: An error, see pbl_errno:
1247  *
1248  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1249  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1250  */
pblListAddAt(PblList * list,int index,void * element)1251 int pblListAddAt(
1252 PblList * list,    /** The list to use                              */
1253 int index,         /** Index at which the element is to be inserted */
1254 void * element     /** Element to be appended to this list          */
1255 )
1256 {
1257     if( PBL_LIST_IS_LINKED_LIST( list ) )
1258     {
1259         return pblLinkedListAddAt( (PblLinkedList *)list, index, element );
1260     }
1261 
1262     return pblArrayListAddAt( (PblArrayList *)list, index, element );
1263 }
1264 
1265 /*
1266  * Appends the specified element to the end of this list.
1267  *
1268  * This method has a time complexity of O(1).
1269  *
1270  * @return int rc >= 0: The size of this list instance.
1271  * @return int rc <  0: An error, see pbl_errno:
1272  *
1273  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1274  */
pblLinkedListAdd(PblLinkedList * list,void * element)1275 static int pblLinkedListAdd(
1276 PblLinkedList * list,  /** The list to append to               */
1277 void * element         /** Element to be appended to this list */
1278 )
1279 {
1280     PblLinkedNode * newNode;
1281 
1282     newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAdd", sizeof(PblLinkedNode) );
1283     if( !newNode )
1284     {
1285         return -1;
1286     }
1287 
1288     newNode->element = element;
1289 
1290     PBL_LIST_APPEND( list->head, list->tail, newNode, next, prev );
1291     list->genericList.size++;
1292     list->genericList.changeCounter++;
1293 
1294     return list->genericList.size;
1295 }
1296 
1297 /**
1298  * Appends the specified element to the end of this list.
1299  *
1300  * This method has a time complexity of O(1).
1301  *
1302  * @return int rc >= 0: The size of this list instance.
1303  * @return int rc <  0: An error, see pbl_errno:
1304  *
1305  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1306  */
pblListAdd(PblList * list,void * element)1307 int pblListAdd(
1308 PblList * list,  /** The list to append to               */
1309 void * element   /** Element to be appended to this list */
1310 )
1311 {
1312     if( PBL_LIST_IS_ARRAY_LIST(list) )
1313     {
1314         return pblArrayListAddAt( (PblArrayList *)list, list->size, element );
1315     }
1316 
1317     return pblLinkedListAdd( (PblLinkedList *)list, element );
1318 }
1319 
1320 /**
1321  * Pushes the specified element to the end (last element) of this list.
1322  *
1323  * This method has a time complexity of O(1).
1324  *
1325  * @return int rc >= 0: The size of this list instance.
1326  * @return int rc <  0: An error, see pbl_errno:
1327  *
1328  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1329  */
pblListPush(PblList * list,void * element)1330 int pblListPush(
1331 PblList * list,   /** The list to append to               */
1332 void * element    /** Element to be appended to this list */
1333 )
1334 {
1335     return pblListAdd( list, element );
1336 }
1337 
1338 /**
1339  * Inserts the given element at the beginning of this list.
1340  *
1341  * For array lists this method has a time complexity of O(N),
1342  * with N being the size of the list.
1343  *
1344  * For linked lists this method has a time complexity of O(1).
1345  *
1346  * @return int rc >= 0: The size of this list instance.
1347  * @return int rc <  0: An error, see pbl_errno:
1348  *
1349  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1350  */
pblListAddFirst(PblList * list,void * element)1351 int pblListAddFirst(
1352 PblList * list,           /** The list to add to              */
1353 void * element            /** Element to be added to the list */
1354 )
1355 {
1356     return pblListAddAt( list, 0, element );
1357 }
1358 
1359 /**
1360  * Appends the given element to the end of this list.
1361  *
1362  * (Identical in function to the add method; included only for consistency.)
1363  *
1364  * This method has a time complexity of O(1).
1365  *
1366  * @return int rc >= 0: The size of this list instance.
1367  * @return int rc <  0: An error, see pbl_errno:
1368  *
1369  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1370  */
pblListAddLast(PblList * list,void * element)1371 int pblListAddLast(
1372 PblList * list,           /** The list to add to              */
1373 void * element            /** Element to be added to the list */
1374 )
1375 {
1376     return pblListAdd( list, element );
1377 }
1378 
1379 /**
1380  * Adds the specified element as the tail (last element) of this list.
1381  *
1382  * This method has a time complexity of O(1).
1383  *
1384  * @return int rc >= 0: The size of this list instance.
1385  * @return int rc <  0: An error, see pbl_errno:
1386  *
1387  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
1388  */
pblListOffer(PblList * list,void * element)1389 int pblListOffer(
1390 PblList * list,           /** The list to add to              */
1391 void * element            /** Element to be added to the list */
1392 )
1393 {
1394     return pblListAdd( list, element );
1395 }
1396 
1397 /*
1398  * Inserts all of the elements in the specified collection
1399  * into this linked list at the specified position.
1400  *
1401  * @return int rc >= 0: The size of this list instance.
1402  * @return int rc <  0: An error, see pbl_errno:
1403  *
1404  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
1405  * <BR>PBL_ERROR_OUT_OF_BOUNDS           - Index is out of range, (index < 0 || index >= size()).
1406  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The list underlying the iterator was modified concurrently.
1407  */
pblLinkedListAddAllAt(PblLinkedList * list,int index,PblIterator * iterator)1408 static int pblLinkedListAddAllAt(
1409 PblLinkedList * list,  /** The list to use                                           */
1410 int index,             /** Index at which the elements are to be inserted            */
1411 PblIterator * iterator /** The iterator whose elements are to be added to this list. */
1412 )
1413 {
1414     int nAdded = 0;
1415     PblLinkedNode * otherNode;
1416     int hasNext;
1417 
1418     if( index == list->genericList.size )
1419     {
1420         // Add at the end of the list
1421         //
1422         while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
1423         {
1424             void * element = pblIteratorNext( iterator );
1425             if( element == (void*)-1 || pblLinkedListAdd( list, element ) < 0 )
1426             {
1427                 // An error, remove the elements added so far
1428                 //
1429                 while( nAdded-- > 0 )
1430                 {
1431                     pblLinkedListRemoveAt( list, list->genericList.size - 1 );
1432                 }
1433                 return -1;
1434             }
1435             nAdded++;
1436         }
1437         if( hasNext < 0 )
1438         {
1439             // Concurrent modification error on the source list,
1440             // remove the elements added so far
1441             //
1442             while( nAdded-- > 0 )
1443             {
1444                 pblLinkedListRemoveAt( list, list->genericList.size - 1 );
1445             }
1446             return -1;
1447         }
1448 
1449         return list->genericList.size;
1450     }
1451 
1452     otherNode = pblLinkedListGetNodeAt( list, index );
1453     if( !otherNode )
1454     {
1455         return -1;
1456     }
1457 
1458     while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
1459     {
1460         PblLinkedNode * newNode;
1461 
1462         newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAddAllAt", sizeof(PblLinkedNode) );
1463         if( !newNode )
1464         {
1465             // Out of memory,
1466             // remove the elements added so far
1467             //
1468             while( nAdded-- > 0 )
1469             {
1470                 pblLinkedListRemoveAt( list, index );
1471             }
1472             return -1;
1473         }
1474         newNode->element = pblIteratorNext( iterator );
1475         if( newNode->element == (void*)-1 )
1476         {
1477             // Concurrent modification error on the source list,
1478             // remove the elements added so far
1479             //
1480             while( nAdded-- > 0 )
1481             {
1482                 pblLinkedListRemoveAt( list, list->genericList.size - 1 );
1483             }
1484             PBL_FREE( newNode );
1485             return -1;
1486         }
1487 
1488         PBL_LIST_INSERT( list->head, otherNode, newNode, next, prev );
1489         list->genericList.size++;
1490         list->genericList.changeCounter++;
1491         nAdded++;
1492     }
1493     if( hasNext < 0 )
1494     {
1495         // Concurrent modification error on the source list,
1496         // remove the elements added so far
1497         //
1498         while( nAdded-- > 0 )
1499         {
1500             pblLinkedListRemoveAt( list, list->genericList.size - 1 );
1501         }
1502         return -1;
1503     }
1504 
1505     return list->genericList.size;
1506 }
1507 
1508 /**
1509  * Inserts all of the elements in the specified collection
1510  * into this list at the specified position.
1511  *
1512  * Shifts the element currently at that position (if any) and any
1513  * subsequent elements to the right (increases their indices).
1514  * The new elements will appear in this list in the order that
1515  * they are returned by the specified collection's iterator.
1516  *
1517  * The behavior of this operation is unspecified if the specified
1518  * collection is modified while the operation is in progress.
1519  * (Note that this will occur if the specified collection
1520  * is this list, and it's nonempty.)
1521  *
1522  * For array lists adding to the end of the list has a time complexity
1523  * of O(M), while adding to the beginning of the list has a time
1524  * complexity of O(N + M) with N being the number of elements in the list
1525  * and M being the size of the collection whose elements are added.
1526  *
1527  * For linked lists adding to beginning or the end of the list has a time complexity
1528  * of O(M), while adding to a random position in the middle of the list has a time
1529  * complexity of O(N + M) with N being the number of elements in the list
1530  * and M being the size of the collection whose elements are added.
1531  *
1532  * @return int rc >= 0: The size of this list instance.
1533  * @return int rc <  0: An error, see pbl_errno:
1534  *
1535  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
1536  * <BR>PBL_ERROR_OUT_OF_BOUNDS           - Index is out of range, (index < 0 || index >= size()).
1537  * <BR>PBL_ERROR_PARAM_LIST              - Collection cannot be iterated.
1538  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - Collection was modified concurrently.
1539  */
pblListAddAllAt(PblList * list,int index,void * collection)1540 int pblListAddAllAt(
1541 PblList * list,     /** The list to use                                             */
1542 int index,          /** Index at which the element are to be inserted               */
1543 void * collection   /** The collection whose elements are to be added to this list. */
1544 )
1545 {
1546     PblArrayList * pblList;
1547     PblIterator    iteratorBuffer;
1548     PblIterator *  iterator = &iteratorBuffer;
1549     int iteratorSize;
1550     int hasNext;
1551 
1552     if( index < 0 || index > list->size )
1553     {
1554         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1555         return -1;
1556     }
1557 
1558     if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 )
1559     {
1560         return -1;
1561     }
1562 
1563     iteratorSize = pblIteratorSize( iterator );
1564     if( iteratorSize < 1 )
1565     {
1566         return list->size;
1567     }
1568 
1569     if( PBL_LIST_IS_LINKED_LIST( list ) )
1570     {
1571         int rc = pblLinkedListAddAllAt( (PblLinkedList *)list, index, iterator );
1572         return rc;
1573     }
1574 
1575     pblList = (PblArrayList *)list;
1576 
1577     if( pblList->genericList.size + iteratorSize >= pblList->capacity )
1578     {
1579         /*
1580          * Make some more space
1581          */
1582         int capacity = pblList->capacity * 2 + 1;
1583         if( capacity < pblList->genericList.size + iteratorSize )
1584         {
1585             capacity = pblList->genericList.size + iteratorSize;
1586         }
1587         if( capacity < PBLAL_INITIAL_CAPACITY )
1588         {
1589             capacity = PBLAL_INITIAL_CAPACITY;
1590         }
1591 
1592         if( pblArrayListEnsureCapacity( pblList, capacity ) < 0 )
1593         {
1594             return -1;
1595         }
1596     }
1597 
1598     if( index < pblList->genericList.size )
1599     {
1600         unsigned char * from = (unsigned char*)&( pblList->pointerArray[ index ] );
1601         unsigned char * to = from + iteratorSize * sizeof(void*);
1602         int length = sizeof(void*) * ( pblList->genericList.size - index );
1603 
1604         memmove( to, from, length );
1605     }
1606 
1607     // If the source is an array list, we use memcpy directly
1608     //
1609     if( PBL_LIST_IS_ARRAY_LIST(collection) )
1610     {
1611         PblArrayList * source = (PblArrayList *)collection;
1612         unsigned char * from = (unsigned char*)&( source->pointerArray[ 0 ] );
1613         unsigned char * to = (unsigned char*)&( pblList->pointerArray[ index ] );
1614         int length = sizeof(void*) * source->genericList.size;
1615 
1616         memcpy( to, from, length );
1617     }
1618     else
1619     {
1620         while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
1621         {
1622             void * next = pblIteratorNext( iterator );
1623             if( next == (void*)-1 )
1624             {
1625                 // Concurrent modification on the source collection
1626                 //
1627                 return -1;
1628             }
1629             pblList->pointerArray[ index++ ] = (unsigned char *)next;
1630         }
1631         if( hasNext < 0 )
1632         {
1633             // Concurrent modification on the source collection
1634             //
1635             return -1;
1636         }
1637     }
1638 
1639     pblList->genericList.size += iteratorSize;
1640     pblList->genericList.changeCounter++;
1641 
1642     return pblList->genericList.size;
1643 }
1644 
1645 /**
1646  * Appends all of the elements in the specified Collection to the end of this list,
1647  * in the order that they are returned by the specified Collection's Iterator.
1648  *
1649  * This method has a time complexity of O(M),
1650  * with M being the size of the collection whose elements are added.
1651  *
1652  * @return int rc >= 0: The size of this list instance.
1653  * @return int rc <  0: An error, see pbl_errno:
1654  *
1655  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
1656  * <BR>PBL_ERROR_PARAM_LIST              - Collection cannot be iterated.
1657  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - Collection was modified concurrently.
1658  */
pblListAddAll(PblList * list,void * collection)1659 int pblListAddAll(
1660 PblList * list,    /** The list to use                                */
1661 void * collection  /** The collection whose elements are to be added to this list. */
1662 )
1663 {
1664     return pblListAddAllAt( list, list->size, collection );
1665 }
1666 
1667 /**
1668  * Retrieves and removes the head (first element) of this list.
1669  *
1670  * @return void * retptr != (void*)-1: The head of this list, can be NULL.
1671  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1672  *
1673  * <BR>PBL_ERROR_OUT_OF_BOUNDS - This list is empty.
1674  */
pblListRemove(PblList * list)1675 void * pblListRemove(
1676 PblList * list          /** The list to use */
1677 )
1678 {
1679     return pblListRemoveAt( list, 0 );
1680 }
1681 
1682 /*
1683  * Removes the element at the specified position in this linked list.
1684  *
1685  * Shifts any subsequent elements to the left (subtracts one from their indices).
1686  *
1687  * @return void * retptr != (void*)-1: The element that was removed, can be NULL.
1688  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1689  *
1690  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1691  */
pblLinkedListRemoveAt(PblLinkedList * list,int index)1692 static void * pblLinkedListRemoveAt(
1693 PblLinkedList * list,   /** The list to use                                */
1694 int index               /** Index at which the element is to be removed    */
1695 )
1696 {
1697     PblLinkedNode * nodeToFree;
1698     unsigned char * result;
1699 
1700     nodeToFree = pblLinkedListGetNodeAt( list, index );
1701     if( !nodeToFree )
1702     {
1703         return (void*)-1;
1704     }
1705 
1706     result = nodeToFree->element;
1707 
1708     PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev );
1709     list->genericList.size--;
1710     list->genericList.changeCounter++;
1711 
1712     PBL_FREE( nodeToFree );
1713 
1714     return result;
1715 }
1716 
1717 /*
1718  * Removes the element at the specified position in this array list.
1719  *
1720  * Shifts any subsequent elements to the left (subtracts one from their indices).
1721  *
1722  * @return void * retptr != (void*)-1: The element that was removed, can be NULL.
1723  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1724  *
1725  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1726  */
pblArrayListRemoveAt(PblArrayList * list,int index)1727 void * pblArrayListRemoveAt(
1728 PblArrayList * list,    /** The list to use                                */
1729 int index               /** Index at which the element is to be removed    */
1730 )
1731 {
1732     unsigned char * result;
1733 
1734     if( index < 0 || index >= list->genericList.size )
1735     {
1736         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1737         return (void*)-1;
1738     }
1739 
1740     result = list->pointerArray[ index ];
1741 
1742     if( index < list->genericList.size - 1 )
1743     {
1744         unsigned char * to = (unsigned char*)&( list->pointerArray[ index ] );
1745         unsigned char * from = to + sizeof(void*);
1746         int length = sizeof(void*) * ( ( list->genericList.size - 1 ) - index );
1747 
1748         memmove( to, from, length );
1749     }
1750 
1751     list->pointerArray[ list->genericList.size - 1 ] = NULL;
1752     list->genericList.size--;
1753     list->genericList.changeCounter++;
1754 
1755     return result;
1756 }
1757 
1758 /**
1759  * Removes the element at the specified position in this list.
1760  *
1761  * Shifts any subsequent elements to the left (subtracts one from their indices).
1762  *
1763  * For array lists removing from the end of the list has a time complexity
1764  * of O(1), while removing from the beginning of the list has a time
1765  * complexity of O(N) with N being the number of elements in the list.
1766  *
1767  * For linked lists removing from the beginning or the end of the list has a time complexity
1768  * of O(1), while removing from a random position in the middle of the list has a time
1769  * complexity of O(N) with N being the number of elements in the list.
1770  *
1771  * @return void * retptr != (void*)-1: The element that was removed, can be NULL.
1772  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1773  *
1774  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
1775  */
pblListRemoveAt(PblList * list,int index)1776 void * pblListRemoveAt(
1777 PblList * list,         /** The list to use                                 */
1778 int index               /** The index at which the element is to be removed */
1779 )
1780 {
1781     if( index < 0 || index >= list->size )
1782     {
1783         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1784         return (void*)-1;
1785     }
1786 
1787     if( PBL_LIST_IS_LINKED_LIST( list ) )
1788     {
1789         return pblLinkedListRemoveAt( (PblLinkedList *)list, index );
1790     }
1791 
1792     return pblArrayListRemoveAt( (PblArrayList *)list, index );
1793 }
1794 
1795 /*
1796  * Removes from this list all of the elements whose index is between
1797  * fromIndex, inclusive and toIndex, exclusive.
1798  *
1799  * For linked lists removing from the beginning or the end of the list has a time complexity
1800  * of O(M), while removing from a random position in the middle of the list has a time
1801  * complexity of O(N + M) with N being the number of elements in the list
1802  * and M being the number of elements removed.
1803  *
1804  * @return int rc >= 0: The size of the list.
1805  * @return int rc <  0: An error, see pbl_errno:
1806  *
1807  * <BR>PBL_ERROR_OUT_OF_BOUNDS -  fromIndex is out of range (fromIndex < 0 || fromIndex >= size())
1808  *                         or toIndex is out of range ( toIndex < 0 || toIndex > size())
1809  */
pblLinkedListRemoveRange(PblLinkedList * list,int fromIndex,int toIndex)1810 static int pblLinkedListRemoveRange(
1811 PblLinkedList * list,     /** The list to use                              */
1812 int fromIndex,            /** The index of first element to be removed.    */
1813 int toIndex               /** The index after last element to be removed.  */
1814 )
1815 {
1816     int elementsToRemove = toIndex - fromIndex;
1817     int distanceToEnd = list->genericList.size - toIndex;
1818     PblLinkedNode * linkedNode;
1819 
1820     if( fromIndex <= distanceToEnd )
1821     {
1822         // Find the first node to remove from the beginning of the list
1823         // and remove forward
1824         //
1825         linkedNode = pblLinkedListGetNodeAt( list, fromIndex );
1826         if( !linkedNode )
1827         {
1828             return -1;
1829         }
1830 
1831         list->genericList.size -= elementsToRemove;
1832         while( elementsToRemove-- > 0 )
1833         {
1834             PblLinkedNode * nodeToFree = linkedNode;
1835             linkedNode = linkedNode->next;
1836 
1837             PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev );
1838             PBL_FREE( nodeToFree );
1839         }
1840     }
1841     else
1842     {
1843         // Find the last node to remove from the end of the list
1844         // and remove backward
1845         //
1846         linkedNode = pblLinkedListGetNodeAt( list, toIndex - 1 );
1847         if( !linkedNode )
1848         {
1849             return -1;
1850         }
1851 
1852         list->genericList.size -= elementsToRemove;
1853         while( elementsToRemove-- > 0 )
1854         {
1855             PblLinkedNode * nodeToFree = linkedNode;
1856             linkedNode = linkedNode->prev;
1857 
1858             PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev );
1859             PBL_FREE( nodeToFree );
1860         }
1861     }
1862 
1863     list->genericList.changeCounter++;
1864     return list->genericList.size;
1865 }
1866 
1867 /**
1868  * Removes from this list all of the elements whose index is between
1869  * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
1870  * elements to the left (reduces their index).
1871  * This call shortens the list by (toIndex - fromIndex) elements.
1872  * (If toIndex==fromIndex, this operation has no effect.)
1873  *
1874  * <B>Note:</B> No memory of the elements themselves is freed.
1875  *
1876  * For array lists removing from the end of the list has a time complexity
1877  * of O(M), while removing from the beginning of the list has a time
1878  * complexity of O(N + M) with N being the number of elements in the list
1879  * and M being the number of elements removed.
1880  *
1881  * For linked lists removing from the beginning or the end of the list has a time complexity
1882  * of O(M), while removing from a random position in the middle of the list has a time
1883  * complexity of O(N + M) with N being the number of elements in the list
1884  * and M being the number of elements removed.
1885  *
1886  * @return int rc >= 0: The size of the list.
1887  * @return int rc <  0: An error, see pbl_errno:
1888  *
1889  * <BR>PBL_ERROR_OUT_OF_BOUNDS  -  fromIndex is out of range (fromIndex < 0 || fromIndex >= size())
1890  *                          or toIndex is out of range ( toIndex < 0 || toIndex > size())
1891  */
pblListRemoveRange(PblList * list,int fromIndex,int toIndex)1892 int pblListRemoveRange(
1893 PblList * list,           /** The list to use                              */
1894 int fromIndex,            /** The index of first element to be removed.    */
1895 int toIndex               /** The index after last element to be removed.  */
1896 )
1897 {
1898     PblArrayList * pblList;
1899     int elementsToRemove;
1900 
1901     if( fromIndex < 0 || fromIndex >= list->size )
1902     {
1903         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1904         return -1;
1905     }
1906 
1907     if( toIndex < 0 || toIndex > list->size )
1908     {
1909         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
1910         return -1;
1911     }
1912 
1913     elementsToRemove = toIndex - fromIndex;
1914     if( elementsToRemove < 1 )
1915     {
1916         return list->size;
1917     }
1918 
1919     if( elementsToRemove == list->size )
1920     {
1921         pblListClear( list );
1922         return 0;
1923     }
1924 
1925     if( PBL_LIST_IS_LINKED_LIST( list ) )
1926     {
1927         return pblLinkedListRemoveRange( (PblLinkedList *)list, fromIndex, toIndex );
1928     }
1929 
1930     pblList = (PblArrayList *)list;
1931 
1932     if( toIndex < pblList->genericList.size )
1933     {
1934         unsigned char * to =
1935                 (unsigned char*)&( pblList->pointerArray[ fromIndex ] );
1936         unsigned char * from = to + elementsToRemove * sizeof(void*);
1937         int length = sizeof(void*) * ( pblList->genericList.size - toIndex );
1938 
1939         memmove( to, from, length );
1940     }
1941 
1942     if( elementsToRemove > 0 )
1943     {
1944         unsigned char * to =
1945                 (unsigned char*)&( pblList->pointerArray[ pblList->genericList.size
1946                         - elementsToRemove ] );
1947         int length = sizeof(void*) * elementsToRemove;
1948 
1949         memset( to, 0, length );
1950         pblList->genericList.size -= elementsToRemove;
1951     }
1952 
1953     pblList->genericList.changeCounter++;
1954 
1955     return pblList->genericList.size;
1956 }
1957 
1958 /**
1959  * Removes and returns the last element in this list.
1960  *
1961  * This method has a time complexity of O(1).
1962  *
1963  * @return void * retptr != (void*)-1: The last element in this list, may be NULL.
1964  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1965  *
1966  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
1967  */
pblListRemoveLast(PblList * list)1968 void * pblListRemoveLast(
1969 PblList * list         /** The list to use */
1970 )
1971 {
1972     return pblListRemoveAt( list, list->size - 1 );
1973 }
1974 
1975 /**
1976  * Removes and returns the first element in this list.
1977  *
1978  * For array lists this method has a time complexity of O(N),
1979  * with N being the size of the list.
1980  *
1981  * For linked lists this method has a time complexity of O(1).
1982  *
1983  * @return void * retptr != (void*)-1: The first element in this list, may be NULL.
1984  * @return void * retptr == (void*)-1: An error, see pbl_errno:
1985  *
1986  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
1987  */
pblListRemoveFirst(PblList * list)1988 void * pblListRemoveFirst(
1989 PblList * list         /** The list to use */
1990 )
1991 {
1992     return pblListRemoveAt( list, 0 );
1993 }
1994 
1995 /**
1996  * Returns the last element in this list.
1997  *
1998  * This method has a time complexity of O(1).
1999  *
2000  * @return void * retptr != (void*)-1: The last element in this list, may be NULL.
2001  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2002  *
2003  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2004  */
pblListGetLast(PblList * list)2005 void * pblListGetLast(
2006 PblList * list         /** The list to use */
2007 )
2008 {
2009     return pblListGet( list, list->size - 1 );
2010 }
2011 
2012 /**
2013  * Retrieves, but does not remove, the tail (last element) of this list.
2014  *
2015  * This method has a time complexity of O(1).
2016  *
2017  * @return void * retptr != (void*)-1: The last element in this list, may be NULL.
2018  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2019  *
2020  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2021  */
pblListTail(PblList * list)2022 void * pblListTail(
2023 PblList * list         /** The list to use */
2024 )
2025 {
2026     return pblListGet( list, list->size - 1 );
2027 }
2028 
2029 /**
2030  * Returns the first element in this list.
2031  *
2032  * This method has a time complexity of O(1).
2033  *
2034  * @return void * retptr != (void*)-1: The first element in this list, may be NULL.
2035  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2036  *
2037  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2038  */
pblListGetFirst(PblList * list)2039 void * pblListGetFirst(
2040 PblList * list          /** The list to use */
2041 )
2042 {
2043     return pblListGet( list, 0 );
2044 }
2045 
2046 /**
2047  * Returns the element at the specified position in this list.
2048  *
2049  * For array lists this method has a time complexity of O(1).
2050  *
2051  * For linked lists this method has a time complexity of O(N),
2052  * with N being the minimum of the differences between index and
2053  * 0 or index and the size of the list. Therefore retrieving the first
2054  * or last element has a time complexity of O(1),
2055  * but retrieving a random element from the list has O(N).
2056  *
2057  * @return void * retptr != (void*)-1: The element at the specified position in this list, may be NULL.
2058  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2059  *
2060  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
2061  */
pblListGet(PblList * list,int index)2062 void * pblListGet(
2063 PblList * list,     /** The list to use                */
2064 int index           /** Index of the element to return */
2065 )
2066 {
2067     /*
2068      * Check the parameter
2069      */
2070     if( index < 0 || index >= list->size )
2071     {
2072         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
2073         return (void*)-1;
2074     }
2075 
2076     if( PBL_LIST_IS_LINKED_LIST( list ) )
2077     {
2078         PblLinkedNode * linkedNode = pblLinkedListGetNodeAt( (PblLinkedList *)list, index );
2079         if( !linkedNode )
2080         {
2081             return (void*)-1;
2082         }
2083         return linkedNode->element;
2084     }
2085     else
2086     {
2087         PblArrayList * pblList = (PblArrayList *)list;
2088         return pblList->pointerArray[ index ];
2089     }
2090 }
2091 
2092 /**
2093  * Retrieves, but does not remove, the head (first element) of this list.
2094  *
2095  * This method has a time complexity of O(1).
2096  *
2097  * @return void * retptr != (void*)-1: The first element of this list, may be NULL.
2098  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2099  *
2100  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2101  */
pblListPeek(PblList * list)2102 void * pblListPeek(
2103 PblList * list      /** The list to use */
2104 )
2105 {
2106     return pblListGet( list, 0 );
2107 }
2108 
2109 /**
2110  * Retrieves, but does not remove, the tail (last element) of this list.
2111  *
2112  * This method has a time complexity of O(1).
2113  *
2114  * @return void * retptr != (void*)-1: The last element of this list, may be NULL.
2115  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2116  *
2117  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2118  */
pblListTop(PblList * list)2119 void * pblListTop(
2120 PblList * list     /** The list to use */
2121 )
2122 {
2123     return pblListGet( list, list->size - 1 );
2124 }
2125 
2126 /**
2127  * Retrieves and removes the tail (last element) of this list.
2128  *
2129  * This method has a time complexity of O(1).
2130  *
2131  * @return void * retptr != (void*)-1: The last element of this list, may be NULL.
2132  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2133  *
2134  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2135  */
pblListPop(PblList * list)2136 void * pblListPop(
2137 PblList * list     /** The list to use */
2138 )
2139 {
2140     return pblListRemoveAt( list, list->size - 1 );
2141 }
2142 
2143 /**
2144  * Retrieves and removes the head (first element) of this list.
2145  *
2146  * For array lists this method has a time complexity of O(N),
2147  * with N being the size of the list.
2148  *
2149  * For linked lists this method has a time complexity of O(1).
2150  *
2151  * @return void * retptr != (void*)-1: The head of this list, may be NULL.
2152  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2153  *
2154  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2155  */
pblListPoll(PblList * list)2156 void * pblListPoll(
2157 PblList * list      /** The list to use                */
2158 )
2159 {
2160     return pblListRemoveAt( list, 0 );
2161 }
2162 
2163 /**
2164  * Retrieves, but does not remove, the head (first element) of this list.
2165  *
2166  * This method has a time complexity of O(1).
2167  *
2168  * @return void * retptr != (void*)-1: The first element of this list, may be NULL.
2169  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2170  *
2171  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2172  */
pblListElement(PblList * list)2173 void * pblListElement(
2174 PblList * list         /** The list to use  */
2175 )
2176 {
2177     return pblListGet( list, 0 );
2178 }
2179 
2180 /**
2181  * Retrieves, but does not remove, the head (first element) of this list.
2182  *
2183  * This method has a time complexity of O(1).
2184  *
2185  * @return void * retptr != (void*)-1: The first element of this list, may be NULL.
2186  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2187  *
2188  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2189  */
pblListHead(PblList * list)2190 void * pblListHead(
2191 PblList * list         /** The list to use  */
2192 )
2193 {
2194     return pblListGet( list, 0 );
2195 }
2196 
2197 /**
2198  * Replaces the head (first element) of this list.
2199  *
2200  * This method has a time complexity of O(1).
2201  *
2202  * @return void * retptr != (void*)-1: The first element of this list before this call, may be NULL.
2203  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2204  *
2205  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2206  */
pblListSetFirst(PblList * list,void * element)2207 void * pblListSetFirst(
2208 PblList * list,         /** The list to use                            */
2209 void    * element       /** Element to be stored at the first position */
2210 )
2211 {
2212     return pblListSet( list, 0, element );
2213 }
2214 
2215 /**
2216  * Replaces the tail (last element) of this list.
2217  *
2218  * This method has a time complexity of O(1).
2219  *
2220  * @return void * retptr != (void*)-1: The last element of this list before this call, may be NULL.
2221  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2222  *
2223  * <BR>PBL_ERROR_OUT_OF_BOUNDS - this list is empty.
2224  */
pblListSetLast(PblList * list,void * element)2225 void * pblListSetLast(
2226 PblList * list,        /** The list to use                           */
2227 void    * element      /** Element to be stored at the last position */
2228 )
2229 {
2230     return pblListSet( list, list->size - 1, element );
2231 }
2232 
2233 /**
2234  * Replaces the element at the specified position in this list with the specified element.
2235  *
2236  * For array lists this method has a time complexity of O(1).
2237  *
2238  * For linked lists this method has a time complexity of O(N),
2239  * with N being the minimum of the differences between index and
2240  * 0 or index and the size of the list. Therefore changing the first
2241  * or last element has a time complexity of O(1),
2242  * but changing a random element from the list has O(N).
2243  *
2244  * @return void * retptr != (void*)-1: The element previously at the specified position, may be NULL.
2245  * @return void * retptr == (void*)-1: An error, see pbl_errno:
2246  *
2247  * <BR>PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()).
2248  */
pblListSet(PblList * list,int index,void * element)2249 void * pblListSet(
2250 PblList * list,    /** The list to use                                */
2251 int index,         /** Index of element to replace                    */
2252 void * element     /** Element to be stored at the specified position */
2253 )
2254 {
2255     unsigned char * result;
2256 
2257     if( index < 0 || index >= list->size )
2258     {
2259         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
2260         return (void*)-1;
2261     }
2262 
2263     if( PBL_LIST_IS_LINKED_LIST( list ) )
2264     {
2265         PblLinkedNode * linkedNode = pblLinkedListGetNodeAt( (PblLinkedList *)list, index );
2266         if( !linkedNode )
2267         {
2268             return (void*)-1;
2269         }
2270 
2271         result = (unsigned char *)linkedNode->element;
2272         linkedNode->element = element;
2273         return result;
2274     }
2275     else
2276     {
2277         PblArrayList * pblList = (PblArrayList *)list;
2278         result = pblList->pointerArray[ index ];
2279         pblList->pointerArray[ index ] = (unsigned char *)element;
2280         return result;
2281     }
2282 }
2283 
2284 /**
2285  * Sets an application specific compare function for the elements
2286  * of the list.
2287  *
2288  * An application specific compare function can be set to the list.
2289  * If no specific compare function is specified by the user,
2290  * the default compare function is used.
2291  * The default compare function compares the two pointers directly,
2292  * i.e. it tests for object identity.
2293  *
2294  * The compare function specified should behave like the one that
2295  * can be specified for the C-library function 'qsort'.
2296  *
2297  * The arguments actually passed to the compare function when it is called
2298  * are addresses of the element pointers added to the list.
2299  * E.g.: If you add char * pointers to the list, the compare function
2300  * will be called with char ** pointers as arguments. See the documentation
2301  * for the C-library function 'qsort' for further information.
2302  *
2303  * This method has a time complexity of O(1).
2304  *
2305  * @return * retptr: The compare function used before, may be NULL.
2306  */
pblListSetCompareFunction(PblList * list,int (* compare)(const void * prev,const void * next))2307 void * pblListSetCompareFunction(
2308 PblList * list,              /** The list to set compare function for   */
2309 int ( *compare )             /** The compare function to set            */
2310     (
2311         const void* prev,    /** The "left" element for compare         */
2312         const void* next     /** The "right" element for compare        */
2313     )
2314 )
2315 {
2316     void * retptr = list->compare;
2317 
2318     list->compare = compare;
2319 
2320     return retptr;
2321 }
2322 
2323 /**
2324  * Gets the application specific compare function for the elements
2325  * of the list.
2326  *
2327  * This method has a time complexity of O(1).
2328  *
2329  * @return void * retptr: The compare function used, may be NULL.
2330  */
pblListGetCompareFunction(PblList * list)2331 void * pblListGetCompareFunction(
2332 PblList * list         /** The list to get the compare function for   */
2333 )
2334 {
2335     return list->compare;
2336 }
2337 
2338 /*
2339  * Sorts the elements of the array list.
2340  *
2341  * This method uses the C library function 'qsort',
2342  * therefore it normally has a time complexity of O( N * Log(N) ),
2343  * with N being he size of the list to sort.
2344  *
2345  * @return int rc == 0: Ok.
2346  * @return int rc <  0: An error, see pbl_errno:
2347  *
2348  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
2349  */
pblArrayListSort(PblArrayList * list,int (* compare)(const void * prev,const void * next))2350 static int pblArrayListSort(
2351 PblArrayList * list,         /** The list to sort                       */
2352 int ( *compare )             /** Specific compare function to use       */
2353     (
2354         const void* prev,    /** "left" element for compare             */
2355         const void* next     /** "right" element for compare            */
2356     )
2357 )
2358 {
2359     if( list->genericList.size < 2 )
2360     {
2361         return 0;
2362     }
2363 
2364     qsort( list->pointerArray, (size_t)list->genericList.size,
2365            (size_t)sizeof(void*), ( compare ? compare
2366                    : list->genericList.compare ? list->genericList.compare
2367                            : pblCollectionDefaultCompare ) );
2368 
2369     list->genericList.changeCounter++;
2370     return 0;
2371 }
2372 
2373 /*
2374  * Sorts the elements of the linked list.
2375  *
2376  * This method uses the C library function 'qsort',
2377  * therefore it normally has a time complexity of O( N * Log(N) ),
2378  * with N being he size of the list to sort.
2379  *
2380  * This method has a memory complexity of O(N).
2381  *
2382  * @return int rc == 0: Ok.
2383  * @return int rc <  0: An error, see pbl_errno:
2384  *
2385  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
2386  */
pblLinkedListSort(PblLinkedList * list,int (* compare)(const void * prev,const void * next))2387 static int pblLinkedListSort(
2388 PblLinkedList * list,        /** The list to sort                       */
2389 int ( *compare )             /** Specific compare function to use       */
2390     (
2391         const void* prev,    /** "left" element for compare             */
2392         const void* next     /** "right" element for compare            */
2393     )
2394 )
2395 {
2396     PblLinkedNode * node = list->head;
2397     void ** array;
2398     void ** arrayPointer;
2399 
2400     if( list->genericList.size < 2 )
2401     {
2402         return 0;
2403     }
2404 
2405     array = pblLinkedListToArray( list );
2406     if( !array )
2407     {
2408         // Out of memory.
2409         //
2410         return -1;
2411     }
2412 
2413     arrayPointer = array;
2414     qsort( array, (size_t)list->genericList.size, (size_t)sizeof(void*),
2415            ( compare ? compare
2416                    : list->genericList.compare ? list->genericList.compare
2417                            : pblCollectionDefaultCompare ) );
2418 
2419     while( node )
2420     {
2421         node->element = *arrayPointer++;
2422         node = node->next;
2423     }
2424     PBL_FREE(array);
2425 
2426     list->genericList.changeCounter++;
2427     return 0;
2428 }
2429 
2430 /**
2431  * Sorts the elements of the list.
2432  *
2433  * A specific compare function can be used for the sort.
2434  *
2435  * If NULL is specific as specific compare function, the compare
2436  * function set for the list will be used if any, otherwise the
2437  * default compare function is used.
2438  *
2439  * The default compare function compares the two pointers directly.
2440  *
2441  * The compare function specified should behave like the one that
2442  * can be specified for the C-library function 'qsort'.
2443  *
2444  * This method uses the C library function 'qsort',
2445  * therefore it normally has a time complexity of O( N * Log(N) ),
2446  * with N being he size of the list to sort.
2447  *
2448  * For linked lists this method has a memory complexity of O(N).
2449  * For array lists this method does not need memory.
2450  *
2451  * @return int rc == 0: Ok.
2452  * @return int rc <  0: An error, see pbl_errno:
2453  *
2454  * <BR>PBL_ERROR_OUT_OF_MEMORY           - Out of memory.
2455  */
pblListSort(PblList * list,int (* compare)(const void * prev,const void * next))2456 int pblListSort(
2457 PblList * list,              /** The list to sort                       */
2458 int ( *compare )             /** Specific compare function to use       */
2459     (
2460         const void* prev,    /** "left" element for compare             */
2461         const void* next    /** "right" element for compare            */
2462     )
2463 )
2464 {
2465     if( PBL_LIST_IS_ARRAY_LIST( list ) )
2466     {
2467         return pblArrayListSort( (PblArrayList*)list, compare );
2468     }
2469 
2470     return pblLinkedListSort( (PblLinkedList*)list, compare );
2471 }
2472 
2473 /*
2474  * Searches for the first occurence of the given argument.
2475  *
2476  * This method has a time complexity of O(N),
2477  * with N being the size of the list.
2478  *
2479  * @return int rc >= 0: The index of the specified element.
2480  * @return int rc <  0: The specified element is not present.
2481  */
pblLinkedListIndexOf(PblLinkedList * list,void * element)2482 static int pblLinkedListIndexOf(
2483 PblLinkedList * list,     /** The list to use      */
2484 void * element            /** Element to look for  */
2485 )
2486 {
2487     int index = 0;
2488     PblLinkedNode * linkedNode = list->head;
2489 
2490     while( linkedNode )
2491     {
2492         if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) )
2493         {
2494             return index;
2495         }
2496         linkedNode = linkedNode->next;
2497         index++;
2498     }
2499 
2500     return -1;
2501 }
2502 
2503 /*
2504  * Searches for the first occurence of the given argument.
2505  *
2506  * This method has a time complexity of O(N),
2507  * with N being the size of the list.
2508  *
2509  * @return int rc >= 0: The index of the specified element.
2510  * @return int rc <  0: The specified element is not present.
2511  */
pblArrayListIndexOf(PblArrayList * list,void * element)2512 static int pblArrayListIndexOf(
2513 PblArrayList * list, /** The list to use      */
2514 void * element       /** Element to look for  */
2515 )
2516 {
2517     int index;
2518 
2519     for( index = 0; index < list->genericList.size; index++ )
2520     {
2521         if( !pblCollectionElementCompare( (PblCollection*)list, element, list->pointerArray[ index ] ) )
2522         {
2523             return index;
2524         }
2525     }
2526 
2527     return -1;
2528 }
2529 
2530 /**
2531  * Searches for the first occurence of the given argument.
2532  *
2533  * This method has a time complexity of O(N),
2534  * with N being the size of the list.
2535  *
2536  * @return int rc >= 0: The index of the specified element.
2537  * @return int rc <  0: The specified element is not present.
2538  */
pblListIndexOf(PblList * list,void * element)2539 int pblListIndexOf(
2540 PblList * list,              /** The list to use      */
2541 void * element               /** Element to look for  */
2542 )
2543 {
2544     if( PBL_LIST_IS_LINKED_LIST( list ) )
2545     {
2546         return pblLinkedListIndexOf( (PblLinkedList*)list, element );
2547     }
2548 
2549     return pblArrayListIndexOf( (PblArrayList*)list, element );
2550 }
2551 
2552 /*
2553  * Searches for the last occurence of the given argument.
2554  *
2555  * This method has a time complexity of O(N),
2556  * with N being the size of the list.
2557  *
2558  * @return int rc >= 0: The last index of the specified element.
2559  * @return int rc <  0: The specified element is not present.
2560  */
pblLinkedListLastIndexOf(PblLinkedList * list,void * element)2561 static int pblLinkedListLastIndexOf(
2562 PblLinkedList * list,        /** The list to use                        */
2563 void * element               /** Element to look for                    */
2564 )
2565 {
2566     int index = list->genericList.size - 1;
2567     PblLinkedNode * linkedNode = list->tail;
2568 
2569     while( linkedNode )
2570     {
2571         if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) )
2572         {
2573             return index;
2574         }
2575         linkedNode = linkedNode->prev;
2576         index--;
2577     }
2578 
2579     return -1;
2580 }
2581 
2582 /*
2583  * Searches for the last occurence of the given argument.
2584  *
2585  * This method has a time complexity of O(N),
2586  * with N being the size of the list.
2587  *
2588  * @return int rc >= 0: The last index of the specified element.
2589  * @return int rc <  0: The specified element is not present.
2590  */
pblArrayListLastIndexOf(PblArrayList * list,void * element)2591 static int pblArrayListLastIndexOf(
2592 PblArrayList * list,         /** The list to use                        */
2593 void * element               /** Element to look for                    */
2594 )
2595 {
2596     int index;
2597 
2598     for( index = list->genericList.size - 1; index >= 0; index-- )
2599     {
2600         if( !pblCollectionElementCompare( (PblCollection*)list, element, list->pointerArray[ index ] ) )
2601         {
2602             return index;
2603         }
2604     }
2605 
2606     return -1;
2607 }
2608 
2609 /**
2610  * Searches for the last occurence of the given argument.
2611  *
2612  * This method has a time complexity of O(N),
2613  * with N being the size of the list.
2614  *
2615  * @return int rc >= 0: The last index of the specified element.
2616  * @return int rc <  0: The specified element is not present.
2617  */
pblListLastIndexOf(PblList * list,void * element)2618 int pblListLastIndexOf(
2619 PblList * list,           /** The list to use                        */
2620 void * element            /** Element to look for                    */
2621 )
2622 {
2623     if( PBL_LIST_IS_LINKED_LIST( list ) )
2624     {
2625         return pblLinkedListLastIndexOf( (PblLinkedList*)list, element );
2626     }
2627 
2628     return pblArrayListLastIndexOf( (PblArrayList*)list, element );
2629 }
2630 
2631 /**
2632  * Returns true if this list contains the specified element.
2633  *
2634  * This method has a time complexity of O(N),
2635  * with N being the size of the list.
2636  *
2637  * @return int rc != 0: The specified element is present.
2638  * @return int rc == 0: The specified element is not present.
2639  */
pblListContains(PblList * list,void * element)2640 int pblListContains(
2641 PblList * list,           /** The list to use                  */
2642 void * element            /** Element to look for              */
2643 )
2644 {
2645     return ( pblListIndexOf( list, element ) >= 0 );
2646 }
2647 
2648 /**
2649  * Returns a value > 0 if this list contains all of the elements
2650  * in the specified collection.
2651  *
2652  * This implementation iterates over the specified collection,
2653  * checking each element returned by the iterator in turn to see if it's contained in this list.
2654  * If all elements are so contained a value > 0 is returned, otherwise 0.
2655  *
2656  * This method has a time complexity of O(N * M),
2657  * with N being the size of the list and M being the size of the
2658  * collection.
2659  *
2660  * @return int rc >  0: The list contains all of the elements in the specified collection.
2661  * @return int rc == 0: The list does not contain all of the elements.
2662  * @return int rc <  0: An error, see pbl_errno:
2663  *
2664  * <BR>PBL_ERROR_PARAM_COLLECTION        - The collection cannot be iterated.
2665  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The collection was modified concurrently.
2666  */
pblListContainsAll(PblList * list,void * collection)2667 int pblListContainsAll(
2668 PblList * list,    /** The list to use                                            */
2669 void * collection  /** The collection to be checked for containment in this list. */
2670 )
2671 {
2672     PblIterator   iteratorBuffer;
2673     PblIterator * iterator = &iteratorBuffer;
2674     int iteratorSize;
2675     int hasNext;
2676 
2677     if( pblIteratorInit( collection, iterator ) < 0 )
2678     {
2679         return -1;
2680     }
2681 
2682     iteratorSize = pblIteratorSize( iterator );
2683     if( iteratorSize < 1 )
2684     {
2685         return 1;
2686     }
2687 
2688     while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
2689     {
2690         void * element = pblIteratorNext( iterator );
2691         if( element == (void*)-1 )
2692         {
2693             // concurrent modification on the collection
2694             //
2695             return -1;
2696         }
2697         if( !pblListContains( list, element ) )
2698         {
2699             return 0;
2700         }
2701     }
2702     if( hasNext < 0 )
2703     {
2704         // concurrent modification on the collection
2705         //
2706         return -1;
2707     }
2708 
2709     return 1;
2710 }
2711 
2712 /*
2713  * Removes or retains from this array list all of its elements
2714  * that are contained in the specified collection.
2715  *
2716  * @return int rc >  0: If this list changed as a result of the call.
2717  * @return int rc == 0: This list did not change.
2718  * @return int rc <  0: An error, see pbl_errno:
2719  *
2720  * <BR>PBL_ERROR_PARAM_LIST - The list cannot be iterated.
2721  */
pblArrayListRemoveRetainAll(PblArrayList * list,PblCollection * collection,int doRemove)2722 static int pblArrayListRemoveRetainAll(
2723 PblArrayList  * list,       /** The list to use                        */
2724 PblCollection * collection, /** The collection to use                  */
2725 int       doRemove          /** Flag: do a remove or a retain          */
2726 )
2727 {
2728     int index = 0;
2729     int newIndex = 0;
2730     void * element;
2731     int isContained;
2732 
2733     for( index = 0; index < list->genericList.size; index++ )
2734     {
2735         element = list->pointerArray[ index ];
2736         isContained = pblCollectionContains( collection, element );
2737 
2738         if( ( doRemove && !isContained ) || ( !doRemove && isContained ) )
2739         {
2740             if( newIndex != index )
2741             {
2742                 list->pointerArray[ newIndex++ ] = element;
2743             }
2744             else
2745             {
2746                 newIndex++;
2747             }
2748         }
2749     }
2750 
2751     if( newIndex != index )
2752     {
2753         if( pblArrayListSetSize( list, newIndex ) != newIndex )
2754         {
2755             return -1;
2756         }
2757         return 1;
2758     }
2759 
2760     return 0;
2761 }
2762 
2763 /*
2764  * Removes or retains from this linked list all of its elements
2765  * that are contained in the specified collection.
2766  *
2767  * @return int rc >  0: If this list changed as a result of the call.
2768  * @return int rc == 0: This list did not change.
2769  * @return int rc <  0: An error, see pbl_errno:
2770  *
2771  * <BR>PBL_ERROR_PARAM_LIST              - The list cannot be iterated.
2772  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently.
2773  */
pblLinkedListRemoveRetainAll(PblLinkedList * list,PblCollection * collection,int doRemove)2774 static int pblLinkedListRemoveRetainAll(
2775 PblLinkedList * list,       /** The list to use                        */
2776 PblCollection * collection, /** The collection to use                  */
2777 int       doRemove          /** Flag: do a remove or a retain          */
2778 )
2779 {
2780     PblIterator   iteratorBuffer;
2781     PblIterator * iterator = &iteratorBuffer;
2782     int rc = 0;
2783     int hasNext;
2784     void * element;
2785     int isContained;
2786 
2787     /*
2788      * Get the iterator for this list
2789      */
2790     if( pblIteratorInit( (PblCollection *)list, iterator ) < 0 )
2791     {
2792         pbl_errno = PBL_ERROR_PARAM_LIST;
2793         return -1;
2794     }
2795 
2796     while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
2797     {
2798         element = pblIteratorNext( iterator );
2799         if( element == (void*)-1 )
2800         {
2801             // Concurrent modification
2802             //
2803             return -1;
2804         }
2805 
2806         isContained = pblCollectionContains( collection, element );
2807 
2808         if( ( doRemove && isContained ) || ( !doRemove && !isContained ) )
2809         {
2810             if( pblIteratorRemove( iterator ) < 0 )
2811             {
2812                 return -1;
2813             }
2814 
2815             /*
2816              * The list changed
2817              */
2818             rc = 1;
2819         }
2820     }
2821     if( hasNext < 0 )
2822     {
2823         // Concurrent modification
2824         //
2825         return -1;
2826     }
2827 
2828     return rc;
2829 }
2830 
2831 /**
2832  * Removes from this list all of its elements
2833  * that are contained in the specified collection.
2834  *
2835  * This implementation iterates over this list,
2836  * checking each element returned by the iterator in turn
2837  * to see if it's contained in the specified collection.
2838  *
2839  * If it's so contained, it's removed from this list
2840  * with the iterator's remove method in case of a linked list
2841  * and with an optimized direct removal method in case of
2842  * an array list.
2843  *
2844  * This method has a time complexity of O(N * M),
2845  * with N being the size of the list and M being the size of the
2846  * collection.
2847  *
2848  * @return int rc >  0: If this list changed as a result of the call.
2849  * @return int rc == 0: This list did not change.
2850  * @return int rc <  0: An error, see pbl_errno:
2851  *
2852  * <BR>PBL_ERROR_PARAM_LIST              - The list be iterated.
2853  * <BR>PBL_ERROR_PARAM_COLLECTION        - The collection cannot be iterated.
2854  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently.
2855  */
pblListRemoveAll(PblList * list,void * collection)2856 int pblListRemoveAll(
2857 PblList * list,    /** The list to use                                                 */
2858 void * collection  /** The collection whose elements are to be removed from this list. */
2859 )
2860 {
2861     PblIterator   iteratorBuffer;
2862     PblIterator * iterator = &iteratorBuffer;
2863     int iteratorSize;
2864 
2865     if( list->size < 1 )
2866     {
2867         return 0;
2868     }
2869 
2870     /*
2871      * Get the iterator for the collection
2872      */
2873     if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 )
2874     {
2875         return -1;
2876     }
2877 
2878     iteratorSize = pblIteratorSize( iterator );
2879     if( iteratorSize < 1 )
2880     {
2881         return 0;
2882     }
2883 
2884     if( PBL_LIST_IS_ARRAY_LIST( list ) )
2885     {
2886         return pblArrayListRemoveRetainAll( (PblArrayList*)list, (PblCollection *)collection, 1 );
2887     }
2888 
2889     return pblLinkedListRemoveRetainAll( (PblLinkedList*)list, (PblCollection *)collection, 1 );
2890 }
2891 
2892 /**
2893  * Retains only the elements in this list
2894  * that are contained in the specified collection.
2895  *
2896  * In other words, removes from this list all
2897  * of its elements that are not contained in the specified collection.
2898  *
2899  * This implementation iterates over this list,
2900  * checking each element returned by the iterator in turn
2901  * to see if it's contained in the specified collection.
2902  *
2903  * If it's not so contained, it's removed from this list
2904  * with the iterator's remove method in case of a linked list
2905  * and with an optimized direct removal method in case of
2906  * an array list.
2907  *
2908  * This method has a time complexity of O(N * M),
2909  * with N being the size of the list and M being the size of the
2910  * collection.
2911  *
2912  * @return int rc >  0: If this list changed as a result of the call.
2913  * @return int rc == 0: This list did not change.
2914  * @return int rc <  0: An error, see pbl_errno:
2915  *
2916  * <BR>PBL_ERROR_PARAM_LIST              - The list cannot be iterated.
2917  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently.
2918  * <BR>PBL_ERROR_PARAM_COLLECTION        - The collection cannot be iterated.
2919  */
pblListRetainAll(PblList * list,void * collection)2920 int pblListRetainAll(
2921 PblList * list,           /** The list to use                           */
2922 void * collection         /** The elements to be retained in this list. */
2923 )
2924 {
2925     PblIterator   iteratorBuffer;
2926     PblIterator * iterator = &iteratorBuffer;
2927     int iteratorSize;
2928 
2929     if( list->size < 1 )
2930     {
2931         return 0;
2932     }
2933 
2934     /*
2935      * Get the iterator for the collection
2936      */
2937     if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 )
2938     {
2939         return -1;
2940     }
2941 
2942     iteratorSize = pblIteratorSize( iterator );
2943     if( iteratorSize < 0 )
2944     {
2945         return -1;
2946     }
2947 
2948     /*
2949      * Get the iterator for this list
2950      */
2951     if( pblIteratorInit( list, iterator ) < 0 )
2952     {
2953         return -1;
2954     }
2955 
2956     if( iteratorSize == 0 )
2957     {
2958         if( pblIteratorSize( iterator ) == 0 )
2959         {
2960             return 0;
2961         }
2962 
2963         /*
2964          * Clear the entire list
2965          */
2966         pblListClear( list );
2967         return 1;
2968     }
2969 
2970     if( PBL_LIST_IS_ARRAY_LIST( list ) )
2971     {
2972         return pblArrayListRemoveRetainAll( (PblArrayList*)list, (PblCollection *)collection, 0 );
2973     }
2974 
2975     return pblLinkedListRemoveRetainAll( (PblLinkedList*)list, (PblCollection *)collection, 0 );
2976 }
2977 
2978 /*
2979  * Removes a single instance of the specified element from this
2980  * linked list, if it is present.
2981  *
2982  * This method has a time complexity of O(N),
2983  * with N being the size of the list.
2984  *
2985  * @return int rc != 0: The list contained the specified element.
2986  * @return int rc == 0: The specified element is not present.
2987  */
pblLinkedListRemoveElement(PblLinkedList * list,void * element)2988 static int pblLinkedListRemoveElement(
2989 PblLinkedList * list,      /** The list to use                        */
2990 void * element             /** Element to remove                      */
2991 )
2992 {
2993     PblLinkedNode * nodeToFree = pblLinkedListGetNode( list, element );
2994     if( !nodeToFree )
2995     {
2996         return 0;
2997     }
2998 
2999     PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev );
3000     list->genericList.size--;
3001     list->genericList.changeCounter++;
3002 
3003     PBL_FREE( nodeToFree );
3004 
3005     return 1;
3006 }
3007 
3008 /**
3009  * Removes a single instance of the specified element from this list,
3010  * if it is present.
3011  *
3012  * More formally, removes an element e such that
3013  * (o==null ? e==null : o.equals(e)),
3014  * if the list contains one or more such elements.
3015  * Returns true if the list contained the specified
3016  * element (or equivalently, if the list changed as
3017  * a result of the call).
3018  *
3019  * This method has a time complexity of O(N),
3020  * with N being the size of the list.
3021  *
3022  * @return int rc != 0: The list contained the specified element.
3023  * @return int rc == 0: The specified element is not present.
3024  */
pblListRemoveElement(PblList * list,void * element)3025 int pblListRemoveElement(
3026 PblList * list,            /** The list to use                    */
3027 void * element             /** The element to remove              */
3028 )
3029 {
3030     int index;
3031 
3032     if( PBL_LIST_IS_LINKED_LIST( list ) )
3033     {
3034         return pblLinkedListRemoveElement( (PblLinkedList*)list, element );
3035     }
3036 
3037     index = pblListIndexOf( list, element );
3038     if( index >= 0 )
3039     {
3040         pblArrayListRemoveAt( (PblArrayList*)list, index );
3041         return 1;
3042     }
3043     return 0;
3044 }
3045 
3046 /*
3047  * Returns an array containing all of the elements in this linked list in the correct order.
3048  *
3049  * This method has a time complexity of O(N),
3050  * with N being the size of the list.
3051  *
3052  * @return void * retptr != NULL: The array containing the elements of the list.
3053  * @return void * retptr == NULL: An error, see pbl_errno:
3054  *
3055  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
3056  * <BR>PBL_ERROR_OUT_OF_BOUNDS - The list is empty.
3057  */
pblLinkedListToArray(PblLinkedList * list)3058 static void ** pblLinkedListToArray(
3059 PblLinkedList * list         /** The list to use */
3060 )
3061 {
3062     PblLinkedNode * linkedNode = list->head;
3063     void ** arrayPointer;
3064     void ** resultArray;
3065 
3066     resultArray = (void **)pbl_malloc( "pblLinkedListToArray", sizeof(void*)
3067             * list->genericList.size );
3068     if( !resultArray )
3069     {
3070         return NULL;
3071     }
3072 
3073     arrayPointer = resultArray;
3074     while( linkedNode )
3075     {
3076         *arrayPointer++ = linkedNode->element;
3077         linkedNode = linkedNode->next;
3078     }
3079 
3080     return resultArray;
3081 }
3082 
3083 /**
3084  * Returns an array containing all of the elements in this list in the correct order.
3085  *
3086  * <B>Note:</B> The pointer array returned is malloced from heap, the caller has to free it
3087  * after it is no longer needed!
3088  *
3089  * The size of the pointer array malloced and returned is defined by the pblListSize()
3090  * of the list.
3091  *
3092  * This method has a time complexity of O(N),
3093  * with N being the size of the list.
3094  *
3095  * @return void * retptr != NULL: The array containing the elements of the list.
3096  * @return void * retptr == NULL: An error, see pbl_errno:
3097  *
3098  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
3099  * <BR>PBL_ERROR_OUT_OF_BOUNDS - The list is empty.
3100  */
pblListToArray(PblList * list)3101 void ** pblListToArray(
3102 PblList * list           /** The list to use */
3103 )
3104 {
3105     if( list->size == 0 )
3106     {
3107         pbl_errno = PBL_ERROR_OUT_OF_BOUNDS;
3108         return NULL;
3109     }
3110 
3111     if( PBL_LIST_IS_LINKED_LIST( list ) )
3112     {
3113         return pblLinkedListToArray( (PblLinkedList*)list );
3114     }
3115     else
3116     {
3117         PblArrayList * pblList = (PblArrayList *)list;
3118 
3119         return (void **)pbl_memdup( "pblListToArray", pblList->pointerArray, sizeof(void*)
3120                 * pblList->genericList.size );
3121     }
3122 }
3123 
3124 /**
3125  * Compares the specified collection with this list for equality.
3126  *
3127  * Returns true if and only if the specified collection is a collection,
3128  * both collections have the same size, and all corresponding pairs of
3129  * elements in the two collections are equal. (Two elements e1 and e2
3130  * are equal if (e1==null ? e2==null : compare( e1, e2 )==0.)
3131  *
3132  * In other words, two collections are defined to be equal as lists
3133  * if they contain the same elements in the same order.
3134  *
3135  * This implementation first checks if the specified collection is this list.
3136  * If so, it returns true; if not, it checks if the specified collection is a list or a tree set.
3137  * If not, it returns false; if so, it iterates over both collections,
3138  * comparing corresponding pairs of elements by using the compare function of this list.
3139  * If any comparison returns false, this method returns false.
3140  * If either iterator runs out of elements before the other it returns false (as the lists are of unequal length);
3141  * otherwise it returns true when the iterations complete.
3142  *
3143  * This method has a time complexity of O(Min(N,M)),
3144  * with N being the size of the list and M being the
3145  * number of elements in the object compared.
3146  *
3147  * @return int rc >  0: The specified collection is equal to this list.
3148  * @return int rc == 0: The specified collection is not equal to this list.
3149  * @return int rc <  0: An error, see pbl_errno:
3150  *
3151  * <BR>PBL_ERROR_PARAM_LIST              - The list or collection cannot be iterated.
3152  * <BR>PBL_ERROR_CONCURRENT_MODIFICATION - The list or collection was modified concurrently.
3153  */
pblListEquals(PblList * list,void * collection)3154 int pblListEquals(
3155 PblList * list,   /** The list to compare with.                                  */
3156 void * collection /** The collection to be compared for equality with this list. */
3157 )
3158 {
3159     PblIterator iteratorBuffer;
3160     PblIterator * iterator = &iteratorBuffer;
3161 
3162     PblIterator thisIteratorBuffer;
3163     PblIterator * thisIterator = &thisIteratorBuffer;
3164 
3165     int hasNext;
3166     int thisHasNext = 0;
3167     void * next;
3168     void * thisNext;
3169 
3170     if( list == collection )
3171     {
3172         return 1;
3173     }
3174 
3175     if( !PBL_COLLECTION_IS_COLLECTION( collection ) )
3176     {
3177         return 0;
3178     }
3179 
3180     if( pblIteratorInit( list, thisIterator ) < 0 )
3181     {
3182         return -1;
3183     }
3184 
3185     if( pblIteratorInit( collection, iterator ) < 0 )
3186     {
3187         return -1;
3188     }
3189 
3190     if( pblIteratorSize( iterator ) != pblIteratorSize( thisIterator ) )
3191     {
3192         return 0;
3193     }
3194 
3195     while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 )
3196     {
3197         if( ( thisHasNext = pblIteratorHasNext( thisIterator ) ) < 0 )
3198         {
3199             return -1;
3200         }
3201         if( thisHasNext == 0 )
3202         {
3203             return 0;
3204         }
3205 
3206         next = pblIteratorNext( iterator );
3207         if( next == (void*)-1 )
3208         {
3209             return -1;
3210         }
3211 
3212         thisNext = pblIteratorNext( thisIterator );
3213         if( thisNext == (void*)-1 )
3214         {
3215             return -1;
3216         }
3217 
3218         if( pblCollectionElementCompare( (PblCollection*)list, thisNext, next ) )
3219         {
3220             return 0;
3221         }
3222     }
3223     if( hasNext < 0 )
3224     {
3225         return -1;
3226     }
3227 
3228     if( ( thisHasNext = pblIteratorHasNext( thisIterator ) ) > 0 )
3229     {
3230         return 0;
3231     }
3232     if( thisHasNext < 0 )
3233     {
3234         return -1;
3235     }
3236 
3237     return 1;
3238 }
3239 
3240 /**
3241  * Returns an iterator over the elements in this list in proper sequence.
3242  *
3243  * The iterator starts the iteration at the beginning of the list.
3244  *
3245  * <B>Note</B>: The memory allocated by this method for the iterator returned needs to be released
3246  *              by calling pblIteratorFree() once the iterator is no longer needed.
3247  *
3248  * The iterators returned by the this method are fail-fast:
3249  * if the list is structurally modified at any time after the iterator is created,
3250  * in any way except through the Iterator's own remove or add methods,
3251  * the iterator will return a PBL_ERROR_CONCURRENT_MODIFICATION error.
3252  *
3253  * Thus, in the face of concurrent modification,
3254  * the iterator fails quickly and cleanly,
3255  * rather than risking arbitrary, non-deterministic
3256  * behavior at an undetermined time in the future.
3257  *
3258  * This method has a time complexity of O(1).
3259  *
3260  * @return void * retptr != NULL: The iterator.
3261  * @return void * retptr == NULL: An error, see pbl_errno:
3262  *
3263  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
3264  * <BR>PBL_ERROR_PARAM_LIST    - list cannot be iterated.
3265  */
pblListIterator(PblList * list)3266 PblIterator * pblListIterator(
3267 PblList * list                 /** The list to create the iterator for */
3268 )
3269 {
3270     if( !PBL_LIST_IS_LIST( list ) )
3271     {
3272         pbl_errno = PBL_ERROR_PARAM_LIST;
3273         return NULL;
3274     }
3275 
3276     return pblIteratorNew( list );
3277 }
3278 
3279 /**
3280  * Returns a reverse iterator over the elements in this list in proper sequence.
3281  *
3282  * The reverse iterator starts the iteration at the end of the list.
3283  *
3284  * <B>Note:</B> The memory allocated by this method for the iterator returned needs to be released
3285  *       by calling pblIteratorFree() once the iterator is no longer needed.
3286  *
3287  * The iterators returned by the this method are fail-fast:
3288  * if the list is structurally modified at any time after the iterator is created,
3289  * in any way except through the Iterator's own remove or add methods,
3290  * the iterator will return a PBL_ERROR_CONCURRENT_MODIFICATION error.
3291  *
3292  * Thus, in the face of concurrent modification,
3293  * the iterator fails quickly and cleanly,
3294  * rather than risking arbitrary, non-deterministic
3295  * behavior at an undetermined time in the future.
3296  *
3297  * This method has a time complexity of O(1).
3298  *
3299  * @return void * retptr != NULL: The iterator.
3300  * @return void * retptr == NULL: An error, see pbl_errno:
3301  *
3302  * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory.
3303  * <BR>PBL_ERROR_PARAM_LIST    - list cannot be iterated.
3304  */
pblListReverseIterator(PblList * list)3305 PblIterator * pblListReverseIterator(
3306 PblList * list                 /** The list to create the iterator for */
3307 )
3308 {
3309     if( !PBL_LIST_IS_LIST( list ) )
3310     {
3311         pbl_errno = PBL_ERROR_PARAM_LIST;
3312         return NULL;
3313     }
3314 
3315     return pblIteratorReverseNew( list );
3316 }
3317 
3318 
3319 
3320