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