|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.