Index: trunk/psLib/src/collections/psCollectionsErrors.dat
===================================================================
--- trunk/psLib/src/collections/psCollectionsErrors.dat	(revision 2676)
+++ trunk/psLib/src/collections/psCollectionsErrors.dat	(revision 2681)
@@ -32,3 +32,10 @@
 psHash_TABLE_NULL                      Input psHash can not be NULL.
 psHash_DATA_NULL                       Input data can not be NULL.
+#
+psList_LOCATION_INVALID                Specified location, %d, is invalid.
+psList_ITERATOR_INVALID                Specified iterator is not valid.
+psList_ITERATOR_NULL                   Specified iterator is NULL.
+psList_LIST_NULL                       Specified psList reference is NULL. 
+psList_DATA_NULL                       Specified data item is NULL.
+psList_DATA_NOT_FOUND                  Specified data item is not found in the psList.
 
Index: trunk/psLib/src/collections/psCollectionsErrors.h
===================================================================
--- trunk/psLib/src/collections/psCollectionsErrors.h	(revision 2676)
+++ trunk/psLib/src/collections/psCollectionsErrors.h	(revision 2681)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-11-13 00:52:49 $
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-12-10 02:50:14 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -50,4 +50,10 @@
 #define PS_ERRORTEXT_psHash_TABLE_NULL "Input psHash can not be NULL."
 #define PS_ERRORTEXT_psHash_DATA_NULL "Input data can not be NULL."
+#define PS_ERRORTEXT_psList_LOCATION_INVALID "Specified location, %d, is invalid."
+#define PS_ERRORTEXT_psList_ITERATOR_INVALID "Specified iterator is not valid."
+#define PS_ERRORTEXT_psList_ITERATOR_NULL "Specified iterator is NULL."
+#define PS_ERRORTEXT_psList_LIST_NULL "Specified psList reference is NULL. "
+#define PS_ERRORTEXT_psList_DATA_NULL "Specified data item is NULL."
+#define PS_ERRORTEXT_psList_DATA_NOT_FOUND "Specified data item is not found in the psList."
 //~End
 
Index: trunk/psLib/src/collections/psList.c
===================================================================
--- trunk/psLib/src/collections/psList.c	(revision 2676)
+++ trunk/psLib/src/collections/psList.c	(revision 2681)
@@ -6,6 +6,6 @@
  *  @author Robert Daniel DeSonia, MHPCC
  *
- *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-11-16 20:00:20 $
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-12-10 02:50:14 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -29,29 +29,7 @@
 
 // private functions.
-static psListElem* listGetIterator(psList* list);
-static psS32 listGetIteratorIndex(psList* list);
-static void listSetIterator(psList* list, psS32 where, psBool lockList);
 static void listFree(psList* list);
-
-psList* psListAlloc(psPtr data)
-{
-    psList* list = psAlloc(sizeof(psList));
-
-    p_psMemSetDeallocator(list, (psFreeFcn) listFree);
-
-    list->size = 0;
-    list->head = list->tail = NULL;
-    list->p_iter = ITER_INIT_HEAD;
-    list->p_iterIndex = PS_LIST_HEAD;
-
-    pthread_mutex_init(&(list->lock), NULL)
-    ;
-
-    if (data != NULL) {
-        psListAdd(list, PS_LIST_TAIL, data);
-    }
-
-    return list;
-}
+static void listIteratorFree(psListIterator* iter);
+static psBool listIteratorRemove(psListIterator* iterator);
 
 static void listFree(psList* list)
@@ -64,4 +42,6 @@
     ;
 
+    psFree(list->iterators);
+
     for (psListElem* ptr = list->head; ptr != NULL;) {
         psListElem* next = ptr->next;
@@ -81,140 +61,29 @@
 }
 
-psBool psListAdd(psList* list, psS32 location, psPtr data)
-{
-    psListElem* position;
-    psListElem* elem;
-    psS32 cursorIndex = 0;
-
-    if (list == NULL) {
-        return false;
-    }
-
-    if (data == NULL) {
-        return false;
-    }
-
-    if (location <= PS_LIST_UNKNOWN) {
-        // / XXX What is the better way to communicate this failure to the caller?
-        psLogMsg(__func__, PS_LOG_WARN, "The given insert location (%i) for psListAdd is invalid.", location);
-        return false;
-    }
-
-    elem = psAlloc(sizeof(psListElem));
+static void listIteratorFree(psListIterator* iter)
+{
+    if (iter == NULL) {
+        return;
+    }
+
+    // remove this iterator from the parent list
+    psArrayRemove(iter->list->iterators,iter);
+
+}
+
+static psBool listIteratorRemove(psListIterator* iterator)
+{
+    if (iterator == NULL) {
+        return false;
+    }
+
+    psListElem* elem = iterator->cursor;
+    psList* list = iterator->list;
+    int index = iterator->index;
 
     pthread_mutex_lock(&list->lock)
     ;
 
-    if (location > 0 && location > list->size) {
-        psLogMsg(__func__, PS_LOG_WARN,
-                 "Invalid index %d (only %d elements in psList); assuming tail.", location, list->size);
-        location = PS_LIST_TAIL;
-    }
-
-    if (location == PS_LIST_TAIL || list->size == 0) {
-        // insert the element at the end of the list
-        elem->prev = list->tail;
-        elem->next = NULL;
-
-        if (list->tail != NULL) {
-            list->tail->next = elem;
-        }
-
-        if (list->head == NULL) {
-            list->head = elem;
-        }
-        list->tail = elem;
-
-        list->size++;
-        list->p_iter = elem;
-        list->p_iterIndex = list->size - 1;
-    } else {
-        // move ourselves to the given position
-        listSetIterator(list, location, false);
-        position = listGetIterator(list);
-        cursorIndex = listGetIteratorIndex(list);
-
-        if (position == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    "Failed to move cursor to specified location (%d)", location);
-            position = list->head;         // since we no list->size != 0, this must be non-NULL
-        }
-        // insert our new element in front of the given position
-        elem->prev = position->prev;
-        elem->next = position;
-        position->prev = elem;
-
-        if (elem->prev == NULL) {          // must be front of list
-            list->head = elem;
-        } else {
-            elem->prev->next = elem;
-        }
-
-        list->size++;
-        list->p_iter = elem;
-        list->p_iterIndex = cursorIndex;
-    }
-
-    elem->data = psMemIncrRefCounter(data);
-
-    pthread_mutex_unlock(&list->lock)
-    ;
-
-    return true;
-}
-
-
-/*
- * Remove an element from a list
- */
-psBool psListRemove(psList* list, psS32 location, psPtr data)
-{
-    psListElem* elem = NULL;    // element to remove
-    psS32 cursorIndex = 0;
-
-    if (list == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, "list parameter found to be NULL.");
-        return false;
-    }
-    // get exclusive access to list so that other threads will not get in the way.
-    pthread_mutex_lock(&list->lock)
-    ;
-
-    if (location == PS_LIST_UNKNOWN) {
-        // search list for the data item.
-
-        psS32 i = 0;              // index
-
-        for (psListElem* ptr = list->head; ptr != NULL; ptr = ptr->next) {
-            if (ptr->data == data) {
-                location = i;
-                break;
-            }
-            i++;
-        }
-
-        if (location == PS_LIST_UNKNOWN) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Failed to find item in given psList.");
-            pthread_mutex_unlock(&list->lock)
-            ;
-            return false;
-        }
-    }
-    // position the list's cursor to the desired location
-    listSetIterator(list, location, false);
-    elem = listGetIterator(list);
-    cursorIndex = listGetIteratorIndex(list);
-
-    if (elem == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                "Couldn't position to given index (%d) to remove element from list.", location);
-        pthread_mutex_unlock(&list->lock)
-        ;
-        return false;
-    }
-
-    list->size--;
-
-    if (elem->prev == NULL) {              // head of list?
+    if (elem == list->head) {        // head of list?
         list->head = elem->next;
     } else {
@@ -222,18 +91,228 @@
     }
 
-    if (elem->next == NULL) {              // tail of list?
+    if (elem == list->tail) {        // tail of list?
         list->tail = elem->prev;
-
-        // removed tail, so iter should be the last element of list to keep it valid
-        if (list->size > 0) {
-            list->p_iter = list->tail;
-            list->p_iterIndex = list->size - 1;
+    } else {
+        elem->next->prev = elem->prev;
+    }
+
+    psArray* iterators = list->iterators;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->cursor == elem) {
+            iter->cursor = NULL;
+        } else if (iter->index > index) {
+            iter->index--;
+        }
+    }
+
+    list->size--;
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    // OK, delete orphaned list element and its data
+    psFree(elem->data);
+    psFree(elem);
+
+    return true;
+}
+
+psList* psListAlloc(psPtr data)
+{
+    psList* list = psAlloc(sizeof(psList));
+
+    p_psMemSetDeallocator(list, (psFreeFcn) listFree);
+
+    list->size = 0;
+    list->head = list->tail = NULL;
+    list->iterators = psArrayAlloc(16);
+
+    // create a default iterator
+    list->iterators->data[0] = psListIteratorAlloc(list,PS_LIST_HEAD);
+    list->iterators->n = 1;
+
+    pthread_mutex_init(&(list->lock), NULL)
+    ;
+
+    if (data != NULL) {
+        psListAdd(list, PS_LIST_TAIL, data);
+    }
+
+    return list;
+}
+
+psListIterator* psListIteratorAlloc(psList* list, int location)
+{
+    psListIterator* iter = psAlloc(sizeof(psListIterator));
+
+    p_psMemSetDeallocator(iter, (psFreeFcn) listIteratorFree);
+
+    // initialize the attributes
+    iter->list = list;
+    iter->cursor = NULL;
+    iter->index = 0;
+    iter->offEnd = false;
+
+    // add to the list's array of iterators
+    psArray* listIterators = list->iterators;
+    int num = listIterators->n;
+    if ( num >= listIterators->nalloc) {
+        // need to resize the array to make more room for another iterator.
+        list->iterators = psArrayRealloc(listIterators,listIterators->nalloc*2);
+        listIterators = list->iterators;
+    }
+    listIterators->data[num] = iter;
+    listIterators->n = num+1;
+
+    if (! psListIteratorSet(iter,location)) {
+        psFree(iter);
+        iter = NULL;
+    }
+
+    return iter;
+}
+
+psBool psListIteratorSet(psListIterator* iterator,
+                         int location)
+{
+    if (iterator == NULL) {
+        return false;
+    }
+
+    psList* list = iterator->list;
+
+    if (location >= list->size) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Specified index, %d, is beyond the end of the psList, which "
+                 "has only %d elements.  Assuming tail.",
+                 location, list->size);
+        location = PS_LIST_TAIL;
+    }
+
+    if (location == PS_LIST_TAIL) {
+        iterator->cursor = list->tail;
+        iterator->index = list->size - 1;
+        iterator->offEnd = false;
+        return true;
+    }
+
+    if (location <= 0) {   // Invalid index
+        return false;
+    }
+
+
+    psListElem* cursor = iterator->cursor;
+    int index = iterator->index;
+    if (cursor == NULL) {      // set the cursor to the head if it is NULL
+        if (location > list->size/2) { // closer to tail or head?
+            cursor = list->tail;
+            index = list->size - 1;
         } else {
-            list->p_iter = ITER_INIT_TAIL;
+            cursor = list->head;
+            index = 0;
+        }
+    }
+
+    if (location < index) {
+        psS32 diff = index - location;
+
+        for (psS32 count = 0; count < diff; count++) {
+            cursor = cursor->prev; // shouldn't need to check for NULL
         }
     } else {
-        elem->next->prev = elem->prev;
-        list->p_iter = elem->next;
-        list->p_iterIndex = cursorIndex;
+        psS32 diff = location - index;
+
+        for (psS32 count = 0; count < diff; count++) {
+            cursor = cursor->next; // shouldn't need to check for NULL
+        }
+    }
+    iterator->cursor = cursor;
+    iterator->index = location;
+    iterator->offEnd = false;
+
+    return true;
+}
+
+psBool psListAdd(psList* list, psS32 location, psPtr data)
+{
+
+    if (list == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_LIST_NULL);
+        return false;
+    }
+
+    if (data == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_DATA_NULL);
+        return false;
+    }
+
+    // move ourselves to the given position
+    if (list->iterators->n < 1 ||
+            ! psListIteratorSet(list->iterators->data[0],location)) {
+        // oh no, I can't find where to add this!
+        psError(PS_ERR_UNKNOWN, false,
+                PS_ERRORTEXT_psList_LOCATION_INVALID,
+                location);
+        return false;
+    }
+
+    if (location == PS_LIST_TAIL) {
+        // insert the element at the end of the list
+        return psListAddAfter(list->iterators->data[0],data);
+    } else {
+        return psListAddBefore(list->iterators->data[0],data);
+    }
+}
+
+bool psListAddAfter(psListIterator* iterator, void* data)
+{
+    if (data == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_DATA_NULL);
+        return false;
+    }
+
+    if (iterator == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_ITERATOR_NULL);
+        return false;
+    }
+
+    psListElem* cursor = iterator->cursor;
+
+    if (cursor == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                PS_ERRORTEXT_psList_ITERATOR_INVALID);
+        return false;
+    }
+
+    psList* list = iterator->list;
+    psListElem* elem = psAlloc(sizeof(psListElem));
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    // set the new list element's attributes
+    elem->prev = cursor;
+    elem->next = cursor->next;
+    elem->data = data;
+
+    cursor->next = elem;
+    list->size++;
+
+    if (cursor == list->tail) {
+        list->tail = elem;
+    }
+
+    psArray* iterators = list->iterators;
+    int index = iterator->index;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->index > index) {
+            iter->index++;
+        }
     }
 
@@ -241,152 +320,129 @@
     ;
 
-    // OK, delete list element and its data
-    psFree(elem->data);
-    psFree(elem);
-
     return true;
 }
 
-void psListSetIterator(psList* list, psS32 where)
-{
-    listSetIterator(list, where, true);
-}
-
-static void listSetIterator(psList* list, psS32 where, psBool lockList)
-{
-    psListElem* cursor;
-    psS32 position;
-
+bool psListAddBefore(psListIterator* iterator, void* data)
+{
+    if (data == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_DATA_NULL);
+        return false;
+    }
+
+    if (iterator == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_ITERATOR_NULL);
+        return false;
+    }
+
+    psListElem* cursor = iterator->cursor;
+
+    if (cursor == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                PS_ERRORTEXT_psList_ITERATOR_INVALID);
+        return false;
+    }
+
+    psList* list = iterator->list;
+    psListElem* elem = psAlloc(sizeof(psListElem));
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    // set the new list element's attributes
+    elem->prev = cursor->prev;
+    elem->next = cursor;
+    elem->data = data;
+
+    cursor->prev = elem;
+    list->size++;
+
+    if (cursor == list->head) {
+        list->head = elem;
+    }
+
+    psArray* iterators = list->iterators;
+    int index = iterator->index;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->index >= index) {
+            iter->index++;
+        }
+    }
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    return true;
+}
+
+psBool psListRemove(psList* list,
+                    psS32 location)
+{
     if (list == NULL) {
         psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                "Unexpected null pointer for psList parameter.");
-        return;
-    }
-
-    if (where == PS_LIST_CURRENT) {
-        return;
-    }
-
-    if (lockList) {
-        pthread_mutex_lock(&list->lock)
-        ;
-        // don't want the list changing on us while we move about
-    }
-
-    if (where >= (psS32)list->size) {
-        list->p_iter = NULL;
-        if (lockList) {
-            pthread_mutex_unlock(&list->lock)
-            ;
-        }
-        return;
-    }
-
-    switch (where) {
-    case PS_LIST_HEAD:
-        list->p_iter = ITER_INIT_HEAD;
-        break;
-
-    case PS_LIST_TAIL:
-        list->p_iter = ITER_INIT_TAIL;
-        break;
-
-    case PS_LIST_PREVIOUS:
-        cursor = listGetIterator(list);
-        position = listGetIteratorIndex(list);
-
-        if (cursor != NULL) {
-            list->p_iter = cursor->prev;
-            list->p_iterIndex = position - 1;
-        }
-        break;
-
-    case PS_LIST_NEXT:
-        cursor = listGetIterator(list);
-        position = listGetIteratorIndex(list);
-
-        if (cursor != NULL) {
-            list->p_iter = cursor->next;
-            list->p_iterIndex = position + 1;
-        }
-        break;
-
-    case PS_LIST_CURRENT:
-        break;
-
-    default:
-        if (where <= PS_LIST_HEAD) {   // bascially same as PS_LIST_UNKNOWN above
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    "Can't move to an unknown position.  Not moving the iterator position.");
-        } else {
-            cursor = listGetIterator(list);
-            if (cursor == NULL) {      // reset the iterator if it is invalid
-                list->p_iter = ITER_INIT_HEAD;
-                list->p_iterIndex = 0;
-            }
-
-            psS32 position = listGetIteratorIndex(list);
-
-            if (where < position) {
-                psS32 diff = position - where;
-
-                for (psS32 count = 0; count < diff; count++) {
-                    listSetIterator(list, PS_LIST_PREVIOUS, false);
-                }
-            } else {
-                psS32 diff = where - position;
-
-                for (psS32 count = 0; count < diff; count++) {
-                    listSetIterator(list, PS_LIST_NEXT, false);
-                }
-            }
-        }
-        break;
-    }
-
-    if (lockList) {
-        pthread_mutex_unlock(&list->lock)
-        ;
-    }
-}
-
-psListElem* listGetIterator(psList* list)
+                PS_ERRORTEXT_psList_LIST_NULL);
+        return false;
+    }
+
+    // move ourselves to the given position
+    psListIterator* defaultIterator = list->iterators->data[0];
+    if (list->iterators->n < 1 ||
+            ! psListIteratorSet(defaultIterator,location)) {
+        // oh no, I can't find where to add this!
+        psError(PS_ERR_UNKNOWN, false,
+                PS_ERRORTEXT_psList_LOCATION_INVALID,
+                location);
+        return false;
+    }
+
+    return listIteratorRemove(defaultIterator);
+}
+
+psBool psListRemoveData(psList* list,
+                        psPtr data)
 {
     if (list == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_LIST_NULL);
+        return false;
+    }
+
+    if (data == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_DATA_NULL);
+        return false;
+    }
+
+    psListIterator* iterator = list->iterators->data[0];
+    psListIteratorSet(iterator,PS_LIST_HEAD);
+
+    psPtr iteratorData = psListGetNext(iterator);
+    while (iteratorData != NULL && iteratorData != data) {
+        iteratorData = psListGetNext(iterator);
+    }
+
+    if (iteratorData == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psList_DATA_NOT_FOUND);
+        return false;
+    }
+
+    return listIteratorRemove(iterator);
+}
+
+psPtr psListGet(psList* list, psS32 location)
+{
+    psListIterator* iterator = list->iterators->data[0];
+
+    if (! psListIteratorSet(iterator,location)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                PS_ERRORTEXT_psList_LOCATION_INVALID,
+                location);
         return NULL;
     }
 
-    if (list->p_iter == ITER_INIT_HEAD) {
-        return list->head;
-    } else if (list->p_iter == ITER_INIT_TAIL) {
-        return list->tail;
-    } else {
-        return list->p_iter;
-    }
-}
-
-psS32 listGetIteratorIndex(psList* list)
-{
-    if (list->p_iter == ITER_INIT_HEAD) {
-        return 0;
-    } else if (list->p_iter == ITER_INIT_TAIL) {
-        return list->size - 1;
-    } else {
-        return list->p_iterIndex;
-    }
-}
-
-psPtr psListGet(psList* list, psS32 location)
-{
-    psListElem* element;
-
-    psListSetIterator(list, location);
-    element = listGetIterator(list);
-
-    if (element == NULL) {
-        return NULL;
-    } else {
-        return element->data;
-    }
+    return iterator->cursor->data;
 }
 
@@ -394,17 +450,33 @@
  * and now return the previous/next element of the list
  */
-psPtr psListGetNext(psList* list)
-{
-    return psListGet(list, PS_LIST_NEXT);
-}
-
-psPtr psListGetPrevious(psList* list)
-{
-    return psListGet(list, PS_LIST_PREVIOUS);
-}
-
-psPtr psListGetCurrent(psList* list)
-{
-    return psListGet(list, PS_LIST_CURRENT);
+psPtr psListGetNext(psListIterator* iterator)
+{
+    if (iterator == NULL || iterator->cursor == NULL) {
+        return NULL;
+    }
+
+    psPtr data = iterator->cursor->data;
+
+    iterator->cursor = iterator->cursor->next;
+    iterator->index++;
+    if (iterator->cursor == NULL) {
+        iterator->offEnd = true;
+    }
+
+    return data;
+}
+
+psPtr psListGetPrevious(psListIterator* iterator)
+{
+    if (iterator == NULL || iterator->cursor == NULL) {
+        return NULL;
+    }
+
+    psPtr data = iterator->cursor->data;
+
+    iterator->cursor = iterator->cursor->prev;
+    iterator->index--;
+
+    return data;
 }
 
@@ -467,4 +539,5 @@
     // convert to indexable vector for use by qsort.
     arr = psListToArray(list);
+    psArray* iterators = psMemIncrRefCounter(list->iterators);
     psFree(list);
 
@@ -473,6 +546,13 @@
     // convert back to linked list
     list = psArrayToList(arr);
+    psFree(list->iterators);
+    list->iterators = iterators;
     psFree(arr);
 
+    // sorting should invalidate all iterator positions.
+    for (int i = 0; i < iterators->n; i++) {
+        ((psListIterator*)iterators->data[i])->cursor = NULL;
+    }
+
     return list;
 }
Index: trunk/psLib/src/collections/psList.h
===================================================================
--- trunk/psLib/src/collections/psList.h	(revision 2676)
+++ trunk/psLib/src/collections/psList.h	(revision 2681)
@@ -10,6 +10,6 @@
  *  @ingroup LinkedList
  *
- *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-11-16 20:00:20 $
+ *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-12-10 02:50:14 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -34,8 +34,4 @@
     PS_LIST_HEAD = 0,                  ///< at head
     PS_LIST_TAIL = -1,                 ///< at tail
-    PS_LIST_PREVIOUS = -2,             ///< previous element
-    PS_LIST_CURRENT = -3,              ///< current element
-    PS_LIST_NEXT = -4,                 ///< next element
-    PS_LIST_UNKNOWN = -5               ///< unknown position (should be last in enum list)
 };
 
@@ -59,8 +55,10 @@
     psListElem* head;                  ///< first element on list (may be NULL)
     psListElem* tail;                  ///< last element on list (may be NULL)
-    psArray* iterators;                ///< iterators
+    psArray* iterators;
+    ///< array of all iterators associated with this list.  First iterator is
+    ///< used internally to improve performance when using indexed access, all
+    ///< others are user-level iterators created by psListIteratorAlloc.
+
     pthread_mutex_t lock;              ///< mutex to lock a node during changes
-psListElem* p_iter;                ///< internal cursor for increased performance index accessing
-int p_iterIndex;                   ///< index position of the iter.
 }
 psList;
@@ -77,6 +75,6 @@
 {
 psList* list;                      ///< List iterator to works on
-psU32 number;                      ///< List iterator number
 psListElem* cursor;                ///< current cursor position
+int index;                         ///< the index number in the list
 bool offEnd;                       ///< Iterator off the end?
 }
@@ -94,26 +92,68 @@
 ;
 
+/** Creates a psListIterator object and associates it with a psList.
+ *
+ *  @return psListIterator* A new psListIterator object.
+ */
+psListIterator* psListIteratorAlloc(
+    psList* list,                      ///< the psList to iterate with
+    int location                       ///< the initial starting point.
+    ///<  This can be a numeric index, PS_LIST_HEAD, or PS_LIST_TAIL.
+);
+
+/** Set the iterator of the list to a given position.  If location is invalid the
+ *  iterator position is not changed.
+ *
+ *  @return psBool        TRUE if iterator successfully set, otherwise FALSE.
+ */
+psBool psListIteratorSet(
+    psListIterator* iterator,            ///< list iterator
+    int location                         ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
 /** Adds an element to a psList at position given.
  *
- *  @return psList* The psList with added data item.  If list parameter is
- *                      NULL, the return value will also be NULL.
+ *  @return psBool        TRUE if item was successfully added, otherwise FALSE.
  */
 psBool psListAdd(
-    psList* restrict list,             ///< list to add to (if NULL, nothing is done)
-    psS32 location,                      ///< index, PS_LIST_HEAD, PS_LIST_TAIL, or numbered location.
+    psList* restrict list,             ///< list to add item to
+    psS32 location,                    ///< index, PS_LIST_HEAD, PS_LIST_TAIL, or numbered location.
     psPtr data                         ///< data item to add.  If NULL, list is not modified.
 );
 
-/** Remove an item from a list.  If location parameter is PS_LIST_UNKNOWN,
+/** Adds an data item to a psList at position just after the list position given
+ *
+ *  @return psBool        TRUE if item was successfully added, otherwise FALSE.
+ */
+psBool psListAddAfter(
+    psListIterator* list,              ///< list position to add item to
+    psPtr data                         ///< data item to add.  If NULL, list is not modified.
+);
+
+/** Adds an data item to a psList at position just before the list position given
+ *
+ *  @return psBool        TRUE if item was successfully added, otherwise FALSE.
+ */
+psBool psListAddBefore(
+    psListIterator* list,              ///< list position to add item to
+    psPtr data                         ///< data item to add.  If NULL, list is not modified.
+);
+
+/** Remove an item at the specified location from a list.
  *
  *  @return psBool        TRUE if element is successfully removed, otherwise FALSE.
  */
 psBool psListRemove(
-    psList* restrict list,
-    ///< list to remove element from
-    psS32 location,
-    ///< index of item, or PS_LIST_UNKNOWN, PS_LIST_NEXT, PS_LIST_PREV, or numbered location.
-    psPtr data
-    ///< if location is PS_LIST_UNKNOWN, data item to find and remove, otherwise this is ignored.
+    psList* restrict list,             ///< list to remove element from
+    psS32 location                     ///< index of item
+);
+
+/** Remove an item from a list.
+ *
+ *  @return psBool        TRUE if element is successfully removed, otherwise FALSE.
+ */
+psBool psListRemoveData(
+    psList* restrict list,             ///< list to remove element from
+    psPtr data                         ///< data item to find and remove
 );
 
@@ -127,47 +167,23 @@
 psPtr psListGet(
     psList* restrict list,             ///< list to retrieve element from
-    psS32 location                       ///< index number, or PS_LIST_NEXT, PS_LIST_PREV, PS_LIST_UNKNOWN
-);
-
-/** Set the iterator of the list to a given position.  If location is invalid the
- *  iterator position is not changed.
- *
- */
-void psListSetIterator(
-    psList* restrict list,             ///< list to retrieve element from
-    psS32 location                       ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
-);
-
-/** Get next element relative to the iterator.  This also moves the iterator to
- *  the next list position.
- *
- *  @return psPtr       the data item next on the list or NULL if the iterator
- *                      is already pointing to the last element or the list
- *                      parameter was NULL.
+    psS32 location                     ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Position the specified iterator to the next item in list.
+ *
+ *  @return psPtr       the data item at the new iterator position or NULL if the
+ *                      iterator goes past the end of the list.
  */
 psPtr psListGetNext(
-    psList* restrict list              ///< list to retrieve element from
-);
-
-/** Get current element according to the psList's iterator cursor.  This does
- *  not move the iterator location.
- *
- *  @return psPtr       the data item cooresponding to current iterator
- *                      cursor position of the list, or NULL if either the
- *                      iterator is not valid or list parameter was NULL.
- */
-psPtr psListGetCurrent(
-    psList* restrict list              ///< list to retrieve element from
-);
-
-/** Get previous element relative to list's iterator. This also moves the
- *  iterator to the previous list position.
- *
- *  @return psPtr       the data item previous on the list or NULL if the iterator
- *                      is already pointing to the first element or the list
- *                      parameter was NULL.
+    psListIterator* restrict iterator  ///< iterator to move
+);
+
+/** Position the specified iterator to the previous item in list.
+ *
+ *  @return psPtr       the data item at the new iterator position or NULL if the
+ *                      iterator goes past the beginning of the list.
  */
 psPtr psListGetPrevious(
-    psList* restrict list              ///< list to retrieve element from
+    psListIterator* restrict iterator  ///< iterator to move
 );
 
Index: trunk/psLib/src/collections/psMetadata.c
===================================================================
--- trunk/psLib/src/collections/psMetadata.c	(revision 2676)
+++ trunk/psLib/src/collections/psMetadata.c	(revision 2681)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.42 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-12-07 23:27:25 $
+*  @version $Revision: 1.43 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-12-10 02:50:14 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -352,8 +352,6 @@
 {
     psList* mdList = NULL;
-    psList* entryList = NULL;
     psHash* mdTable = NULL;
     psMetadataItem* entry = NULL;
-    psMetadataItem* entryChild = NULL;
 
 
@@ -375,29 +373,4 @@
         }
 
-        if (entry->type == PS_META_LIST) {
-
-            // Table entry has children. Entry and children must be removed from metadata collection's list
-            psListSetIterator(entryList, PS_LIST_HEAD);
-            entryChild = psListGetCurrent(entryList);
-            while(entryChild != NULL) {
-                if (!psListRemove(mdList, PS_LIST_UNKNOWN, entryChild)) {
-                    psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
-                    return false;
-                }
-                entryChild = psListGetNext(entryList);
-            }
-        } else {
-
-            // Table entry has no children. Remove entry from metadata collection's list
-            if (!psListRemove(mdList, PS_LIST_UNKNOWN, entry)) {
-                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
-                return false;
-            }
-        }
-        // Remove entry from metadata collection's table
-        if (!psHashRemove(mdTable, key)) {
-            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-            return false;
-        }
     } else {
 
@@ -414,6 +387,15 @@
             return false;
         }
-        // Use recursive remove, now that key is known
-        psMetadataRemove(md, PS_LIST_UNKNOWN, key);
+    }
+
+    if (!psListRemoveData(mdList, entry)) {
+        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
+        return false;
+    }
+
+    // Remove entry from metadata collection's table
+    if (!psHashRemove(mdTable, key)) {
+        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+        return false;
     }
 
Index: trunk/psLib/src/collections/psMetadataIO.c
===================================================================
--- trunk/psLib/src/collections/psMetadataIO.c	(revision 2676)
+++ trunk/psLib/src/collections/psMetadataIO.c	(revision 2681)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-12-06 19:59:57 $
+*  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-12-10 02:50:14 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -19,4 +19,5 @@
 #include <string.h>
 #include <ctype.h>
+#include <limits.h>
 
 #include "psAbort.h"
@@ -598,5 +599,5 @@
                 if(metadataItem->type!=PS_META_LIST) {
                     if(overwrite) {
-                        psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                        psMetadataRemove(md, INT_MIN, strName);
                     } else {
                         (*nFail)++;
@@ -790,6 +791,5 @@
     PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
     PS_PTR_CHECK_NULL_GENERAL(metadataItem->data.list, return);
-    psListSetIterator(metadataItem->data.list, PS_LIST_TAIL);
-    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->data.list);
+    metadataItem = (psMetadataItem*)psListGet(metadataItem->data.list,PS_LIST_TAIL);
     htAtts = (psHash*)metadataItem->data.list;
     PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
@@ -848,5 +848,5 @@
             if(metadataItem->type != PS_META_LIST) {
                 if(overwrite) {
-                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                    psMetadataRemove(md, INT_MIN, strName);
                 } else {
                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
@@ -943,6 +943,5 @@
     PS_PTR_CHECK_NULL_GENERAL(tables, return);
     PS_PTR_CHECK_NULL_GENERAL(tables->data.list, return);
-    psListSetIterator(tables->data.list, PS_LIST_TAIL);
-    table = (psMetadataItem*)psListGetCurrent(tables->data.list);
+    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
     htAtts = (psHash*)table->data.list;
     PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
@@ -1002,5 +1001,5 @@
             if(metadataItem->type != PS_META_LIST) {
                 if(overwrite) {
-                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                    psMetadataRemove(md, INT_MIN, strName);
                 } else {
                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
@@ -1045,6 +1044,5 @@
     PS_PTR_CHECK_NULL_GENERAL(tables, return);
     PS_PTR_CHECK_NULL_GENERAL(tables->data.list, return);
-    psListSetIterator(tables->data.list, PS_LIST_TAIL);
-    table = (psMetadataItem*)psListGetCurrent(tables->data.list);
+    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
     htAtts = (psHash*)table->data.list;
     PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
@@ -1070,5 +1068,5 @@
 
     // Free temporary metadata item and its hash table
-    psListRemove(tables->data.list, PS_LIST_TAIL, table);
+    psListRemove(tables->data.list, PS_LIST_TAIL);
 
     psFree(psEndTagName);
