|
|
1.1 root 1: /* link_list.c */
2:
3: /* Double-Linked-list library */
4:
1.1.1.2 ! root 5: /* $Id: link_list.c,v 1.53 2011/09/10 01:27:01 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This library is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU Lesser General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU Lesser General Public License for more details: lgpl.txt or *
18: * http://www.fsf.org/copyleft/lesser.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include <stdlib.h> /* malloc */
39: #include <string.h> /* memset */
40: #include "link_list.h"
41: #include "genwrap.h"
42:
1.1.1.2 ! root 43: #if defined(_WIN32) && defined(LINK_LIST_USE_HEAPALLOC)
! 44: #define malloc(size) HeapAlloc(GetProcessHeap(), /* flags: */0, size)
! 45: #define free(ptr) HeapFree(GetProcessHeap(), /* flags: */0, ptr)
1.1 root 46: #endif
47:
48: link_list_t* DLLCALL listInit(link_list_t* list, long flags)
49: {
1.1.1.2 ! root 50: if((flags&LINK_LIST_MALLOC) || list==NULL) {
1.1 root 51: if((list=(link_list_t*)malloc(sizeof(link_list_t)))==NULL)
52: return(NULL);
53: flags |= LINK_LIST_MALLOC;
54: }
55:
56: memset(list,0,sizeof(link_list_t));
57:
58: list->flags = flags;
59:
60: #if defined(LINK_LIST_THREADSAFE)
1.1.1.2 ! root 61: if(list->flags&LINK_LIST_MUTEX) {
! 62: list->mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
! 63: memset(&list->tid, 0xff, sizeof(list->tid));
! 64: }
! 65:
1.1 root 66: if(list->flags&LINK_LIST_SEMAPHORE)
67: sem_init(&list->sem,0,0);
68: #endif
69:
70: if(flags&LINK_LIST_ATTACH)
71: listAttach(list);
72:
73: return(list);
74: }
75:
76: BOOL DLLCALL listFreeNodeData(list_node_t* node)
77: {
1.1.1.2 ! root 78: if(node!=NULL && node->data!=NULL && !(node->flags&LINK_LIST_LOCKED)) {
1.1 root 79: free(node->data);
80: node->data = NULL;
81: return(TRUE);
82: }
83: return(FALSE);
84: }
85:
86: long DLLCALL listFreeNodes(link_list_t* list)
87: {
88: list_node_t* node;
89: list_node_t* next;
90:
1.1.1.2 ! root 91: if(list==NULL)
! 92: return(-1);
! 93:
! 94: listLock(list);
! 95:
1.1 root 96: for(node=list->first; node!=NULL; node=next) {
97:
1.1.1.2 ! root 98: if(node->flags&LINK_LIST_LOCKED)
1.1 root 99: break;
100:
1.1.1.2 ! root 101: if(((list->flags&LINK_LIST_ALWAYS_FREE) || (node->flags&LINK_LIST_MALLOC))
1.1 root 102: && !(list->flags&LINK_LIST_NEVER_FREE))
103: listFreeNodeData(node);
104:
105: next = node->next;
106:
107: free(node);
108:
109: if(list->count)
110: list->count--;
111: }
112:
113: list->first = node;
114: if(!list->count)
115: list->last = NULL;
116:
1.1.1.2 ! root 117: listUnlock(list);
! 118:
1.1 root 119: return(list->count);
120: }
121:
122: BOOL DLLCALL listFree(link_list_t* list)
123: {
124: if(list==NULL)
125: return(FALSE);
126:
127: if(listFreeNodes(list))
128: return(FALSE);
129:
130: #if defined(LINK_LIST_THREADSAFE)
1.1.1.2 ! root 131:
! 132: if(list->flags&LINK_LIST_MUTEX) {
! 133: while(pthread_mutex_destroy((pthread_mutex_t*)&list->mutex)==EBUSY)
! 134: SLEEP(1);
! 135: }
! 136:
1.1 root 137: if(list->flags&LINK_LIST_SEMAPHORE) {
138: while(sem_destroy(&list->sem)==-1 && errno==EBUSY)
139: SLEEP(1);
1.1.1.2 ! root 140: //list->sem=(sem_t)NULL; /* Removed 08-20-08 - list->sem is never checked and this causes an error with gcc 4.1.2 (ThetaSigma) */
1.1 root 141: }
142: #endif
143:
144: if(list->flags&LINK_LIST_MALLOC)
145: free(list);
146:
147: return(TRUE);
148: }
149:
150: long DLLCALL listAttach(link_list_t* list)
151: {
152: if(list==NULL)
153: return(-1);
154:
1.1.1.2 ! root 155: listLock(list);
1.1 root 156: list->refs++;
1.1.1.2 ! root 157: listUnlock(list);
1.1 root 158:
159: return(list->refs);
160: }
161:
162: long DLLCALL listDettach(link_list_t* list)
163: {
164: int refs;
165:
166: if(list==NULL || list->refs<1)
167: return(-1);
168:
1.1.1.2 ! root 169: listLock(list);
1.1 root 170: if((refs=--list->refs)==0)
171: listFree(list);
172: else
1.1.1.2 ! root 173: listUnlock(list);
1.1 root 174:
175: return(refs);
176: }
177:
178: void* DLLCALL listSetPrivateData(link_list_t* list, void* p)
179: {
180: void* old;
181:
182: if(list==NULL)
183: return(NULL);
184:
1.1.1.2 ! root 185: listLock(list);
1.1 root 186: old=list->private_data;
187: list->private_data=p;
1.1.1.2 ! root 188: listUnlock(list);
1.1 root 189: return(old);
190: }
191:
192: void* DLLCALL listGetPrivateData(link_list_t* list)
193: {
194: if(list==NULL)
195: return(NULL);
196: return(list->private_data);
197: }
198:
199: #if defined(LINK_LIST_THREADSAFE)
200:
201: BOOL DLLCALL listSemPost(link_list_t* list)
202: {
203: if(list==NULL || !(list->flags&LINK_LIST_SEMAPHORE))
204: return(FALSE);
205:
206: return(sem_post(&list->sem)==0);
207: }
208:
209: BOOL DLLCALL listSemWait(link_list_t* list)
210: {
211: if(list==NULL || !(list->flags&LINK_LIST_SEMAPHORE))
212: return(FALSE);
213:
214: return(sem_wait(&list->sem)==0);
215: }
216:
217: BOOL DLLCALL listSemTryWait(link_list_t* list)
218: {
219: if(list==NULL || !(list->flags&LINK_LIST_SEMAPHORE))
220: return(FALSE);
221:
222: return(sem_trywait(&list->sem)==0);
223: }
224:
225: BOOL DLLCALL listSemTryWaitBlock(link_list_t* list, unsigned long timeout)
226: {
227: if(list==NULL || !(list->flags&LINK_LIST_SEMAPHORE))
228: return(FALSE);
229:
230: return(sem_trywait_block(&list->sem,timeout)==0);
231: }
232:
233: #endif
234:
1.1.1.2 ! root 235: BOOL DLLCALL listLock(link_list_t* list)
! 236: {
! 237: BOOL ret=TRUE;
! 238:
! 239: if(list==NULL)
! 240: return(FALSE);
! 241: #if defined(LINK_LIST_THREADSAFE)
! 242: if((list->flags&LINK_LIST_MUTEX) && (ret=pthread_mutex_lock(&list->mutex))==0)
1.1 root 243: #endif
1.1.1.2 ! root 244: list->locks++;
! 245: return(ret);
! 246: }
! 247:
! 248: BOOL DLLCALL listIsLocked(const link_list_t* list)
1.1 root 249: {
1.1.1.2 ! root 250: if(list==NULL)
! 251: return(FALSE);
! 252: return(list->locks > 0 ? TRUE : FALSE);
1.1 root 253: }
254:
1.1.1.2 ! root 255: BOOL DLLCALL listUnlock(link_list_t* list)
1.1 root 256: {
1.1.1.2 ! root 257: BOOL ret=TRUE;
! 258:
! 259: if(list==NULL)
! 260: return(FALSE);
! 261: #if defined(LINK_LIST_THREADSAFE)
! 262: if((list->flags&LINK_LIST_MUTEX) && (ret=pthread_mutex_unlock(&list->mutex))==0)
! 263: #endif
! 264: list->locks--;
! 265: return(ret);
1.1 root 266: }
267:
1.1.1.2 ! root 268: long DLLCALL listCountNodes(link_list_t* list)
1.1 root 269: {
270: long count=0;
271: list_node_t* node;
272:
273: if(list==NULL)
274: return(-1);
275:
276: if(list->count)
277: return(list->count);
278:
1.1.1.2 ! root 279: listLock(list);
1.1 root 280:
281: for(node=list->first; node!=NULL; node=node->next)
282: count++;
283:
1.1.1.2 ! root 284: listUnlock(list);
1.1 root 285:
286: return(count);
287: }
288:
1.1.1.2 ! root 289: list_node_t* DLLCALL listFindNode(link_list_t* list, const void* data, size_t length)
1.1 root 290: {
291: list_node_t* node;
292:
293: if(list==NULL)
294: return(NULL);
295:
1.1.1.2 ! root 296: listLock(list);
1.1 root 297:
298: for(node=list->first; node!=NULL; node=node->next) {
299: if(length==0) {
300: if(node->data==data)
301: break;
1.1.1.2 ! root 302: } else if(data==NULL) {
! 303: if(node->tag==(list_node_tag_t)length)
! 304: break;
1.1 root 305: } else if(node->data!=NULL && memcmp(node->data,data,length)==0)
306: break;
307: }
308:
1.1.1.2 ! root 309: listUnlock(list);
1.1 root 310:
311: return(node);
312: }
313:
1.1.1.2 ! root 314: str_list_t DLLCALL listStringList(link_list_t* list)
1.1 root 315: {
316: list_node_t* node;
317: str_list_t str_list;
318: size_t count=0;
319:
320: if(list==NULL)
321: return(NULL);
322:
323: if((str_list=strListInit())==NULL)
324: return(NULL);
325:
1.1.1.2 ! root 326: listLock(list);
1.1 root 327:
328: for(node=list->first; node!=NULL; node=node->next) {
329: if(node->data!=NULL)
330: strListAppend(&str_list, (char*)node->data, count++);
331: }
332:
1.1.1.2 ! root 333: listUnlock(list);
1.1 root 334:
335: return(str_list);
336: }
337:
338: str_list_t DLLCALL listSubStringList(const list_node_t* node, long max)
339: {
340: long count;
341: str_list_t str_list;
1.1.1.2 ! root 342: link_list_t* list;
1.1 root 343:
344: if(node==NULL)
345: return(NULL);
346:
347: if((str_list=strListInit())==NULL)
348: return(NULL);
349:
1.1.1.2 ! root 350: list=node->list;
! 351: listLock(list);
1.1 root 352:
353: for(count=0; count<max && node!=NULL; node=node->next) {
354: if(node->data!=NULL)
355: strListAppend(&str_list, (char*)node->data, count++);
356: }
357:
1.1.1.2 ! root 358: listUnlock(list);
1.1 root 359:
360: return(str_list);
361: }
362:
363: void* DLLCALL listFreeStringList(str_list_t list)
364: {
365: strListFree(&list);
366: return(list);
367: }
368:
1.1.1.2 ! root 369: list_node_t* DLLCALL listFirstNode(link_list_t* list)
1.1 root 370: {
1.1.1.2 ! root 371: list_node_t* node;
! 372:
1.1 root 373: if(list==NULL)
374: return(NULL);
375:
1.1.1.2 ! root 376: listLock(list);
! 377: node=list->first;
! 378: listUnlock(list);
! 379:
! 380: return(node);
1.1 root 381: }
382:
1.1.1.2 ! root 383: list_node_t* DLLCALL listLastNode(link_list_t* list)
1.1 root 384: {
385: list_node_t* node;
386: list_node_t* last=NULL;
387:
388: if(list==NULL)
389: return(NULL);
390:
1.1.1.2 ! root 391: listLock(list);
1.1 root 392: if(list->last!=NULL)
1.1.1.2 ! root 393: last=list->last;
! 394: else
! 395: for(node=list->first; node!=NULL; node=node->next)
! 396: last=node;
! 397: listUnlock(list);
1.1 root 398:
399: return(last);
400: }
401:
1.1.1.2 ! root 402: long DLLCALL listNodeIndex(link_list_t* list, list_node_t* find_node)
1.1 root 403: {
404: long i=0;
405: list_node_t* node;
406:
407: if(list==NULL)
408: return(-1);
409:
1.1.1.2 ! root 410: listLock(list);
1.1 root 411:
412: for(node=list->first; node!=NULL; node=node->next)
413: if(node==find_node)
414: break;
415:
1.1.1.2 ! root 416: listUnlock(list);
1.1 root 417:
418: if(node==NULL)
419: return(-1);
420:
421: return(i);
422: }
423:
1.1.1.2 ! root 424: list_node_t* DLLCALL listNodeAt(link_list_t* list, long index)
1.1 root 425: {
426: long i=0;
427: list_node_t* node;
428:
429: if(list==NULL || index<0)
430: return(NULL);
431:
1.1.1.2 ! root 432: listLock(list);
1.1 root 433:
434: for(node=list->first; node!=NULL && i<index; node=node->next)
435: i++;
436:
1.1.1.2 ! root 437: listUnlock(list);
1.1 root 438:
439: return(node);
440: }
441:
442: list_node_t* DLLCALL listNextNode(const list_node_t* node)
443: {
1.1.1.2 ! root 444: list_node_t* next;
! 445:
1.1 root 446: if(node==NULL)
447: return(NULL);
448:
1.1.1.2 ! root 449: listLock(node->list);
! 450: next=node->next;
! 451: listUnlock(node->list);
! 452:
! 453: return(next);
1.1 root 454: }
455:
456: list_node_t* DLLCALL listPrevNode(const list_node_t* node)
457: {
1.1.1.2 ! root 458: list_node_t* prev;
! 459:
1.1 root 460: if(node==NULL)
461: return(NULL);
462:
1.1.1.2 ! root 463: listLock(node->list);
! 464: prev=node->prev;
! 465: listUnlock(node->list);
! 466:
! 467: return(prev);
1.1 root 468: }
469:
470: void* DLLCALL listNodeData(const list_node_t* node)
471: {
1.1.1.2 ! root 472: void* data;
! 473:
1.1 root 474: if(node==NULL)
475: return(NULL);
476:
1.1.1.2 ! root 477: listLock(node->list);
! 478: data=node->data;
! 479: listUnlock(node->list);
! 480:
! 481: return(data);
1.1 root 482: }
483:
484: BOOL DLLCALL listNodeIsLocked(const list_node_t* node)
485: {
1.1.1.2 ! root 486: return(node!=NULL && (node->flags&LINK_LIST_LOCKED));
1.1 root 487: }
488:
489: BOOL DLLCALL listLockNode(list_node_t* node)
490: {
1.1.1.2 ! root 491: if(node==NULL || (node->flags&LINK_LIST_LOCKED))
1.1 root 492: return(FALSE);
493:
1.1.1.2 ! root 494: listLock(node->list);
! 495: node->flags|=LINK_LIST_LOCKED;
! 496: listUnlock(node->list);
1.1 root 497:
498: return(TRUE);
499: }
500:
501: BOOL DLLCALL listUnlockNode(list_node_t* node)
502: {
503: if(!listNodeIsLocked(node))
504: return(FALSE);
505:
1.1.1.2 ! root 506: listLock(node->list);
! 507: node->flags&=~LINK_LIST_LOCKED;
! 508: listUnlock(node->list);
1.1 root 509:
510: return(TRUE);
511: }
512:
513: static list_node_t* DLLCALL list_add_node(link_list_t* list, list_node_t* node, list_node_t* after)
514: {
515: if(list==NULL)
516: return(NULL);
517:
1.1.1.2 ! root 518: listLock(list);
1.1 root 519:
520: node->list = list;
521: if(after==LAST_NODE) /* e.g. listPushNode() */
522: after=list->last;
523: node->prev = after;
524:
525: if(after==list->last) /* append to list */
526: list->last = node;
527: if(after==FIRST_NODE) { /* insert at beginning of list */
528: node->next = list->first;
529: if(node->next!=NULL)
530: node->next->prev = node;
531: list->first = node;
532: } else {
533: if(after->next!=NULL) {
534: after->next->prev = node;
535: node->next = after->next;
536: }
537: after->next = node;
538: }
539:
540: list->count++;
541:
1.1.1.2 ! root 542: listUnlock(list);
1.1 root 543:
544: #if defined(LINK_LIST_THREADSAFE)
545: if(list->flags&LINK_LIST_SEMAPHORE)
546: listSemPost(list);
547: #endif
548:
549: return(node);
550: }
551:
1.1.1.2 ! root 552: list_node_t* DLLCALL listAddNode(link_list_t* list, void* data, list_node_tag_t tag, list_node_t* after)
1.1 root 553: {
554: list_node_t* node;
555:
1.1.1.2 ! root 556: if(list==NULL)
1.1 root 557: return(NULL);
558:
559: if((node=(list_node_t*)malloc(sizeof(list_node_t)))==NULL)
560: return(NULL);
561:
562: memset(node,0,sizeof(list_node_t));
563: node->data = data;
1.1.1.2 ! root 564: node->tag = tag;
1.1 root 565:
566: return(list_add_node(list,node,after));
567: }
568:
1.1.1.2 ! root 569: long DLLCALL listAddNodes(link_list_t* list, void** data, list_node_tag_t* tag, list_node_t* after)
1.1 root 570: {
571: long i;
572: list_node_t* node=NULL;
573:
574: if(data==NULL)
575: return(-1);
576:
577: for(i=0; data[i]!=NULL ;i++)
1.1.1.2 ! root 578: if((node=listAddNode(list,data[i],tag==NULL ? LIST_NODE_TAG_DEFAULT : *(tag++),node==NULL ? after:node))==NULL)
1.1 root 579: return(i);
580:
581: return(i);
582: }
583:
1.1.1.2 ! root 584: list_node_t* DLLCALL listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_tag_t tag, list_node_t* after)
1.1 root 585: {
586: list_node_t* node;
587: void* buf;
588:
589: if((buf=malloc(length))==NULL)
590: return(NULL);
591: memcpy(buf,data,length);
592:
1.1.1.2 ! root 593: if((node=listAddNode(list,buf,tag,after))==NULL) {
1.1 root 594: free(buf);
595: return(NULL);
596: }
597: node->flags |= LINK_LIST_MALLOC;
598:
599: return(node);
600: }
601:
1.1.1.2 ! root 602: list_node_t* DLLCALL listAddNodeString(link_list_t* list, const char* str, list_node_tag_t tag, list_node_t* after)
1.1 root 603: {
604: list_node_t* node;
605: char* buf;
606:
607: if(str==NULL)
608: return(NULL);
609:
610: if((buf=strdup(str))==NULL)
611: return(NULL);
612:
1.1.1.2 ! root 613: if((node=listAddNode(list,buf,tag,after))==NULL) {
1.1 root 614: free(buf);
615: return(NULL);
616: }
617: node->flags |= LINK_LIST_MALLOC;
618:
619: return(node);
620: }
621:
1.1.1.2 ! root 622: long DLLCALL listAddStringList(link_list_t* list, str_list_t str_list, list_node_tag_t* tag, list_node_t* after)
1.1 root 623: {
624: long i;
625: list_node_t* node=NULL;
626:
627: if(str_list==NULL)
628: return(-1);
629:
630: for(i=0; str_list[i]!=NULL ;i++)
1.1.1.2 ! root 631: if((node=listAddNodeString(list,str_list[i],tag==NULL ? LIST_NODE_TAG_DEFAULT : *(tag++),node==NULL ? after:node))==NULL)
1.1 root 632: return(i);
633:
634: return(i);
635: }
636:
637: long DLLCALL listAddNodeList(link_list_t* list, const link_list_t* src, list_node_t* after)
638: {
639: long count=0;
640: list_node_t* node=NULL;
641: list_node_t* src_node;
642:
643: if(src==NULL)
644: return(-1);
645:
646: for(src_node=src->first; src_node!=NULL; src_node=src_node->next, count++) {
1.1.1.2 ! root 647: if((node=listAddNode(list, src_node->data, src_node->tag, node==NULL ? after:node))==NULL)
1.1 root 648: return(count);
649: node->flags = src_node->flags;
650: }
651:
652: return(count);
653: }
654:
655: long DLLCALL listMerge(link_list_t* list, const link_list_t* src, list_node_t* after)
656: {
657: long count=0;
658: list_node_t* node=NULL;
659: list_node_t* src_node;
660:
661: if(src==NULL)
662: return(-1);
663:
664: for(src_node=src->first; src_node!=NULL; src_node=src_node->next, count++)
665: if((node=list_add_node(list, src_node, node==NULL ? after:node))==NULL)
666: return(count);
667:
668: return(count);
669: }
670:
671: link_list_t* DLLCALL listExtract(link_list_t* dest_list, const list_node_t* node, long max)
672: {
673: long count;
674: link_list_t* list;
675:
676: if(node==NULL || node->list==NULL)
677: return(NULL);
678:
679: if((list=listInit(dest_list, node->list->flags))==NULL)
680: return(NULL);
681:
682: for(count=0; count<max && node!=NULL; node=node->next) {
1.1.1.2 ! root 683: listAddNode(list, node->data, node->tag, list->last);
1.1 root 684: count++;
685: }
686:
687: return(list);
688: }
689:
690: static void* list_remove_node(link_list_t* list, list_node_t* node, BOOL free_data)
691: {
692: void* data;
693:
694: if(node==FIRST_NODE)
695: node=list->first;
696: else if(node==LAST_NODE)
697: node=list->last;
698: if(node==NULL)
699: return(NULL);
700:
1.1.1.2 ! root 701: if(node->flags&LINK_LIST_LOCKED)
1.1 root 702: return(NULL);
703:
704: if(node->prev!=NULL)
705: node->prev->next = node->next;
706: if(node->next!=NULL)
707: node->next->prev = node->prev;
708: if(list->first==node)
709: list->first = node->next;
710: if(list->last==node)
711: list->last = node->prev;
712:
713: if(free_data)
714: listFreeNodeData(node);
715:
716: data = node->data;
717:
718: free(node);
719:
720: if(list->count)
721: list->count--;
722:
723: return(data);
724: }
725:
726: void* DLLCALL listRemoveNode(link_list_t* list, list_node_t* node, BOOL free_data)
727: {
728: void* data;
729:
730: if(list==NULL)
731: return(NULL);
732:
1.1.1.2 ! root 733: listLock(list);
1.1 root 734:
735: data = list_remove_node(list, node, free_data);
736:
1.1.1.2 ! root 737: listUnlock(list);
! 738:
! 739: return(data);
! 740: }
! 741:
! 742: void* DLLCALL listRemoveTaggedNode(link_list_t* list, list_node_tag_t tag, BOOL free_data)
! 743: {
! 744: void* data=NULL;
! 745: list_node_t* node;
! 746:
! 747: if(list==NULL)
! 748: return(NULL);
! 749:
! 750: listLock(list);
! 751:
! 752: if((node=listFindTaggedNode(list, tag)) != NULL)
! 753: data = list_remove_node(list, node, free_data);
! 754:
! 755: listUnlock(list);
1.1 root 756:
757: return(data);
758: }
759:
760: long DLLCALL listRemoveNodes(link_list_t* list, list_node_t* node, long max, BOOL free_data)
761: {
762: long count;
763:
764: if(list==NULL)
765: return(-1);
766:
1.1.1.2 ! root 767: listLock(list);
1.1 root 768:
769: if(node==FIRST_NODE)
770: node=list->first;
771:
772: for(count=0; node!=NULL && count<max; node=node->next, count++)
773: if(listRemoveNode(list, node, free_data)==NULL)
774: break;
775:
1.1.1.2 ! root 776: listUnlock(list);
1.1 root 777:
778: return(count);
779: }
780:
781: BOOL DLLCALL listSwapNodes(list_node_t* node1, list_node_t* node2)
782: {
783: list_node_t tmp;
784:
785: if(node1==NULL || node2==NULL || node1==node2)
786: return(FALSE);
787:
788: if(listNodeIsLocked(node1) || listNodeIsLocked(node2))
789: return(FALSE);
790:
791: if(node1->list==NULL || node2->list==NULL)
792: return(FALSE);
793:
794: #if defined(LINK_LIST_THREADSAFE)
1.1.1.2 ! root 795: listLock(node1->list);
1.1 root 796: if(node1->list != node2->list)
1.1.1.2 ! root 797: listLock(node2->list);
1.1 root 798: #endif
799:
800: tmp=*node1;
1.1.1.2 ! root 801: node1->tag=node2->tag;
1.1 root 802: node1->data=node2->data;
803: node1->flags=node2->flags;
1.1.1.2 ! root 804: node2->tag=tmp.tag;
1.1 root 805: node2->data=tmp.data;
806: node2->flags=tmp.flags;
807:
808: #if defined(LINK_LIST_THREADSAFE)
1.1.1.2 ! root 809: listUnlock(node1->list);
1.1 root 810: if(node1->list != node2->list)
1.1.1.2 ! root 811: listUnlock(node2->list);
1.1 root 812: #endif
813:
814: return(TRUE);
815: }
816:
817: #if 0
818:
819: #include <stdio.h> /* printf, sprintf */
820:
821: int main(int arg, char** argv)
822: {
823: int i;
824: char* p;
825: char str[32];
826: link_list_t list;
827:
828: listInit(&list,0);
829: for(i=0; i<100; i++) {
830: sprintf(str,"%u",i);
831: listPushNodeString(&list,str);
832: }
833:
834: while((p=listShiftNode(&list))!=NULL)
835: printf("%d %s\n",listCountNodes(&list),p), free(p);
836:
837: /* Yes, this test code leaks heap memory. :-) */
838: gets(str);
839: return 0;
840: }
841:
842: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.