/* pblList.c - C implementation of two Lists similar to the Java ArrayList and Java LinkedList. Copyright (C) 2009 Peter Graf This file is part of PBL - The Program Base Library. PBL is free software. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For more information on the Program Base Library or Peter Graf, please see: http://www.mission-base.com/. $Log: pblList.c,v $ Revision 1.40 2010/05/30 20:06:45 peter Removed warnings found by 'Microsoft Visual C++ 2010'. Revision 1.39 2009/03/11 23:48:44 peter More tests and clean up. Revision 1.38 2009/03/08 20:56:50 peter port to gcc (Ubuntu 4.3.2-1ubuntu12) 4.3.2. Exposing the hash set and tree set interfaces. Revision 1.21 2009/02/03 16:40:14 peter PBL vesion 1.04, optimizations, MAC OS X port, port to Microsoft Visual C++ 2008 Express Edition, exposing the array list and the linked list interface */ /* * Make sure "strings | grep Id | sort -u" shows the source file versions */ char* pblList_c_id = "$Id: pblList.c 70917 2014-12-08 23:34:40Z cxh $"; char * PblArrayListMagic = "PblArrayListMagic"; char * PblLinkedListMagic = "PblLinkedListMagic"; #include #ifndef PT_DOES_NOT_HAVE_MEMORY_H #include #endif #ifndef __APPLE__ #ifndef PT_DOES_NOT_HAVE_MALLOC_H #include #endif #endif #include #include "pbl.h" /*****************************************************************************/ /* #defines */ /*****************************************************************************/ #ifndef PBLAL_INITIAL_CAPACITY /* value might be set by compiler switch */ #define PBLAL_INITIAL_CAPACITY 10 /* default initial capacity */ #endif /*****************************************************************************/ /* Function declarations */ /*****************************************************************************/ static int pblLinkedListAdd( PblLinkedList * list, /** The list to append to */ void * element /** Element to be appended to this list */ ); static void * pblLinkedListRemoveAt( PblLinkedList * list, /** The list to use */ int index /** Index at which the element is to be removed */ ); static void ** pblLinkedListToArray( PblLinkedList * list /** The list to use */ ); static int pblLinkedListRemoveRange( PblLinkedList * list, /** The list to use */ int fromIndex, /** The index of first element to be removed. */ int toIndex /** The index after last element to be removed. */ ); static PblLinkedNode * pblLinkedListGetNodeAt( PblLinkedList * list, /** The list to use */ int index /** Index of the node to return */ ); static int pblLinkedListAddAt( PblLinkedList * list, /** The list to use */ int index, /** Index at which the element is to be inserted */ void * element /** Element to be appended to this list */ ); /*****************************************************************************/ /* Functions */ /*****************************************************************************/ /** * Creates a new array list. * * This method has a time complexity of O(1). * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ PblList * pblListNewArrayList( void ) { PblArrayList * pblList = (PblArrayList *)pbl_malloc0( "pblListNewArrayList", sizeof(PblArrayList) ); if( !pblList ) { return NULL; } pblList->genericList.magic = PblArrayListMagic; return (PblList *)pblList; } /** * Creates a new linked list. * * This method has a time complexity of O(1). * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ PblList * pblListNewLinkedList( void ) { PblLinkedList * pblList = (PblLinkedList *)pbl_malloc0( "pblListNewLinkedList", sizeof(PblLinkedList) ); if( !pblList ) { return NULL; } pblList->genericList.magic = PblLinkedListMagic; return (PblList *)pblList; } /* * Returns a shallow copy from this linked list of all of the elements * whose index is between fromIndex, inclusive and toIndex, exclusive. * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - fromIndex is out of range (fromIndex < 0 || fromIndex >= size()) * or toIndex is out of range ( toIndex < 0 || toIndex > size()) */ static PblList * pblLinkedListCloneRange( PblLinkedList * list, /** The list to use */ int fromIndex, /** The index of first element to be cloned. */ int toIndex /** The index after last element to be cloned. */ ) { int elementsToClone; int distanceToEnd; PblLinkedNode * linkedNode; PblLinkedList * newList = (PblLinkedList *)pblListNewLinkedList(); if( !newList ) { return NULL; } ( (PblLinkedList *)newList )->genericList.compare = list->genericList.compare; elementsToClone = toIndex - fromIndex; if( elementsToClone < 1 ) { return (PblList *)newList; } distanceToEnd = list->genericList.size - toIndex; if( fromIndex <= distanceToEnd ) { // Find the first node to clone from the beginning of the list // and clone forward // linkedNode = pblLinkedListGetNodeAt( list, fromIndex ); if( !linkedNode ) { pblListFree( (PblList *)newList ); return NULL; } while( elementsToClone-- > 0 ) { if( pblLinkedListAdd( newList, linkedNode->element ) < 0 ) { pblListFree( (PblList *)newList ); return NULL; } linkedNode = linkedNode->next; } } else { // Find the last node to clone from the end of the list // and clone backward // linkedNode = pblLinkedListGetNodeAt( list, toIndex - 1 ); if( !linkedNode ) { pblListFree( (PblList *)newList ); return NULL; } while( elementsToClone-- > 0 ) { if( pblLinkedListAddAt( newList, 0, linkedNode->element ) < 0 ) { pblListFree( (PblList *)newList ); return NULL; } linkedNode = linkedNode->prev; } } return (PblList *)newList; } /* * Returns a shallow copy from this array list of all of the elements * whose index is between fromIndex, inclusive and toIndex, exclusive. * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - fromIndex is out of range (fromIndex < 0 || fromIndex >= size()) * or toIndex is out of range ( toIndex < 0 || toIndex > size()) */ static PblList * pblArrayListCloneRange( PblArrayList * list, /** The list to use */ int fromIndex, /** The index of first element to be cloned. */ int toIndex /** The index after last element to be cloned. */ ) { int elementsToClone = toIndex - fromIndex; PblArrayList * newList = (PblArrayList *)pblListNewArrayList(); if( !newList ) { return NULL; } newList->genericList.compare = list->genericList.compare; if( elementsToClone < 1 ) { return (PblList*)newList; } newList->pointerArray = pbl_memdup( "pblArrayListCloneRange pointerArray", &( list->pointerArray[ fromIndex ] ), sizeof(void*) * elementsToClone ); if( !newList->pointerArray ) { PBL_FREE( newList ); return NULL; } newList->capacity = elementsToClone; newList->genericList.size = elementsToClone; return (PblList*)newList; } /** * Returns a shallow copy from this list of all of the elements * whose index is between fromIndex, inclusive and toIndex, exclusive. * * For array lists cloning has a time complexity * of O(M), with M being the number of elements cloned. * * For linked lists cloning from the beginning or the end of the list has a time complexity * of O(M) with M being the number of elements cloned, * while cloning from a random position in the middle of the list has a time * complexity of O(N) with N being the number of elements in the list. * * This method has a memory complexity of O(M), * with M being the number of elements cloned. * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - fromIndex is out of range (fromIndex < 0 || fromIndex >= size()) * or toIndex is out of range ( toIndex < 0 || toIndex > size()) or range is negative. */ PblList * pblListCloneRange( PblList * list, /** The list to use */ int fromIndex, /** The index of first element to be cloned. */ int toIndex /** The index after last element to be cloned. */ ) { int elementsToClone = toIndex - fromIndex; if( fromIndex < 0 || fromIndex > list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } if( toIndex < 0 || toIndex > list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } if( elementsToClone < 0 ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListCloneRange( (PblLinkedList *)list, fromIndex, toIndex ); } return pblArrayListCloneRange( (PblArrayList *)list, fromIndex, toIndex ); } /** * Returns a shallow copy of this list instance. * * The elements themselves are not copied. * * This method has a memory and time complexity of O(N), * with N being the number of elements in the list. * * @return PblList * retPtr != NULL: A pointer to the new list. * @return PblList * retPtr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ PblList * pblListClone( PblList * list /** The list to clone */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListCloneRange( (PblLinkedList *)list, 0, list->size ); } return pblArrayListCloneRange( (PblArrayList *)list, 0, list->size ); } /* * Removes all of the elements from this list. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ static void pblArrayListClear( PblArrayList * list /** The list to clear */ ) { if( list->genericList.size > 0 && list->pointerArray ) { memset( list->pointerArray, 0, sizeof(void*) * list->genericList.size ); } list->genericList.size = 0; list->genericList.changeCounter++; } /* * Removes all of the elements from this list. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ static void pblLinkedListClear( PblLinkedList * list /** The list to clear */ ) { while( list->head ) { PblLinkedNode * nodeToFree = list->head; PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev ); PBL_FREE( nodeToFree ); } list->genericList.size = 0; list->genericList.changeCounter++; } /** * Removes all of the elements from this list. * * Note: No memory of the elements themselves is freed. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ void pblListClear( PblList * list /** The list to clear */ ) { if( PBL_LIST_IS_ARRAY_LIST( list ) ) { pblArrayListClear( (PblArrayList *)list ); return; } pblLinkedListClear( (PblLinkedList *)list ); } /* * Reverses the order of the elements of the array list. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ static void pblArrayListReverse( PblArrayList * list /** The list to reverse */ ) { unsigned char ** leftPointer = list->pointerArray - 1; unsigned char ** rightPointer = list->pointerArray + list->genericList.size; unsigned char * tmp; if( list->genericList.size < 2 ) { return; } list->genericList.changeCounter++; while( ++leftPointer < --rightPointer ) { tmp = *rightPointer; *rightPointer = *leftPointer; *leftPointer = tmp; } } /* * Reverses the order of the elements of this linked list. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ static void pblLinkedListReverse( PblLinkedList * list /** The list to reverse */ ) { PblLinkedNode * leftNode = list->head; PblLinkedNode * rightNode = list->tail; void * tmp; if( list->genericList.size < 2 ) { return; } list->genericList.changeCounter++; while( leftNode != rightNode ) { tmp = rightNode->element; rightNode->element = leftNode->element; leftNode->element = tmp; if( leftNode->next == rightNode ) { break; } leftNode = leftNode->next; rightNode = rightNode->prev; } } /** * Reverses the order of the elements of this list. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ void pblListReverse( PblList * list /** The list to reverse */ ) { if( PBL_LIST_IS_ARRAY_LIST( list )) { pblArrayListReverse( (PblArrayList *)list ); return; } pblLinkedListReverse( (PblLinkedList *)list ); } /* * Free the array list's memory from heap. * * Note: The memory of the elements themselves is not freed. * * This method has a time complexity of O(1). * * @return void */ static void pblArrayListFree( PblArrayList * list /** The list to free */ ) { PBL_FREE( list->pointerArray ); PBL_FREE( list ); } /** * Free the list's memory from heap. * * Note: The memory of the elements themselves is not freed. * * For array lists this method has a time complexity of O(1). * * For linked lists this method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void */ void pblListFree( PblList * list /** The list to free */ ) { if( PBL_LIST_IS_ARRAY_LIST( list )) { pblArrayListFree( (PblArrayList *)list ); return; } pblLinkedListClear( (PblLinkedList *)list ); PBL_FREE( list ); } /* * Increases the capacity of this array list instance, if necessary. * * This method ensures that the list can hold * at least the number of elements specified by the minimum * capacity argument. * * @return int rc >= 0: OK, the list capacity is returned. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblArrayListEnsureCapacity( PblArrayList * list, /** The list to use */ int minCapacity /** The desired minimum capacity */ ) { unsigned char ** pointerArray; if( minCapacity <= list->capacity ) { /* * Nothing to do */ return list->capacity; } /* * Malloc space for minCapacity pointers */ pointerArray = (unsigned char **)pbl_malloc( "pblArrayListEnsureCapacity", sizeof(void*) * minCapacity ); if( !pointerArray ) { return -1; } if( list->capacity > 0 ) { /* * Copy the old values */ memcpy( pointerArray, list->pointerArray, sizeof(void*) * list->capacity ); } /* * Make sure all new pointers are NULL */ memset( &( pointerArray[ list->capacity ] ), 0, sizeof(void*) * ( minCapacity - list->capacity ) ); /* * Remember the new capacity */ list->capacity = minCapacity; /* * Free any old data */ if( list->pointerArray ) { PBL_FREE( list->pointerArray ); } /* * Remember the new pointer array */ list->pointerArray = pointerArray; list->genericList.changeCounter++; return list->capacity; } /** * Increases the capacity of this list instance, if necessary. * * For array lists this method ensures that the list can hold * at least the number of elements specified by the minimum * capacity argument. * * For linked lists this method does nothing, * it justs returns the value of parameter minCapacity. * * If the list is an array list and if the capacity is actually * increased, this method has a memory and time complexity of O(N), * with N being the new capacity of the list. * * In all other cases this method has a time complexity of O(1). * * @return int rc >= 0: OK, the list capacity is returned. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListEnsureCapacity( PblList * list, /** The list to use */ int minCapacity /** The desired minimum capacity */ ) { if( PBL_LIST_IS_LINKED_LIST( list )) { return minCapacity; } return pblArrayListEnsureCapacity( (PblArrayList *)list, minCapacity ); } /* * Sets the size of a linked list. * * If the size is increased, the new elements are initialized with NULL. * * This method has a time complexity of O(N), * with N being the difference between the old and new size * of the list. * * @return int rc >= 0: OK, the list size is returned. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblLinkedListSetSize( PblLinkedList * list, /** The list to use */ int size /** The desired size to set */ ) { int nAdded = 0; if( size < 0 || size == list->genericList.size ) { /* * Nothing to do */ return list->genericList.size; } while( size < list->genericList.size ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } while( size > list->genericList.size ) { if( pblLinkedListAdd( list, NULL ) < 0 ) { while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } return -1; } nAdded++; } return list->genericList.size; } /* * Sets the size of an array list. * * If the size is increased, the new elements are initialized with NULL. * * This method has a time complexity of O(N), * with N being the difference between the old and new size * of the list. * * @return int rc >= 0: OK, the list size is returned. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblArrayListSetSize( PblArrayList * list, /** The list to use */ int size /** The desired size to set */ ) { if( size < 0 || size == list->genericList.size ) { /* * Nothing to do */ return list->genericList.size; } if( size < list->genericList.size ) { /* * Make sure all unused pointers are NULL */ memset( &( list->pointerArray[ size ] ), 0, sizeof(void*) * ( list->genericList.size - size ) ); } else if( size > list->capacity ) { /* * Make some more space */ int capacity = list->capacity; if( capacity < PBLAL_INITIAL_CAPACITY ) { capacity = PBLAL_INITIAL_CAPACITY; } if( size > capacity * 2 + 1 ) { capacity = size; } else { while( size > capacity ) { capacity = capacity * 2 + 1; } } if( pblArrayListEnsureCapacity( list, capacity ) < size ) { return size; } } list->genericList.size = size; list->genericList.changeCounter++; return list->genericList.size; } /** * Sets the size of a list. * * Truncates the list if necessary. * * If the size is increased, the new elements are initialized with NULL. * * This method has a time complexity of O(N), * with N being the difference between the old and new size * of the list. * * @return int rc >= 0: OK, the list size is returned. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListSetSize( PblList * list, /** The list to use */ int size /** The desired size to set */ ) { if( size < 0 || size == list->size ) { /* * Nothing to do */ return list->size; } if( size == 0 ) { pblListClear( list ); return 0; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListSetSize( (PblLinkedList *)list, size ); } return pblArrayListSetSize( (PblArrayList *)list, size ); } /** * Returns the capacity of this list instance. * * For linked lists this call returns the list's size. * * For array lists it returns the list's capacity. * * This method has a time complexity of O(1). * * @return int rc: The capacity of this list instance. */ int pblListGetCapacity( PblList * list /** The list to use */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return list->size; } return ((PblArrayList *)list)->capacity; } /** * Returns the number of elements in this list. * * This method has a time complexity of O(1). * * @return int rc: The number of elements in this list. */ int pblListSize( PblList * list /** The list to use */ ) { return list->size; } /** * Tests if this list has no elements. * * This method has a time complexity of O(1). * * @return int rc != 0: This list has no elements. * @return int rc == 0: This list has elements. */ int pblListIsEmpty( PblList * list /** The list to test */ ) { return 0 == list->size; } /** * Tests if the object is a list. * * This method has a time complexity of O(1). * * @return int rc != 0: This object is a list. * @return int rc == 0: This object is not a list. */ int pblListIsList( void * object /** The object to test */ ) { return PBL_LIST_IS_LIST(object); } /** * Tests if the object is an array list. * * This method has a time complexity of O(1). * * @return int rc != 0: This object is an array list. * @return int rc == 0: This object is not an array list. */ int pblListIsArrayList( void * object /** The object to test */ ) { return PBL_LIST_IS_ARRAY_LIST(object); } /** * Tests if the object is a linked list. * * This method has a time complexity of O(1). * * @return int rc != 0: This object is a linked list. * @return int rc == 0: This object is not a linked list. */ int pblListIsLinkedList( void * object /** The object to test */ ) { return PBL_LIST_IS_LINKED_LIST(object); } /* * Trims the capacity of this list instance to be the list's current size. * * If the capacity is actually * decreased, this method has a time complexity of O(N), * with N being the number of elements in the list. * * In all other cases this method has a time complexity of O(1). * * @return int rc >= 0: The capacity of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblArrayListTrimToSize( PblArrayList * list /** The list to use */ ) { unsigned char ** pointerArray; int nBytes; if( list->genericList.size == list->capacity ) { return list->capacity; } if( list->genericList.size == 0 ) { PBL_FREE( list->pointerArray ); list->capacity = 0; return list->capacity; } nBytes = sizeof(void*) * list->genericList.size; /* * Malloc space for size pointers */ pointerArray = (unsigned char **)pbl_malloc( "pblListTrimToSize", nBytes ); if( !pointerArray ) { return -1; } /* * Copy the values */ memcpy( pointerArray, list->pointerArray, nBytes ); PBL_FREE( list->pointerArray ); list->pointerArray = pointerArray; list->capacity = list->genericList.size; return list->capacity; } /** * Trims the capacity of this list instance to be the list's current size. * * For linked list this call returns the list's size. * * If the list is an array list and if the capacity is actually * decreased, this method has a time complexity of O(N), * with N being the number of elements in the list. * * In all other cases this method has a time complexity of O(1). * * @return int rc >= 0: The capacity of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListTrimToSize( PblList * list /** The list to use */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return list->size; } return pblArrayListTrimToSize( (PblArrayList *)list ); } /* * Searches for the first linked node containing the given element. * * This method has a time complexity of O(N), * with N being the number of elements in the list. * * @return void * retptr != NULL: The linked node containing the element. * @return void * retptr == NULL: The specified element is not present. */ static PblLinkedNode * pblLinkedListGetNode( PblLinkedList * list, /** The list to use */ void * element /** Element to look for */ ) { PblLinkedNode * linkedNode = list->head; while( linkedNode ) { if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) ) { return linkedNode; } linkedNode = linkedNode->next; } return NULL; } /* * Returns the linked list node at the specified position in this linked list. * * This method has a time complexity of O(N), * with N being the minimum of the differences between index and * 0 or index and the size of the list. Therefore retrieving the first * or last node has a time complexity of O(1), * but retrieving a random node from the list has O(N). * * @return void * retptr != NULL: The node at the specified position in this list. * @return void * retptr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size(). */ static PblLinkedNode * pblLinkedListGetNodeAt( PblLinkedList * list, /** The list to use */ int index /** Index of the node to return */ ) { PblLinkedNode * linkedNode; if( index <= list->genericList.size / 2 ) { linkedNode = list->head; while( index-- > 0 ) { if( !linkedNode ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } linkedNode = linkedNode->next; } } else { index = list->genericList.size - ( index + 1 ); linkedNode = list->tail; while( index-- > 0 ) { if( !linkedNode ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } linkedNode = linkedNode->prev; } } return linkedNode; } /* * Inserts the specified element at the specified position in this * linked list. * * This method has a time complexity of O(N), * with N being the minimum of the differences between index and * 0 or index and the size of the list. Therefore adding the first * or last element has a time complexity of O(1), * but adding a random element to the list has O(N). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ static int pblLinkedListAddAt( PblLinkedList * list, /** The list to use */ int index, /** Index at which the element is to be inserted */ void * element /** Element to be appended to this list */ ) { PblLinkedNode * newNode; PblLinkedNode * otherNode; if( index < 0 || index > list->genericList.size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return -1; } if( index == list->genericList.size ) { return pblLinkedListAdd( list, element ); } newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAddAt", sizeof(PblLinkedNode) ); if( !newNode ) { return -1; } newNode->element = element; if( index == 0 ) { PBL_LIST_PUSH( list->head, list->tail, newNode, next, prev ); } else { otherNode = pblLinkedListGetNodeAt( list, index ); if( !otherNode ) { PBL_FREE( newNode ); return -1; } PBL_LIST_INSERT( list->head, otherNode, newNode, next, prev ); } list->genericList.size++; list->genericList.changeCounter++; return list->genericList.size; } /* * Inserts the specified element at the specified position in this list. * * Shifts the element currently at that position (if any) and any subsequent * elements to the right (adds one to their indices). * * For array lists adding to the end of the list has a time complexity * of O(1), while adding to the beginning of the list has a time * complexity of O(N) with N being the number of elements in the list. * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ static int pblArrayListAddAt( PblArrayList * list, /** The list to use */ int index, /** Index at which the element is to be inserted */ void * element /** Element to be appended to this list */ ) { if( index < 0 || index > list->genericList.size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return -1; } if( list->genericList.size == list->capacity ) { /* * Make some more space */ int capacity = list->capacity * 2 + 1; if( capacity < PBLAL_INITIAL_CAPACITY ) { capacity = PBLAL_INITIAL_CAPACITY; } if( pblArrayListEnsureCapacity( list, capacity ) < 0 ) { return -1; } } if( index < list->genericList.size ) { unsigned char * from = (unsigned char*)&( list->pointerArray[ index ] ); unsigned char * to = from + sizeof(void*); int length = sizeof(void*) * ( list->genericList.size - index ); memmove( to, from, length ); } list->pointerArray[ index ] = (unsigned char *)element; list->genericList.size++; list->genericList.changeCounter++; return list->genericList.size; } /** * Inserts the specified element at the specified position in this list. * * Shifts the element currently at that position (if any) and any subsequent * elements to the right (adds one to their indices). * * For array lists adding to the end of the list has a time complexity * of O(1), while adding to the beginning of the list has a time * complexity of O(N) with N being the number of elements in the list. * * For linked lists adding to beginning or the end of the list has a time complexity * of O(1), while adding to a random position in the middle of the list has a time * complexity of O(N) with N being the number of elements in the list. * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ int pblListAddAt( PblList * list, /** The list to use */ int index, /** Index at which the element is to be inserted */ void * element /** Element to be appended to this list */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListAddAt( (PblLinkedList *)list, index, element ); } return pblArrayListAddAt( (PblArrayList *)list, index, element ); } /* * Appends the specified element to the end of this list. * * This method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblLinkedListAdd( PblLinkedList * list, /** The list to append to */ void * element /** Element to be appended to this list */ ) { PblLinkedNode * newNode; newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAdd", sizeof(PblLinkedNode) ); if( !newNode ) { return -1; } newNode->element = element; PBL_LIST_APPEND( list->head, list->tail, newNode, next, prev ); list->genericList.size++; list->genericList.changeCounter++; return list->genericList.size; } /** * Appends the specified element to the end of this list. * * This method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListAdd( PblList * list, /** The list to append to */ void * element /** Element to be appended to this list */ ) { if( PBL_LIST_IS_ARRAY_LIST(list) ) { return pblArrayListAddAt( (PblArrayList *)list, list->size, element ); } return pblLinkedListAdd( (PblLinkedList *)list, element ); } /** * Pushes the specified element to the end (last element) of this list. * * This method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListPush( PblList * list, /** The list to append to */ void * element /** Element to be appended to this list */ ) { return pblListAdd( list, element ); } /** * Inserts the given element at the beginning of this list. * * For array lists this method has a time complexity of O(N), * with N being the size of the list. * * For linked lists this method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListAddFirst( PblList * list, /** The list to add to */ void * element /** Element to be added to the list */ ) { return pblListAddAt( list, 0, element ); } /** * Appends the given element to the end of this list. * * (Identical in function to the add method; included only for consistency.) * * This method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListAddLast( PblList * list, /** The list to add to */ void * element /** Element to be added to the list */ ) { return pblListAdd( list, element ); } /** * Adds the specified element as the tail (last element) of this list. * * This method has a time complexity of O(1). * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListOffer( PblList * list, /** The list to add to */ void * element /** Element to be added to the list */ ) { return pblListAdd( list, element ); } /* * Inserts all of the elements in the specified collection * into this linked list at the specified position. * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range, (index < 0 || index >= size()). *
PBL_ERROR_CONCURRENT_MODIFICATION - The list underlying the iterator was modified concurrently. */ static int pblLinkedListAddAllAt( PblLinkedList * list, /** The list to use */ int index, /** Index at which the elements are to be inserted */ PblIterator * iterator /** The iterator whose elements are to be added to this list. */ ) { int nAdded = 0; PblLinkedNode * otherNode; int hasNext; if( index == list->genericList.size ) { // Add at the end of the list // while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { void * element = pblIteratorNext( iterator ); if( element == (void*)-1 || pblLinkedListAdd( list, element ) < 0 ) { // An error, remove the elements added so far // while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } return -1; } nAdded++; } if( hasNext < 0 ) { // Concurrent modification error on the source list, // remove the elements added so far // while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } return -1; } return list->genericList.size; } otherNode = pblLinkedListGetNodeAt( list, index ); if( !otherNode ) { return -1; } while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { PblLinkedNode * newNode; newNode = (PblLinkedNode *)pbl_malloc( "pblLinkedListAddAllAt", sizeof(PblLinkedNode) ); if( !newNode ) { // Out of memory, // remove the elements added so far // while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, index ); } return -1; } newNode->element = pblIteratorNext( iterator ); if( newNode->element == (void*)-1 ) { // Concurrent modification error on the source list, // remove the elements added so far // while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } PBL_FREE( newNode ); return -1; } PBL_LIST_INSERT( list->head, otherNode, newNode, next, prev ); list->genericList.size++; list->genericList.changeCounter++; nAdded++; } if( hasNext < 0 ) { // Concurrent modification error on the source list, // remove the elements added so far // while( nAdded-- > 0 ) { pblLinkedListRemoveAt( list, list->genericList.size - 1 ); } return -1; } return list->genericList.size; } /** * Inserts all of the elements in the specified collection * into this list at the specified position. * * Shifts the element currently at that position (if any) and any * subsequent elements to the right (increases their indices). * The new elements will appear in this list in the order that * they are returned by the specified collection's iterator. * * The behavior of this operation is unspecified if the specified * collection is modified while the operation is in progress. * (Note that this will occur if the specified collection * is this list, and it's nonempty.) * * For array lists adding to the end of the list has a time complexity * of O(M), while adding to the beginning of the list has a time * complexity of O(N + M) with N being the number of elements in the list * and M being the size of the collection whose elements are added. * * For linked lists adding to beginning or the end of the list has a time complexity * of O(M), while adding to a random position in the middle of the list has a time * complexity of O(N + M) with N being the number of elements in the list * and M being the size of the collection whose elements are added. * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range, (index < 0 || index >= size()). *
PBL_ERROR_PARAM_LIST - Collection cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - Collection was modified concurrently. */ int pblListAddAllAt( PblList * list, /** The list to use */ int index, /** Index at which the element are to be inserted */ void * collection /** The collection whose elements are to be added to this list. */ ) { PblArrayList * pblList; PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; int iteratorSize; int hasNext; if( index < 0 || index > list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return -1; } if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 ) { return -1; } iteratorSize = pblIteratorSize( iterator ); if( iteratorSize < 1 ) { return list->size; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { int rc = pblLinkedListAddAllAt( (PblLinkedList *)list, index, iterator ); return rc; } pblList = (PblArrayList *)list; if( pblList->genericList.size + iteratorSize >= pblList->capacity ) { /* * Make some more space */ int capacity = pblList->capacity * 2 + 1; if( capacity < pblList->genericList.size + iteratorSize ) { capacity = pblList->genericList.size + iteratorSize; } if( capacity < PBLAL_INITIAL_CAPACITY ) { capacity = PBLAL_INITIAL_CAPACITY; } if( pblArrayListEnsureCapacity( pblList, capacity ) < 0 ) { return -1; } } if( index < pblList->genericList.size ) { unsigned char * from = (unsigned char*)&( pblList->pointerArray[ index ] ); unsigned char * to = from + iteratorSize * sizeof(void*); int length = sizeof(void*) * ( pblList->genericList.size - index ); memmove( to, from, length ); } // If the source is an array list, we use memcpy directly // if( PBL_LIST_IS_ARRAY_LIST(collection) ) { PblArrayList * source = (PblArrayList *)collection; unsigned char * from = (unsigned char*)&( source->pointerArray[ 0 ] ); unsigned char * to = (unsigned char*)&( pblList->pointerArray[ index ] ); int length = sizeof(void*) * source->genericList.size; memcpy( to, from, length ); } else { while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { void * next = pblIteratorNext( iterator ); if( next == (void*)-1 ) { // Concurrent modification on the source collection // return -1; } pblList->pointerArray[ index++ ] = (unsigned char *)next; } if( hasNext < 0 ) { // Concurrent modification on the source collection // return -1; } } pblList->genericList.size += iteratorSize; pblList->genericList.changeCounter++; return pblList->genericList.size; } /** * Appends all of the elements in the specified Collection to the end of this list, * in the order that they are returned by the specified Collection's Iterator. * * This method has a time complexity of O(M), * with M being the size of the collection whose elements are added. * * @return int rc >= 0: The size of this list instance. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_PARAM_LIST - Collection cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - Collection was modified concurrently. */ int pblListAddAll( PblList * list, /** The list to use */ void * collection /** The collection whose elements are to be added to this list. */ ) { return pblListAddAllAt( list, list->size, collection ); } /** * Retrieves and removes the head (first element) of this list. * * @return void * retptr != (void*)-1: The head of this list, can be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - This list is empty. */ void * pblListRemove( PblList * list /** The list to use */ ) { return pblListRemoveAt( list, 0 ); } /* * Removes the element at the specified position in this linked list. * * Shifts any subsequent elements to the left (subtracts one from their indices). * * @return void * retptr != (void*)-1: The element that was removed, can be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ static void * pblLinkedListRemoveAt( PblLinkedList * list, /** The list to use */ int index /** Index at which the element is to be removed */ ) { PblLinkedNode * nodeToFree; unsigned char * result; nodeToFree = pblLinkedListGetNodeAt( list, index ); if( !nodeToFree ) { return (void*)-1; } result = nodeToFree->element; PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev ); list->genericList.size--; list->genericList.changeCounter++; PBL_FREE( nodeToFree ); return result; } /* * Removes the element at the specified position in this array list. * * Shifts any subsequent elements to the left (subtracts one from their indices). * * @return void * retptr != (void*)-1: The element that was removed, can be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ void * pblArrayListRemoveAt( PblArrayList * list, /** The list to use */ int index /** Index at which the element is to be removed */ ) { unsigned char * result; if( index < 0 || index >= list->genericList.size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return (void*)-1; } result = list->pointerArray[ index ]; if( index < list->genericList.size - 1 ) { unsigned char * to = (unsigned char*)&( list->pointerArray[ index ] ); unsigned char * from = to + sizeof(void*); int length = sizeof(void*) * ( ( list->genericList.size - 1 ) - index ); memmove( to, from, length ); } list->pointerArray[ list->genericList.size - 1 ] = NULL; list->genericList.size--; list->genericList.changeCounter++; return result; } /** * Removes the element at the specified position in this list. * * Shifts any subsequent elements to the left (subtracts one from their indices). * * For array lists removing from the end of the list has a time complexity * of O(1), while removing from the beginning of the list has a time * complexity of O(N) with N being the number of elements in the list. * * For linked lists removing from the beginning or the end of the list has a time complexity * of O(1), while removing from a random position in the middle of the list has a time * complexity of O(N) with N being the number of elements in the list. * * @return void * retptr != (void*)-1: The element that was removed, can be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ void * pblListRemoveAt( PblList * list, /** The list to use */ int index /** The index at which the element is to be removed */ ) { if( index < 0 || index >= list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return (void*)-1; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListRemoveAt( (PblLinkedList *)list, index ); } return pblArrayListRemoveAt( (PblArrayList *)list, index ); } /* * Removes from this list all of the elements whose index is between * fromIndex, inclusive and toIndex, exclusive. * * For linked lists removing from the beginning or the end of the list has a time complexity * of O(M), while removing from a random position in the middle of the list has a time * complexity of O(N + M) with N being the number of elements in the list * and M being the number of elements removed. * * @return int rc >= 0: The size of the list. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - fromIndex is out of range (fromIndex < 0 || fromIndex >= size()) * or toIndex is out of range ( toIndex < 0 || toIndex > size()) */ static int pblLinkedListRemoveRange( PblLinkedList * list, /** The list to use */ int fromIndex, /** The index of first element to be removed. */ int toIndex /** The index after last element to be removed. */ ) { int elementsToRemove = toIndex - fromIndex; int distanceToEnd = list->genericList.size - toIndex; PblLinkedNode * linkedNode; if( fromIndex <= distanceToEnd ) { // Find the first node to remove from the beginning of the list // and remove forward // linkedNode = pblLinkedListGetNodeAt( list, fromIndex ); if( !linkedNode ) { return -1; } list->genericList.size -= elementsToRemove; while( elementsToRemove-- > 0 ) { PblLinkedNode * nodeToFree = linkedNode; linkedNode = linkedNode->next; PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev ); PBL_FREE( nodeToFree ); } } else { // Find the last node to remove from the end of the list // and remove backward // linkedNode = pblLinkedListGetNodeAt( list, toIndex - 1 ); if( !linkedNode ) { return -1; } list->genericList.size -= elementsToRemove; while( elementsToRemove-- > 0 ) { PblLinkedNode * nodeToFree = linkedNode; linkedNode = linkedNode->prev; PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev ); PBL_FREE( nodeToFree ); } } list->genericList.changeCounter++; return list->genericList.size; } /** * Removes from this list all of the elements whose index is between * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding * elements to the left (reduces their index). * This call shortens the list by (toIndex - fromIndex) elements. * (If toIndex==fromIndex, this operation has no effect.) * * Note: No memory of the elements themselves is freed. * * For array lists removing from the end of the list has a time complexity * of O(M), while removing from the beginning of the list has a time * complexity of O(N + M) with N being the number of elements in the list * and M being the number of elements removed. * * For linked lists removing from the beginning or the end of the list has a time complexity * of O(M), while removing from a random position in the middle of the list has a time * complexity of O(N + M) with N being the number of elements in the list * and M being the number of elements removed. * * @return int rc >= 0: The size of the list. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - fromIndex is out of range (fromIndex < 0 || fromIndex >= size()) * or toIndex is out of range ( toIndex < 0 || toIndex > size()) */ int pblListRemoveRange( PblList * list, /** The list to use */ int fromIndex, /** The index of first element to be removed. */ int toIndex /** The index after last element to be removed. */ ) { PblArrayList * pblList; int elementsToRemove; if( fromIndex < 0 || fromIndex >= list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return -1; } if( toIndex < 0 || toIndex > list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return -1; } elementsToRemove = toIndex - fromIndex; if( elementsToRemove < 1 ) { return list->size; } if( elementsToRemove == list->size ) { pblListClear( list ); return 0; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListRemoveRange( (PblLinkedList *)list, fromIndex, toIndex ); } pblList = (PblArrayList *)list; if( toIndex < pblList->genericList.size ) { unsigned char * to = (unsigned char*)&( pblList->pointerArray[ fromIndex ] ); unsigned char * from = to + elementsToRemove * sizeof(void*); int length = sizeof(void*) * ( pblList->genericList.size - toIndex ); memmove( to, from, length ); } if( elementsToRemove > 0 ) { unsigned char * to = (unsigned char*)&( pblList->pointerArray[ pblList->genericList.size - elementsToRemove ] ); int length = sizeof(void*) * elementsToRemove; memset( to, 0, length ); pblList->genericList.size -= elementsToRemove; } pblList->genericList.changeCounter++; return pblList->genericList.size; } /** * Removes and returns the last element in this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListRemoveLast( PblList * list /** The list to use */ ) { return pblListRemoveAt( list, list->size - 1 ); } /** * Removes and returns the first element in this list. * * For array lists this method has a time complexity of O(N), * with N being the size of the list. * * For linked lists this method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListRemoveFirst( PblList * list /** The list to use */ ) { return pblListRemoveAt( list, 0 ); } /** * Returns the last element in this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListGetLast( PblList * list /** The list to use */ ) { return pblListGet( list, list->size - 1 ); } /** * Retrieves, but does not remove, the tail (last element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListTail( PblList * list /** The list to use */ ) { return pblListGet( list, list->size - 1 ); } /** * Returns the first element in this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListGetFirst( PblList * list /** The list to use */ ) { return pblListGet( list, 0 ); } /** * Returns the element at the specified position in this list. * * For array lists this method has a time complexity of O(1). * * For linked lists this method has a time complexity of O(N), * with N being the minimum of the differences between index and * 0 or index and the size of the list. Therefore retrieving the first * or last element has a time complexity of O(1), * but retrieving a random element from the list has O(N). * * @return void * retptr != (void*)-1: The element at the specified position in this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ void * pblListGet( PblList * list, /** The list to use */ int index /** Index of the element to return */ ) { /* * Check the parameter */ if( index < 0 || index >= list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return (void*)-1; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { PblLinkedNode * linkedNode = pblLinkedListGetNodeAt( (PblLinkedList *)list, index ); if( !linkedNode ) { return (void*)-1; } return linkedNode->element; } else { PblArrayList * pblList = (PblArrayList *)list; return pblList->pointerArray[ index ]; } } /** * Retrieves, but does not remove, the head (first element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListPeek( PblList * list /** The list to use */ ) { return pblListGet( list, 0 ); } /** * Retrieves, but does not remove, the tail (last element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListTop( PblList * list /** The list to use */ ) { return pblListGet( list, list->size - 1 ); } /** * Retrieves and removes the tail (last element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListPop( PblList * list /** The list to use */ ) { return pblListRemoveAt( list, list->size - 1 ); } /** * Retrieves and removes the head (first element) of this list. * * For array lists this method has a time complexity of O(N), * with N being the size of the list. * * For linked lists this method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The head of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListPoll( PblList * list /** The list to use */ ) { return pblListRemoveAt( list, 0 ); } /** * Retrieves, but does not remove, the head (first element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListElement( PblList * list /** The list to use */ ) { return pblListGet( list, 0 ); } /** * Retrieves, but does not remove, the head (first element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element of this list, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListHead( PblList * list /** The list to use */ ) { return pblListGet( list, 0 ); } /** * Replaces the head (first element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The first element of this list before this call, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListSetFirst( PblList * list, /** The list to use */ void * element /** Element to be stored at the first position */ ) { return pblListSet( list, 0, element ); } /** * Replaces the tail (last element) of this list. * * This method has a time complexity of O(1). * * @return void * retptr != (void*)-1: The last element of this list before this call, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - this list is empty. */ void * pblListSetLast( PblList * list, /** The list to use */ void * element /** Element to be stored at the last position */ ) { return pblListSet( list, list->size - 1, element ); } /** * Replaces the element at the specified position in this list with the specified element. * * For array lists this method has a time complexity of O(1). * * For linked lists this method has a time complexity of O(N), * with N being the minimum of the differences between index and * 0 or index and the size of the list. Therefore changing the first * or last element has a time complexity of O(1), * but changing a random element from the list has O(N). * * @return void * retptr != (void*)-1: The element previously at the specified position, may be NULL. * @return void * retptr == (void*)-1: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_BOUNDS - Index is out of range (index < 0 || index >= size()). */ void * pblListSet( PblList * list, /** The list to use */ int index, /** Index of element to replace */ void * element /** Element to be stored at the specified position */ ) { unsigned char * result; if( index < 0 || index >= list->size ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return (void*)-1; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { PblLinkedNode * linkedNode = pblLinkedListGetNodeAt( (PblLinkedList *)list, index ); if( !linkedNode ) { return (void*)-1; } result = (unsigned char *)linkedNode->element; linkedNode->element = element; return result; } else { PblArrayList * pblList = (PblArrayList *)list; result = pblList->pointerArray[ index ]; pblList->pointerArray[ index ] = (unsigned char *)element; return result; } } /** * Sets an application specific compare function for the elements * of the list. * * An application specific compare function can be set to the list. * If no specific compare function is specified by the user, * the default compare function is used. * The default compare function compares the two pointers directly, * i.e. it tests for object identity. * * The compare function specified should behave like the one that * can be specified for the C-library function 'qsort'. * * The arguments actually passed to the compare function when it is called * are addresses of the element pointers added to the list. * E.g.: If you add char * pointers to the list, the compare function * will be called with char ** pointers as arguments. See the documentation * for the C-library function 'qsort' for further information. * * This method has a time complexity of O(1). * * @return * retptr: The compare function used before, may be NULL. */ void * pblListSetCompareFunction( PblList * list, /** The list to set compare function for */ int ( *compare ) /** The compare function to set */ ( const void* prev, /** The "left" element for compare */ const void* next /** The "right" element for compare */ ) ) { void * retptr = list->compare; list->compare = compare; return retptr; } /** * Gets the application specific compare function for the elements * of the list. * * This method has a time complexity of O(1). * * @return void * retptr: The compare function used, may be NULL. */ void * pblListGetCompareFunction( PblList * list /** The list to get the compare function for */ ) { return list->compare; } /* * Sorts the elements of the array list. * * This method uses the C library function 'qsort', * therefore it normally has a time complexity of O( N * Log(N) ), * with N being he size of the list to sort. * * @return int rc == 0: Ok. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblArrayListSort( PblArrayList * list, /** The list to sort */ int ( *compare ) /** Specific compare function to use */ ( const void* prev, /** "left" element for compare */ const void* next /** "right" element for compare */ ) ) { if( list->genericList.size < 2 ) { return 0; } qsort( list->pointerArray, (size_t)list->genericList.size, (size_t)sizeof(void*), ( compare ? compare : list->genericList.compare ? list->genericList.compare : pblCollectionDefaultCompare ) ); list->genericList.changeCounter++; return 0; } /* * Sorts the elements of the linked list. * * This method uses the C library function 'qsort', * therefore it normally has a time complexity of O( N * Log(N) ), * with N being he size of the list to sort. * * This method has a memory complexity of O(N). * * @return int rc == 0: Ok. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ static int pblLinkedListSort( PblLinkedList * list, /** The list to sort */ int ( *compare ) /** Specific compare function to use */ ( const void* prev, /** "left" element for compare */ const void* next /** "right" element for compare */ ) ) { PblLinkedNode * node = list->head; void ** array; void ** arrayPointer; if( list->genericList.size < 2 ) { return 0; } array = pblLinkedListToArray( list ); if( !array ) { // Out of memory. // return -1; } arrayPointer = array; qsort( array, (size_t)list->genericList.size, (size_t)sizeof(void*), ( compare ? compare : list->genericList.compare ? list->genericList.compare : pblCollectionDefaultCompare ) ); while( node ) { node->element = *arrayPointer++; node = node->next; } PBL_FREE(array); list->genericList.changeCounter++; return 0; } /** * Sorts the elements of the list. * * A specific compare function can be used for the sort. * * If NULL is specific as specific compare function, the compare * function set for the list will be used if any, otherwise the * default compare function is used. * * The default compare function compares the two pointers directly. * * The compare function specified should behave like the one that * can be specified for the C-library function 'qsort'. * * This method uses the C library function 'qsort', * therefore it normally has a time complexity of O( N * Log(N) ), * with N being he size of the list to sort. * * For linked lists this method has a memory complexity of O(N). * For array lists this method does not need memory. * * @return int rc == 0: Ok. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ int pblListSort( PblList * list, /** The list to sort */ int ( *compare ) /** Specific compare function to use */ ( const void* prev, /** "left" element for compare */ const void* next /** "right" element for compare */ ) ) { if( PBL_LIST_IS_ARRAY_LIST( list ) ) { return pblArrayListSort( (PblArrayList*)list, compare ); } return pblLinkedListSort( (PblLinkedList*)list, compare ); } /* * Searches for the first occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The index of the specified element. * @return int rc < 0: The specified element is not present. */ static int pblLinkedListIndexOf( PblLinkedList * list, /** The list to use */ void * element /** Element to look for */ ) { int index = 0; PblLinkedNode * linkedNode = list->head; while( linkedNode ) { if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) ) { return index; } linkedNode = linkedNode->next; index++; } return -1; } /* * Searches for the first occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The index of the specified element. * @return int rc < 0: The specified element is not present. */ static int pblArrayListIndexOf( PblArrayList * list, /** The list to use */ void * element /** Element to look for */ ) { int index; for( index = 0; index < list->genericList.size; index++ ) { if( !pblCollectionElementCompare( (PblCollection*)list, element, list->pointerArray[ index ] ) ) { return index; } } return -1; } /** * Searches for the first occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The index of the specified element. * @return int rc < 0: The specified element is not present. */ int pblListIndexOf( PblList * list, /** The list to use */ void * element /** Element to look for */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListIndexOf( (PblLinkedList*)list, element ); } return pblArrayListIndexOf( (PblArrayList*)list, element ); } /* * Searches for the last occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The last index of the specified element. * @return int rc < 0: The specified element is not present. */ static int pblLinkedListLastIndexOf( PblLinkedList * list, /** The list to use */ void * element /** Element to look for */ ) { int index = list->genericList.size - 1; PblLinkedNode * linkedNode = list->tail; while( linkedNode ) { if( !pblCollectionElementCompare( (PblCollection*)list, element, linkedNode->element ) ) { return index; } linkedNode = linkedNode->prev; index--; } return -1; } /* * Searches for the last occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The last index of the specified element. * @return int rc < 0: The specified element is not present. */ static int pblArrayListLastIndexOf( PblArrayList * list, /** The list to use */ void * element /** Element to look for */ ) { int index; for( index = list->genericList.size - 1; index >= 0; index-- ) { if( !pblCollectionElementCompare( (PblCollection*)list, element, list->pointerArray[ index ] ) ) { return index; } } return -1; } /** * Searches for the last occurence of the given argument. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc >= 0: The last index of the specified element. * @return int rc < 0: The specified element is not present. */ int pblListLastIndexOf( PblList * list, /** The list to use */ void * element /** Element to look for */ ) { if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListLastIndexOf( (PblLinkedList*)list, element ); } return pblArrayListLastIndexOf( (PblArrayList*)list, element ); } /** * Returns true if this list contains the specified element. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc != 0: The specified element is present. * @return int rc == 0: The specified element is not present. */ int pblListContains( PblList * list, /** The list to use */ void * element /** Element to look for */ ) { return ( pblListIndexOf( list, element ) >= 0 ); } /** * Returns a value > 0 if this list contains all of the elements * in the specified collection. * * This implementation iterates over the specified collection, * checking each element returned by the iterator in turn to see if it's contained in this list. * If all elements are so contained a value > 0 is returned, otherwise 0. * * This method has a time complexity of O(N * M), * with N being the size of the list and M being the size of the * collection. * * @return int rc > 0: The list contains all of the elements in the specified collection. * @return int rc == 0: The list does not contain all of the elements. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_COLLECTION - The collection cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - The collection was modified concurrently. */ int pblListContainsAll( PblList * list, /** The list to use */ void * collection /** The collection to be checked for containment in this list. */ ) { PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; int iteratorSize; int hasNext; if( pblIteratorInit( collection, iterator ) < 0 ) { return -1; } iteratorSize = pblIteratorSize( iterator ); if( iteratorSize < 1 ) { return 1; } while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { void * element = pblIteratorNext( iterator ); if( element == (void*)-1 ) { // concurrent modification on the collection // return -1; } if( !pblListContains( list, element ) ) { return 0; } } if( hasNext < 0 ) { // concurrent modification on the collection // return -1; } return 1; } /* * Removes or retains from this array list all of its elements * that are contained in the specified collection. * * @return int rc > 0: If this list changed as a result of the call. * @return int rc == 0: This list did not change. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_LIST - The list cannot be iterated. */ static int pblArrayListRemoveRetainAll( PblArrayList * list, /** The list to use */ PblCollection * collection, /** The collection to use */ int doRemove /** Flag: do a remove or a retain */ ) { int index = 0; int newIndex = 0; void * element; int isContained; for( index = 0; index < list->genericList.size; index++ ) { element = list->pointerArray[ index ]; isContained = pblCollectionContains( collection, element ); if( ( doRemove && !isContained ) || ( !doRemove && isContained ) ) { if( newIndex != index ) { list->pointerArray[ newIndex++ ] = element; } else { newIndex++; } } } if( newIndex != index ) { if( pblArrayListSetSize( list, newIndex ) != newIndex ) { return -1; } return 1; } return 0; } /* * Removes or retains from this linked list all of its elements * that are contained in the specified collection. * * @return int rc > 0: If this list changed as a result of the call. * @return int rc == 0: This list did not change. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_LIST - The list cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently. */ static int pblLinkedListRemoveRetainAll( PblLinkedList * list, /** The list to use */ PblCollection * collection, /** The collection to use */ int doRemove /** Flag: do a remove or a retain */ ) { PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; int rc = 0; int hasNext; void * element; int isContained; /* * Get the iterator for this list */ if( pblIteratorInit( (PblCollection *)list, iterator ) < 0 ) { pbl_errno = PBL_ERROR_PARAM_LIST; return -1; } while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { element = pblIteratorNext( iterator ); if( element == (void*)-1 ) { // Concurrent modification // return -1; } isContained = pblCollectionContains( collection, element ); if( ( doRemove && isContained ) || ( !doRemove && !isContained ) ) { if( pblIteratorRemove( iterator ) < 0 ) { return -1; } /* * The list changed */ rc = 1; } } if( hasNext < 0 ) { // Concurrent modification // return -1; } return rc; } /** * Removes from this list all of its elements * that are contained in the specified collection. * * This implementation iterates over this list, * checking each element returned by the iterator in turn * to see if it's contained in the specified collection. * * If it's so contained, it's removed from this list * with the iterator's remove method in case of a linked list * and with an optimized direct removal method in case of * an array list. * * This method has a time complexity of O(N * M), * with N being the size of the list and M being the size of the * collection. * * @return int rc > 0: If this list changed as a result of the call. * @return int rc == 0: This list did not change. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_LIST - The list be iterated. *
PBL_ERROR_PARAM_COLLECTION - The collection cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently. */ int pblListRemoveAll( PblList * list, /** The list to use */ void * collection /** The collection whose elements are to be removed from this list. */ ) { PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; int iteratorSize; if( list->size < 1 ) { return 0; } /* * Get the iterator for the collection */ if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 ) { return -1; } iteratorSize = pblIteratorSize( iterator ); if( iteratorSize < 1 ) { return 0; } if( PBL_LIST_IS_ARRAY_LIST( list ) ) { return pblArrayListRemoveRetainAll( (PblArrayList*)list, (PblCollection *)collection, 1 ); } return pblLinkedListRemoveRetainAll( (PblLinkedList*)list, (PblCollection *)collection, 1 ); } /** * Retains only the elements in this list * that are contained in the specified collection. * * In other words, removes from this list all * of its elements that are not contained in the specified collection. * * This implementation iterates over this list, * checking each element returned by the iterator in turn * to see if it's contained in the specified collection. * * If it's not so contained, it's removed from this list * with the iterator's remove method in case of a linked list * and with an optimized direct removal method in case of * an array list. * * This method has a time complexity of O(N * M), * with N being the size of the list and M being the size of the * collection. * * @return int rc > 0: If this list changed as a result of the call. * @return int rc == 0: This list did not change. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_LIST - The list cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - The list was modified concurrently. *
PBL_ERROR_PARAM_COLLECTION - The collection cannot be iterated. */ int pblListRetainAll( PblList * list, /** The list to use */ void * collection /** The elements to be retained in this list. */ ) { PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; int iteratorSize; if( list->size < 1 ) { return 0; } /* * Get the iterator for the collection */ if( pblIteratorInit( (PblCollection *)collection, iterator ) < 0 ) { return -1; } iteratorSize = pblIteratorSize( iterator ); if( iteratorSize < 0 ) { return -1; } /* * Get the iterator for this list */ if( pblIteratorInit( list, iterator ) < 0 ) { return -1; } if( iteratorSize == 0 ) { if( pblIteratorSize( iterator ) == 0 ) { return 0; } /* * Clear the entire list */ pblListClear( list ); return 1; } if( PBL_LIST_IS_ARRAY_LIST( list ) ) { return pblArrayListRemoveRetainAll( (PblArrayList*)list, (PblCollection *)collection, 0 ); } return pblLinkedListRemoveRetainAll( (PblLinkedList*)list, (PblCollection *)collection, 0 ); } /* * Removes a single instance of the specified element from this * linked list, if it is present. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc != 0: The list contained the specified element. * @return int rc == 0: The specified element is not present. */ static int pblLinkedListRemoveElement( PblLinkedList * list, /** The list to use */ void * element /** Element to remove */ ) { PblLinkedNode * nodeToFree = pblLinkedListGetNode( list, element ); if( !nodeToFree ) { return 0; } PBL_LIST_UNLINK( list->head, list->tail, nodeToFree, next, prev ); list->genericList.size--; list->genericList.changeCounter++; PBL_FREE( nodeToFree ); return 1; } /** * Removes a single instance of the specified element from this list, * if it is present. * * More formally, removes an element e such that * (o==null ? e==null : o.equals(e)), * if the list contains one or more such elements. * Returns true if the list contained the specified * element (or equivalently, if the list changed as * a result of the call). * * This method has a time complexity of O(N), * with N being the size of the list. * * @return int rc != 0: The list contained the specified element. * @return int rc == 0: The specified element is not present. */ int pblListRemoveElement( PblList * list, /** The list to use */ void * element /** The element to remove */ ) { int index; if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListRemoveElement( (PblLinkedList*)list, element ); } index = pblListIndexOf( list, element ); if( index >= 0 ) { pblArrayListRemoveAt( (PblArrayList*)list, index ); return 1; } return 0; } /* * Returns an array containing all of the elements in this linked list in the correct order. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return void * retptr != NULL: The array containing the elements of the list. * @return void * retptr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - The list is empty. */ static void ** pblLinkedListToArray( PblLinkedList * list /** The list to use */ ) { PblLinkedNode * linkedNode = list->head; void ** arrayPointer; void ** resultArray; resultArray = (void **)pbl_malloc( "pblLinkedListToArray", sizeof(void*) * list->genericList.size ); if( !resultArray ) { return NULL; } arrayPointer = resultArray; while( linkedNode ) { *arrayPointer++ = linkedNode->element; linkedNode = linkedNode->next; } return resultArray; } /** * Returns an array containing all of the elements in this list in the correct order. * * Note: The pointer array returned is malloced from heap, the caller has to free it * after it is no longer needed! * * The size of the pointer array malloced and returned is defined by the pblListSize() * of the list. * * This method has a time complexity of O(N), * with N being the size of the list. * * @return void * retptr != NULL: The array containing the elements of the list. * @return void * retptr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_OUT_OF_BOUNDS - The list is empty. */ void ** pblListToArray( PblList * list /** The list to use */ ) { if( list->size == 0 ) { pbl_errno = PBL_ERROR_OUT_OF_BOUNDS; return NULL; } if( PBL_LIST_IS_LINKED_LIST( list ) ) { return pblLinkedListToArray( (PblLinkedList*)list ); } else { PblArrayList * pblList = (PblArrayList *)list; return (void **)pbl_memdup( "pblListToArray", pblList->pointerArray, sizeof(void*) * pblList->genericList.size ); } } /** * Compares the specified collection with this list for equality. * * Returns true if and only if the specified collection is a collection, * both collections have the same size, and all corresponding pairs of * elements in the two collections are equal. (Two elements e1 and e2 * are equal if (e1==null ? e2==null : compare( e1, e2 )==0.) * * In other words, two collections are defined to be equal as lists * if they contain the same elements in the same order. * * This implementation first checks if the specified collection is this list. * If so, it returns true; if not, it checks if the specified collection is a list or a tree set. * If not, it returns false; if so, it iterates over both collections, * comparing corresponding pairs of elements by using the compare function of this list. * If any comparison returns false, this method returns false. * If either iterator runs out of elements before the other it returns false (as the lists are of unequal length); * otherwise it returns true when the iterations complete. * * This method has a time complexity of O(Min(N,M)), * with N being the size of the list and M being the * number of elements in the object compared. * * @return int rc > 0: The specified collection is equal to this list. * @return int rc == 0: The specified collection is not equal to this list. * @return int rc < 0: An error, see pbl_errno: * *
PBL_ERROR_PARAM_LIST - The list or collection cannot be iterated. *
PBL_ERROR_CONCURRENT_MODIFICATION - The list or collection was modified concurrently. */ int pblListEquals( PblList * list, /** The list to compare with. */ void * collection /** The collection to be compared for equality with this list. */ ) { PblIterator iteratorBuffer; PblIterator * iterator = &iteratorBuffer; PblIterator thisIteratorBuffer; PblIterator * thisIterator = &thisIteratorBuffer; int hasNext; int thisHasNext = 0; void * next; void * thisNext; if( list == collection ) { return 1; } if( !PBL_COLLECTION_IS_COLLECTION( collection ) ) { return 0; } if( pblIteratorInit( list, thisIterator ) < 0 ) { return -1; } if( pblIteratorInit( collection, iterator ) < 0 ) { return -1; } if( pblIteratorSize( iterator ) != pblIteratorSize( thisIterator ) ) { return 0; } while( ( hasNext = pblIteratorHasNext( iterator ) ) > 0 ) { if( ( thisHasNext = pblIteratorHasNext( thisIterator ) ) < 0 ) { return -1; } if( thisHasNext == 0 ) { return 0; } next = pblIteratorNext( iterator ); if( next == (void*)-1 ) { return -1; } thisNext = pblIteratorNext( thisIterator ); if( thisNext == (void*)-1 ) { return -1; } if( pblCollectionElementCompare( (PblCollection*)list, thisNext, next ) ) { return 0; } } if( hasNext < 0 ) { return -1; } if( ( thisHasNext = pblIteratorHasNext( thisIterator ) ) > 0 ) { return 0; } if( thisHasNext < 0 ) { return -1; } return 1; } /** * Returns an iterator over the elements in this list in proper sequence. * * The iterator starts the iteration at the beginning of the list. * * Note: The memory allocated by this method for the iterator returned needs to be released * by calling pblIteratorFree() once the iterator is no longer needed. * * The iterators returned by the this method are fail-fast: * if the list is structurally modified at any time after the iterator is created, * in any way except through the Iterator's own remove or add methods, * the iterator will return a PBL_ERROR_CONCURRENT_MODIFICATION error. * * Thus, in the face of concurrent modification, * the iterator fails quickly and cleanly, * rather than risking arbitrary, non-deterministic * behavior at an undetermined time in the future. * * This method has a time complexity of O(1). * * @return void * retptr != NULL: The iterator. * @return void * retptr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_PARAM_LIST - list cannot be iterated. */ PblIterator * pblListIterator( PblList * list /** The list to create the iterator for */ ) { if( !PBL_LIST_IS_LIST( list ) ) { pbl_errno = PBL_ERROR_PARAM_LIST; return NULL; } return pblIteratorNew( list ); } /** * Returns a reverse iterator over the elements in this list in proper sequence. * * The reverse iterator starts the iteration at the end of the list. * * Note: The memory allocated by this method for the iterator returned needs to be released * by calling pblIteratorFree() once the iterator is no longer needed. * * The iterators returned by the this method are fail-fast: * if the list is structurally modified at any time after the iterator is created, * in any way except through the Iterator's own remove or add methods, * the iterator will return a PBL_ERROR_CONCURRENT_MODIFICATION error. * * Thus, in the face of concurrent modification, * the iterator fails quickly and cleanly, * rather than risking arbitrary, non-deterministic * behavior at an undetermined time in the future. * * This method has a time complexity of O(1). * * @return void * retptr != NULL: The iterator. * @return void * retptr == NULL: An error, see pbl_errno: * *
PBL_ERROR_OUT_OF_MEMORY - Out of memory. *
PBL_ERROR_PARAM_LIST - list cannot be iterated. */ PblIterator * pblListReverseIterator( PblList * list /** The list to create the iterator for */ ) { if( !PBL_LIST_IS_LIST( list ) ) { pbl_errno = PBL_ERROR_PARAM_LIST; return NULL; } return pblIteratorReverseNew( list ); }