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

1.1       root        1: /* link_list.h */
                      2: 
                      3: /* Double-Linked-list library */
                      4: 
1.1.1.2 ! root        5: /* $Id: link_list.h,v 1.25 2011/09/08 06:26:02 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: #ifndef _LINK_LIST_H
                     39: #define _LINK_LIST_H
                     40: 
                     41: #include <stddef.h>            /* size_t */
                     42: #include "wrapdll.h"
                     43: #include "str_list.h"  /* string list functions and types */
                     44: 
                     45: #if defined(LINK_LIST_THREADSAFE)
                     46:        #include "threadwrap.h" /* mutexes */
                     47:        #include "semwrap.h"    /* semaphores */
                     48: #endif
                     49: 
                     50: #if defined(__cplusplus)
                     51: extern "C" {
                     52: #endif
                     53: 
                     54: #define FIRST_NODE                             ((list_node_t*)NULL)    /* Special value to specify first node in list */
                     55: #define LAST_NODE                              ((list_node_t*)-1)              /* Special value to specify last node in list */
                     56: 
1.1.1.2 ! root       57: /* Valid link_list_t.flags and list_node_t.flags bits */
1.1       root       58: #define LINK_LIST_MALLOC               (1<<0)  /* List/node allocated with malloc() */
                     59: #define LINK_LIST_ALWAYS_FREE  (1<<1)  /* ALWAYS free node data in listFreeNodes() */
                     60: #define LINK_LIST_NEVER_FREE   (1<<2)  /* NEVER free node data (careful of memory leaks!) */
                     61: #define LINK_LIST_MUTEX                        (1<<3)  /* Mutex-protected linked-list */
                     62: #define LINK_LIST_SEMAPHORE            (1<<4)  /* Semaphore attached to linked-list */
1.1.1.2 ! root       63: #define LINK_LIST_LOCKED               (1<<5)  /* Node is locked */
1.1       root       64: #define LINK_LIST_ATTACH               (1<<6)  /* Attach during init */
                     65: 
1.1.1.2 ! root       66: /* in case the default tag type is not sufficient for your needs, you can over-ride */
        !            67: #if !defined(list_node_tag_t)                  
        !            68:        typedef long list_node_tag_t;
        !            69: #endif
        !            70: #if !defined(LIST_NODE_TAG_DEFAULT)
        !            71:        #define LIST_NODE_TAG_DEFAULT   0
        !            72: #endif
        !            73: 
1.1       root       74: typedef struct list_node {
                     75:        void*                           data;                   /* pointer to some kind of data */
                     76:        struct list_node*       next;                   /* next node in list (or NULL) */
                     77:        struct list_node*       prev;                   /* previous node in list (or NULL) */
                     78:        struct link_list*       list;
1.1.1.2 ! root       79:        unsigned long           flags;                  /* private use flags (by this library) */
        !            80:        list_node_tag_t         tag;                    /* application use value */
1.1       root       81: } list_node_t;
                     82: 
                     83: typedef struct link_list {
                     84:        list_node_t*            first;                  /* first node in list (or NULL) */
                     85:        list_node_t*            last;                   /* last node in list (or NULL) */
1.1.1.2 ! root       86:        unsigned long           flags;                  /* private use flags (by this library) */
1.1       root       87:        long                            count;                  /* number of nodes in list */
1.1.1.2 ! root       88:        void*                           private_data;   /* for use by the application/caller */
1.1       root       89:        long                            refs;                   /* reference counter (attached clients) */
1.1.1.2 ! root       90:        long                            locks;                  /* recursive lock counter */
1.1       root       91: #if defined(LINK_LIST_THREADSAFE)
1.1.1.2 ! root       92:        pthread_mutex_t         mmutex;
1.1       root       93:        pthread_mutex_t         mutex;
1.1.1.2 ! root       94:        pthread_t                       tid;
1.1       root       95:        sem_t                           sem;
                     96: #endif
                     97: } link_list_t;
                     98: 
                     99: /* Initialization, Allocation, and Freeing of Lists and Nodes */
                    100: DLLEXPORT link_list_t* DLLCALL listInit(link_list_t* /* NULL to auto-allocate */, long flags);
                    101: DLLEXPORT BOOL                 DLLCALL listFree(link_list_t*);
                    102: DLLEXPORT long                 DLLCALL listFreeNodes(link_list_t*);
                    103: DLLEXPORT BOOL                 DLLCALL listFreeNodeData(list_node_t* node);
                    104: 
                    105: /* Increment/decrement reference counter (and auto-free when zero), returns -1 on error */
                    106: DLLEXPORT long DLLCALL listAttach(link_list_t*);
                    107: DLLEXPORT long DLLCALL listDetach(link_list_t*);
                    108: 
                    109: #if defined(LINK_LIST_THREADSAFE)
                    110: DLLEXPORT BOOL DLLCALL listSemPost(link_list_t*);
                    111: DLLEXPORT BOOL DLLCALL listSemWait(link_list_t*);
                    112: DLLEXPORT BOOL DLLCALL listSemTryWait(link_list_t*);
                    113: DLLEXPORT BOOL DLLCALL listSemTryWaitBlock(link_list_t*, unsigned long timeout);
                    114: #endif
                    115: 
1.1.1.2 ! root      116: /* Lock/unlock linked lists (works best for mutex-protected lists) */
        !           117: /* Locks are recusive (e.g. must call Unlock for each call to Lock */
        !           118: DLLEXPORT BOOL DLLCALL listLock(link_list_t*);
        !           119: DLLEXPORT BOOL DLLCALL listUnlock(link_list_t*);
        !           120: DLLEXPORT BOOL DLLCALL listIsLocked(const link_list_t*);
        !           121: #define        listForceUnlock(list)   while(listUnlock(list)==TRUE)
1.1       root      122: 
                    123: /* Return count or index of nodes, or -1 on error */
1.1.1.2 ! root      124: DLLEXPORT long DLLCALL listCountNodes(link_list_t*);
        !           125: DLLEXPORT long DLLCALL listNodeIndex(link_list_t*, list_node_t*);
1.1       root      126: 
                    127: /* Get/Set list private data */
                    128: DLLEXPORT void*        DLLCALL listSetPrivateData(link_list_t*, void*);
                    129: DLLEXPORT void*        DLLCALL listGetPrivateData(link_list_t*);
                    130: 
                    131: /* Return an allocated string list (which must be freed), array of all strings in linked list */
1.1.1.2 ! root      132: DLLEXPORT str_list_t DLLCALL listStringList(link_list_t*);
1.1       root      133: 
                    134: /* Return an allocated string list (which must be freed), subset of strings in linked list */
                    135: DLLEXPORT str_list_t DLLCALL listSubStringList(const list_node_t*, long max);
                    136: 
                    137: /* Free a string list returned from either of the above functions */
                    138: DLLEXPORT void*        DLLCALL listFreeStringList(str_list_t);
                    139: 
                    140: /* Extract subset (up to max number of nodes) in linked list (src_node) and place into dest_list */
                    141: /* dest_list == NULL, then allocate a return a new linked list */
                    142: DLLEXPORT link_list_t* DLLCALL listExtract(link_list_t* dest_list, const list_node_t* src_node, long max);
                    143: 
                    144: /* Simple search functions returning found node or NULL on error */
1.1.1.2 ! root      145: DLLEXPORT list_node_t* DLLCALL listNodeAt(link_list_t*, long index);
        !           146: /* Find a specific node by data */
        !           147: /* Pass length of 0 to search by data pointer rather than by data content comparison (memcmp) */
        !           148: DLLEXPORT list_node_t* DLLCALL listFindNode(link_list_t*, const void* data, size_t length);
        !           149: /* Find a specific node by its tag value */
        !           150: #define listFindTaggedNode(list, tag)  listFindNode(list, NULL, tag)
1.1       root      151: 
                    152: /* Convenience functions */
1.1.1.2 ! root      153: DLLEXPORT list_node_t* DLLCALL listFirstNode(link_list_t*);
        !           154: DLLEXPORT list_node_t* DLLCALL listLastNode(link_list_t*);
1.1       root      155: DLLEXPORT list_node_t* DLLCALL listNextNode(const list_node_t*);
                    156: DLLEXPORT list_node_t* DLLCALL listPrevNode(const list_node_t*);
                    157: DLLEXPORT void*                        DLLCALL listNodeData(const list_node_t*);
                    158: 
1.1.1.2 ! root      159: /* Primitive node locking (not recursive) */
1.1       root      160: DLLEXPORT BOOL DLLCALL listLockNode(list_node_t*);
                    161: DLLEXPORT BOOL DLLCALL listUnlockNode(list_node_t*);
                    162: DLLEXPORT BOOL DLLCALL listNodeIsLocked(const list_node_t*);
                    163: 
                    164: /* Add node to list, returns pointer to new node or NULL on error */
1.1.1.2 ! root      165: DLLEXPORT list_node_t* DLLCALL listAddNode(link_list_t*, void* data, list_node_tag_t, list_node_t* after /* NULL=insert */);
1.1       root      166: 
                    167: /* Add array of node data to list, returns number of nodes added (or negative on error) */
1.1.1.2 ! root      168: /* tag array may be NULL */
        !           169: DLLEXPORT long         DLLCALL listAddNodes(link_list_t*, void** data, list_node_tag_t*, list_node_t* after /* NULL=insert */);
1.1       root      170: 
                    171: /* Add node to list, allocating and copying the data for the node */
1.1.1.2 ! root      172: DLLEXPORT list_node_t* DLLCALL listAddNodeData(link_list_t*, const void* data, size_t length, list_node_tag_t, list_node_t* after);
1.1       root      173: 
                    174: /* Add node to list, allocating and copying ASCIIZ string data */
1.1.1.2 ! root      175: DLLEXPORT list_node_t* DLLCALL listAddNodeString(link_list_t*, const char* str, list_node_tag_t, list_node_t* after);
1.1       root      176: 
                    177: /* Add a list of strings to the linked list, allocating and copying each */
1.1.1.2 ! root      178: /* tag array may be NULL */
        !           179: DLLEXPORT long         DLLCALL listAddStringList(link_list_t*, str_list_t, list_node_tag_t*, list_node_t* after);
1.1       root      180: 
                    181: /* Add a list of nodes from a source linked list */
                    182: DLLEXPORT long         DLLCALL listAddNodeList(link_list_t*, const link_list_t* src, list_node_t* after); 
                    183: 
                    184: /* Merge a source linked list into the destination linked list */
                    185: /* after merging, the nodes in the source linked list should not be modified or freed */
                    186: DLLEXPORT long         DLLCALL listMerge(link_list_t* dest, const link_list_t* src, list_node_t* after);
                    187: 
                    188: /* Swap the data pointers and flags for 2 nodes (possibly in separate lists) */
                    189: DLLEXPORT BOOL         DLLCALL listSwapNodes(list_node_t* node1, list_node_t* node2);
                    190: 
                    191: /* Convenience macros for pushing, popping, and inserting nodes */
1.1.1.2 ! root      192: #define        listPushNode(list, data)                                listAddNode(list, data, LIST_NODE_TAG_DEFAULT, LAST_NODE)
        !           193: #define listInsertNode(list, data)                             listAddNode(list, data, LIST_NODE_TAG_DEFAULT, FIRST_NODE)
        !           194: #define listPushNodeData(list, data, length)   listAddNodeData(list, data, length, LIST_NODE_TAG_DEFAULT, LAST_NODE)
        !           195: #define        listInsertNodeData(list, data, length)  listAddNodeData(list, data, length, LIST_NODE_TAG_DEFAULT, FIRST_NODE)
        !           196: #define        listPushNodeString(list, str)                   listAddNodeString(list, str, LIST_NODE_TAG_DEFAULT, LAST_NODE)
        !           197: #define listInsertNodeString(list, str)                        listAddNodeString(list, str, LIST_NODE_TAG_DEFAULT, FIRST_NODE)
        !           198: #define        listPushStringList(list, str_list)              listAddStringList(list, str_list, NULL, LAST_NODE)
        !           199: #define listInsertStringList(list, str_list)   listAddStringList(list, str_list, NULL, FIRST_NODE)
1.1       root      200: #define listPopNode(list)                                              listRemoveNode(list, LAST_NODE, FALSE)
                    201: #define listShiftNode(list)                                            listRemoveNode(list, FIRST_NODE, FALSE)
                    202: 
                    203: /* Remove node from list, returning the node's data (if not free'd) */
                    204: DLLEXPORT void*        DLLCALL listRemoveNode(link_list_t*, list_node_t* /* NULL=first */, BOOL free_data);
1.1.1.2 ! root      205: DLLEXPORT void* DLLCALL listRemoveTaggedNode(link_list_t*, list_node_tag_t, BOOL free_data);
1.1       root      206: 
                    207: /* Remove multiple nodes from list, returning the number of nodes removed */
                    208: DLLEXPORT long DLLCALL listRemoveNodes(link_list_t*, list_node_t* /* NULL=first */, long count, BOOL free_data);
                    209: 
                    210: #if defined(__cplusplus)
                    211: }
                    212: #endif
                    213: 
                    214: #endif /* Don't add anything after this line */

unix.superglobalmegacorp.com

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