Changeset 454
- Timestamp:
- Apr 19, 2004, 11:01:12 AM (22 years ago)
- 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 9 static psDlistElem *dlistElemAlloc(void) 10 { 11 return(psAlloc(sizeof(psDlistElem))); 12 } 13 14 static void dlistElemFree(psDlistElem *elem) 15 { 16 psFree(elem); 17 } 18 19 /*****************************************************************************/ 20 21 psDlist *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 36 void 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 */ 66 psDlist *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 128 psDlist *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 */ 138 void *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 241 void *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 */ 291 void 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 */ 307 void *psDlistGetNext(psDlist *list, // the list in question 308 int which) // @notused@ the desired iterator 309 { 310 return psDlistGet(list, PS_DLIST_NEXT); 311 } 312 313 void *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 */ 323 psVoidPtrArray *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 344 psDlist *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 */ 10 typedef 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 } 16 psDlistElem; 17 18 /** Doubly-linked list */ 19 typedef 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 } 26 psDlist; 27 28 /** Special values of index into list */ 29 enum { 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 */ 43 psDlist *psDlistAlloc(void *data) ///< initial data item; may be NULL 44 ; 45 46 /** Destructor */ 47 void 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 */ 54 psDlist *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 */ 60 psDlist *psDlistAppend(psDlist *list, ///< list to append to (may be NULL) 61 void *data) ///< data item to add 62 ; 63 64 /** Remove from a list */ 65 void *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 */ 71 void *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 */ 76 void 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 */ 81 void *psDlistGetNext(psDlist *list) ///< list to retrieve element from 82 ; 83 84 /** Get prev element relative to iter */ 85 void *psDlistGetPrev(psDlist *list) ///< list to retrieve element from 86 ; 87 88 /** Convert doubly-linked list to an array */ 89 psVoidPtrArray *psDlistToArray(psDlist *dlist) ///< List to convert 90 ; 91 92 /** Convert array to a doubly-linked list */ 93 psDlist *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.
