IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 454


Ignore:
Timestamp:
Apr 19, 2004, 11:01:12 AM (22 years ago)
Author:
desonia
Message:

from IP3

Location:
trunk/psLib/src/sysUtils
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/sysUtils/psDList.c

    r453 r454  
     1/*
     2 * Minimal support for doubly linked lists
     3 */
     4#include <stdlib.h>
     5#include <stdio.h>
     6#include <assert.h>
     7#include "psLib.h"
     8
     9static psDlistElem *dlistElemAlloc(void)
     10{
     11    return(psAlloc(sizeof(psDlistElem)));
     12}
     13
     14static void dlistElemFree(psDlistElem *elem)
     15{
     16    psFree(elem);
     17}
     18
     19/*****************************************************************************/
     20
     21psDlist *psDlistAlloc(void *data) // initial data item; may be NULL
     22{
     23    psDlist *list = psAlloc(sizeof(psDlist));
     24
     25    list->n = 0;
     26    list->head = list->tail = NULL;
     27    list->iter = NULL;
     28    if (data != NULL)
     29    {
     30        psDlistAdd(list, data, PS_DLIST_TAIL);
     31    }
     32
     33    return list;
     34}
     35
     36void psDlistFree(psDlist *list,  // list to destroy
     37                 void (*elemFree)(void *)) // destructor for data on list
     38{
     39    if (list == NULL)
     40    {
     41        return;
     42    }
     43
     44    psDlistElem *ptr = list->head;
     45    while (ptr != NULL)
     46    {
     47        psDlistElem *next = ptr->next;
     48
     49        if (elemFree == NULL) {
     50            psMemDecrRefCounter(ptr->data);
     51        } else {
     52            elemFree(psMemDecrRefCounter(ptr->data));
     53        }
     54        dlistElemFree(ptr);
     55
     56        ptr = next;
     57    }
     58
     59    psFree(list);
     60}
     61
     62/*****************************************************************************/
     63/*
     64 * Add an element to a list
     65 */
     66psDlist *psDlistAdd(psDlist *list, // list to add to; may be NULL
     67                    void *data,  // data to add
     68                    int where)  // where to add data. PS_DLIST_HEAD,
     69// PS_DLIST_TAIL, or an integer
     70{
     71    psDlistElem *elem = dlistElemAlloc();
     72
     73    if (list == NULL)
     74    {
     75        list = psDlistAlloc(NULL);
     76    }
     77
     78    if (where > list->n)
     79    {  // XXX need better diagnostic here
     80        fprintf(stderr, "Invalid index %d (only %d elements)\n",
     81                where, list->n);
     82        dlistElemFree(elem);  // cleanup
     83
     84        return list;
     85    }
     86
     87    if (where == PS_DLIST_HEAD)
     88    { // easy
     89        elem->prev = NULL;
     90        elem->next = list->head;
     91        elem->data = psMemIncrRefCounter(data);
     92
     93        if (list->head != NULL) {
     94            list->head->prev = elem;
     95        }
     96
     97        list->head = elem;
     98        if (list->tail == NULL) {
     99            list->tail = elem;
     100        }
     101        list->n++;
     102    } else if (where == PS_DLIST_TAIL)
     103    { // also easy
     104        elem->prev = list->tail;
     105        elem->next = NULL;
     106        elem->data = psMemIncrRefCounter(data);
     107
     108        if (list->tail != NULL) {
     109            list->tail->next = elem;
     110        }
     111
     112        list->tail = elem;
     113        if (list->head == NULL) {
     114            list->head = elem;
     115        }
     116        list->n++;
     117    } else
     118    {    // XXX
     119        fprintf(stderr, "Insertion into psDlists is not yet supported\n");
     120        return psDlistAdd(list, data, PS_DLIST_TAIL);
     121    }
     122
     123    return list;
     124}
     125
     126/*****************************************************************************/
     127
     128psDlist *psDlistAppend(psDlist *list, // list to add to; may be NULL
     129                       void *data) // data to add at end
     130{
     131    return psDlistAdd(list, data, PS_DLIST_TAIL);
     132}
     133
     134/*****************************************************************************/
     135/*
     136 * Remove an element from a list
     137 */
     138void *psDlistRemove(psDlist *list, // list to remove element from
     139                    void *data,  // data item to remove (or NULL)
     140                    int which)  // index of item, if known.
     141// PS_DLIST_UNKNOWN, or PS_DLIST_HEAD,
     142// or PS_DLIST_TAIL
     143{
     144    psDlistElem *elem = NULL;  // element to remove
     145    assert (list != NULL);
     146
     147    if (data != NULL)
     148    {
     149        assert (which == PS_DLIST_UNKNOWN);
     150
     151        int i = 0;   // index
     152        for (psDlistElem *ptr = list->head; ptr != NULL; ptr = ptr->next, i++) {
     153            if (ptr->data == data) {
     154                return psDlistRemove(list, NULL, i);
     155            }
     156        }
     157
     158        psTrace("utils.dlist.remove", 5, "Failed to find 0x%x on psDlist 0x%x", data, list);
     159
     160        return NULL;
     161    }
     162
     163    if (which == PS_DLIST_HEAD || which == 0)
     164    {
     165        if (list->head == NULL) {
     166            return NULL;
     167        } else {
     168            elem = list->head;
     169
     170            if (list->head->next != NULL) {
     171                list->head->next->prev = NULL;
     172            }
     173            list->head = list->head->next;
     174            list->n--;
     175
     176            if (list->head == NULL) {
     177                list->tail = NULL;
     178            }
     179        }
     180    } else if (which == PS_DLIST_TAIL || which == list->n - 1)
     181    {
     182        if (list->tail == NULL) {
     183            return NULL;
     184        } else {
     185            elem = list->tail;
     186            if (list->tail->prev != NULL) {
     187                list->tail->prev->next = NULL;
     188            }
     189            list->tail = list->tail->prev;
     190            list->n--;
     191
     192            if (list->tail == NULL) {
     193                list->head = NULL;
     194            }
     195        }
     196    } else if (which != PS_DLIST_UNKNOWN)
     197    { // an index in the middle of the list
     198        assert (which != 0 && which != list->n - 1);
     199
     200        if (which < 0 || which >= list->n) { // out of bounds
     201            psError(__func__, PS_ERR_BAD_INDEX, 1, "Index %d is not in range [0..%d] for list 0x%x", which, list->n,
     202                    list);
     203            return NULL;
     204        }
     205
     206        int i = 0;   // index
     207        for (psDlistElem *ptr = list->head; ptr != NULL; ptr = ptr->next, i++) {
     208            if (i == which) {
     209                ptr->prev->next = ptr->next;
     210                ptr->next->prev = ptr->prev;
     211
     212                elem = ptr;
     213            }
     214        }
     215    }
     216    /*
     217     * OK, delete list element and return the data
     218     */
     219    assert (elem != NULL);
     220    data = elem->data;
     221    dlistElemFree(elem);
     222
     223    return psMemDecrRefCounter(data);
     224}
     225
     226/*****************************************************************************/
     227/*
     228 * Retrieve an element from the list, or iterate over list.
     229 *
     230 * If which is psDlist{Next,Prev} return the next/previous
     231 * data and move the iteration cursor
     232 *
     233 * If which is psDlist{Head,Tail} initialise the iteration pointer
     234 * and return the head/tail
     235 *
     236 * Otherwise, return the desired element
     237 */
     238#define ITER_INIT_HEAD ((void *)1) // next iteration should return head
     239#define ITER_INIT_TAIL ((void *)2) // next iteration should return tail
     240
     241void *psDlistGet(
     242    const psDlist *list,  // list to retrieve element from
     243    int which)    // index of item, or PS_DLIST_NEXT,
     244// or PS_DLIST_PREV
     245{
     246    assert (list != NULL);
     247
     248    switch (which) {
     249    case PS_DLIST_HEAD:  // easy
     250        ((psDlist *)list)->iter = ITER_INIT_HEAD;
     251        return (list->head == NULL) ? NULL : list->head->data;
     252    case PS_DLIST_TAIL:  // also easy
     253        ((psDlist *)list)->iter = ITER_INIT_TAIL;
     254        return (list->tail == NULL) ? NULL : list->tail->data;
     255    case PS_DLIST_PREV:  // use iterator
     256    case PS_DLIST_NEXT:
     257        if (list->iter == NULL) {
     258            return NULL;
     259        } else if (list->iter == ITER_INIT_HEAD) {
     260            ((psDlist *)list)->iter = list->head;
     261        } else if (list->iter == ITER_INIT_TAIL) {
     262            ((psDlist *)list)->iter = list->tail;
     263        } else if (which == PS_DLIST_PREV) {
     264            ((psDlist *)list)->iter = list->iter->prev;
     265        } else if (which == PS_DLIST_NEXT) {
     266            ((psDlist *)list)->iter = list->iter->next;
     267        } else {
     268            fprintf(stderr,"You cannot get here\n");
     269            abort();
     270        }
     271
     272        if (list->iter == NULL) {
     273            return NULL;
     274        }
     275        return list->iter->data; // XXX what if data is NULL?
     276
     277        break;
     278    default:    // XXX
     279        fprintf(stderr,
     280                "Retrieval from psDlists by index is not yet supported\n");
     281        return NULL;
     282    }
     283}
     284
     285/*****************************************************************************/
     286/*
     287 * Some wrappers for those iteration calls using psDlistGet.
     288 *
     289 * First a call to set the iteration pointer to the head of the list
     290 */
     291void psDlistSetIterator(psDlist *list, // the list in question
     292                        int where, // where on the list should I start?
     293                        int which) // @notused@ the desired iterator
     294{
     295    if (where != PS_DLIST_HEAD && where != PS_DLIST_TAIL)
     296    {
     297        psError(__func__, PS_ERR_UNKNOWN, 1, "Invalid where argument: %d; assuming PS_DLIST_HEAD", where);
     298        where = PS_DLIST_HEAD;
     299    }
     300
     301    psDlistGet(list, where); // initialise iterator at head/tail
     302}
     303
     304/*
     305 * and now return the previous/next element of the list
     306 */
     307void *psDlistGetNext(psDlist *list, // the list in question
     308                     int which)  // @notused@ the desired iterator
     309{
     310    return psDlistGet(list, PS_DLIST_NEXT);
     311}
     312
     313void *psDlistGetPrev(psDlist *list, // the list in question
     314                     int which)  // @notused@ the desired iterator
     315{
     316    return psDlistGet(list, PS_DLIST_PREV);
     317}
     318
     319/*****************************************************************************/
     320/*
     321 * Convert a psDlist to/from a psVoidPtrArray
     322 */
     323psVoidPtrArray *psDlistToArray(psDlist *restrict dlist)
     324{
     325    if (dlist == NULL) {
     326        return NULL;
     327    }
     328
     329    psVoidPtrArray *restrict arr = psVoidPtrArrayAlloc(dlist->n, dlist->n);
     330
     331    psDlistElem *ptr = dlist->head;
     332    for (int i = 0, n = dlist->n; i < n; i++) {
     333        arr->arr[i] = ptr->data;
     334
     335        ptr->data = NULL;
     336        ptr = ptr->next;
     337    }
     338
     339    psDlistFree(dlist, NULL);
     340
     341    return arr;
     342}
     343
     344psDlist *psArrayToDlist(psVoidPtrArray *arr)
     345{
     346    psDlist *list = psDlistAlloc(NULL); // list of elements
     347
     348    for (int i = 0, n = arr->n; i < n; i++) {
     349        psDlistAppend(list,
     350                      psMemDecrRefCounter(arr->arr[i])); // it's already Incr
     351        arr->arr[i] = NULL;
     352    }
     353
     354    psVoidPtrArrayFree(arr, NULL);
     355
     356    return list;
     357}
  • trunk/psLib/src/sysUtils/psDList.h

    r453 r454  
    1 //
    2 // C++ Interface: psDList
    3 //
    4 // Description:
    5 //
    6 //
    7 // Author: Robert DeSonia <robert.desonia@mhpcc.hpc.mil>, (C) 2004
    8 //
    9 // Copyright: See COPYING file that comes with this distribution
    10 //
    11 //
     1#if !defined(PS_DLIST_H)
     2#define PS_DLIST_H
     3
     4/** \file psDlist.h
     5 *  \brief Support for doubly linked lists
     6 *  \ingroup DataGroup
     7 */
     8
     9/** Doubly-linked list element */
     10typedef struct psDlistElem
     11{
     12    struct psDlistElem *prev;  ///< previous link in list
     13    struct psDlistElem *next;  ///< next link in list
     14    void *data;    ///< real data item
     15}
     16psDlistElem;
     17
     18/** Doubly-linked list */
     19typedef struct
     20{
     21    int n;    ///< number of elements on list
     22    psDlistElem *head;   ///< first element on list (may be NULL)
     23    psDlistElem *tail;   ///< last element on list (may be NULL)
     24    psDlistElem *iter;   ///< iteration cursor
     25}
     26psDlist;
     27
     28/** Special values of index into list */
     29enum {
     30    PS_DLIST_HEAD = 0,   ///< at head
     31    PS_DLIST_TAIL = -1,   ///< at tail
     32    PS_DLIST_UNKNOWN = -2,  ///< unknown position
     33    PS_DLIST_PREV = -3,   ///< previous element
     34    PS_DLIST_NEXT = -4   ///< next element
     35};
     36
     37/** Functions **************************************************************/
     38/** \addtogroup DataGroup General Data Container Utilities
     39 *  \{
     40 */
     41
     42/** Constructor */
     43psDlist *psDlistAlloc(void *data) ///< initial data item; may be NULL
     44;
     45
     46/** Destructor */
     47void psDlistFree(psDlist *list,  ///< list to destroy
     48                 void (*elemFree)(void *)) ///< destructor for data on list
     49;
     50
     51/**** List maintainence functions ****/
     52
     53/** Add to list */
     54psDlist *psDlistAdd(psDlist *list, ///< list to add to (may be NULL)
     55                    void *data,  ///< data item to add
     56                    int where)  ///< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
     57;
     58
     59/** Append to a list */
     60psDlist *psDlistAppend(psDlist *list, ///< list to append to (may be NULL)
     61                       void *data) ///< data item to add
     62;
     63
     64/** Remove from a list */
     65void *psDlistRemove(psDlist *list, ///< list to remove element from
     66                    void *data,  ///< data item to remove
     67                    int which)  ///< index of item, or PS_DLIST_UNKNOWN, PS_DLIST_NEXT, PS_DLIST_PREV
     68;
     69
     70/** Retrieve from a list */
     71void *psDlistGet(const psDlist *list, ///< list to retrieve element from
     72                 int which)  ///< index of item, or PS_DLIST_NEXT, PS_DLIST_PREV, PS_DLIST_UNKNOWN
     73;
     74
     75/** Set the iterator */
     76void psDlistSetIterator(psDlist *list, ///< list to retrieve element from
     77                        int where) ///< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
     78;
     79
     80/** Get next element relative to iter */
     81void *psDlistGetNext(psDlist *list) ///< list to retrieve element from
     82;
     83
     84/** Get prev element relative to iter */
     85void *psDlistGetPrev(psDlist *list) ///< list to retrieve element from
     86;
     87
     88/** Convert doubly-linked list to an array */
     89psVoidPtrArray *psDlistToArray(psDlist *dlist) ///< List to convert
     90;
     91
     92/** Convert array to a doubly-linked list */
     93psDlist *psArrayToDlist(psVoidPtrArray *arr) ///< Array to convert
     94;
     95
     96/* \} */ // End of DataGroup Functions
     97
     98#endif
Note: See TracChangeset for help on using the changeset viewer.