Annotation of sbbs/src/xpdev/link_list.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.