Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

link_list.h 8.82 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* link_list.h */

/* Double-Linked-list library */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *																			*
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#ifndef _LINK_LIST_H
#define _LINK_LIST_H

#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 47
	#include "threadwrap.h"	/* mutexes */
	#include "semwrap.h"	/* semaphores */
48 49
#endif

50 51 52 53
#if defined(__cplusplus)
extern "C" {
#endif

54 55
#define FIRST_NODE				NULL	/* Special value to specify first node in list */

56
/* Valid link_list_t.flags bits */
57
#define LINK_LIST_MALLOC		(1<<0)	/* List/node allocated with malloc() */
58 59 60 61 62 63
#define LINK_LIST_ALWAYS_FREE	(1<<1)	/* ALWAYS free node data in listFreeNodes() */
#define LINK_LIST_NEVER_FREE	(1<<2)	/* NEVER free node data (careful of memory leaks!) */
#define LINK_LIST_MUTEX			(1<<3)	/* Mutex-protected linked-list */
#define LINK_LIST_SEMAPHORE		(1<<4)	/* Semaphore attached to linked-list */
#define LINK_LIST_NODE_LOCKED	(1<<5)	/* Node is locked */
#define LINK_LIST_ATTACH		(1<<6)	/* Attach during init */
64 65

typedef struct list_node {
66 67 68
	void*				data;			/* pointer to some kind of data */
	struct list_node*	next;			/* next node in list (or NULL) */
	struct list_node*	prev;			/* previous node in list (or NULL) */
69
	struct link_list*	list;
70
	unsigned long		flags;			/* private use flags */
71 72
} list_node_t;

73
typedef struct link_list {
74 75 76 77 78
	list_node_t*		first;			/* first node in list (or NULL) */
	list_node_t*		last;			/* last node in list (or NULL) */
	unsigned long		flags;			/* private use flags */
	long				count;			/* number of nodes in list */
	void*				private_data;	/* for use by the application only */
79
	long				refs;			/* reference counter (attached clients) */
80 81
#if defined(LINK_LIST_THREADSAFE)
	pthread_mutex_t		mutex;
82
	sem_t				sem;
83
#endif
84 85 86
} link_list_t;

/* Initialization, Allocation, and Freeing of Lists and Nodes */
87
DLLEXPORT link_list_t*	DLLCALL listInit(link_list_t* /* NULL to auto-allocate */, long flags);
88 89 90
BOOL			listFree(link_list_t*);
long			listFreeNodes(link_list_t*);
BOOL			listFreeNodeData(list_node_t* node);
91

92 93 94 95
/* Increment/decrement reference counter (and auto-free when zero), returns -1 on error */
long			listAttach(link_list_t*);
long			listDetach(link_list_t*);

96
#if defined(LINK_LIST_THREADSAFE)
97 98 99 100
DLLEXPORT BOOL		DLLCALL	listSemPost(link_list_t*);
DLLEXPORT BOOL		DLLCALL	listSemWait(link_list_t*);
DLLEXPORT BOOL		DLLCALL	listSemTryWait(link_list_t*);
DLLEXPORT BOOL		DLLCALL	listSemTryWaitBlock(link_list_t*, unsigned long timeout);
101
#endif
102

103
/* Lock/unlock mutex-protected linked lists (no-op for unprotected lists) */
104 105
DLLEXPORT void		DLLCALL	listLock(const link_list_t*);
DLLEXPORT void		DLLCALL	listUnlock(const link_list_t*);
106

107
/* Return count or index of nodes, or -1 on error */
108 109
DLLEXPORT long		DLLCALL	listCountNodes(const link_list_t*);
DLLEXPORT long		DLLCALL	listNodeIndex(const link_list_t*, list_node_t*);
110

111
/* Get/Set list private data */
112 113
DLLEXPORT void*		DLLCALL	listSetPrivateData(link_list_t*, void*);
DLLEXPORT void*		DLLCALL	listGetPrivateData(link_list_t*);
114

115 116 117 118 119 120
/* Return an allocated string list (which must be freed), array of all strings in linked list */
str_list_t		listStringList(const link_list_t*);

/* Return an allocated string list (which must be freed), subset of strings in linked list */
str_list_t		listSubStringList(const list_node_t*, long max);

121 122 123
/* Free a string list returned from either of the above functions */
void*			listFreeStringList(str_list_t);

124 125
/* Extract subset (up to max number of nodes) in linked list (src_node) and place into dest_list */
/* dest_list == NULL, then allocate a return a new linked list */
126
DLLEXPORT link_list_t*	DLLCALL	listExtract(link_list_t* dest_list, const list_node_t* src_node, long max);
127

128
/* Simple search functions returning found node or NULL on error */
129 130
DLLEXPORT list_node_t*	DLLCALL	listNodeAt(const link_list_t*, long index);
DLLEXPORT list_node_t*	DLLCALL	listFindNode(const link_list_t*, const void* data, size_t length);
131

132
/* Convenience functions */
133 134 135 136 137
DLLEXPORT list_node_t*	DLLCALL	listFirstNode(const link_list_t*);
DLLEXPORT list_node_t*	DLLCALL	listLastNode(const link_list_t*);
DLLEXPORT list_node_t*	DLLCALL	listNextNode(const list_node_t*);
DLLEXPORT list_node_t*	DLLCALL	listPrevNode(const list_node_t*);
DLLEXPORT void*			DLLCALL	listNodeData(const list_node_t*);
138

139
/* Primitive node locking */
140 141 142
DLLEXPORT BOOL		DLLCALL	listLockNode(list_node_t*);
DLLEXPORT BOOL		DLLCALL	listUnlockNode(list_node_t*);
DLLEXPORT BOOL		DLLCALL	listNodeIsLocked(const list_node_t*);
143

144
/* Add node to list, returns pointer to new node or NULL on error */
145
DLLEXPORT list_node_t*	DLLCALL	listAddNode(link_list_t*, void* data, list_node_t* after /* NULL=insert */);
146

147
/* Add array of node data to list, returns number of nodes added (or negative on error) */
148
DLLEXPORT long		DLLCALL	listAddNodes(link_list_t*, void** data, list_node_t* after /* NULL=insert */);
149

150 151 152
/* Add node to list, allocating and copying the data for the node */
list_node_t*	listAddNodeData(link_list_t*, const void* data, size_t length, list_node_t* after);

153
/* Add node to list, allocating and copying ASCIIZ string data */
154
list_node_t*	listAddNodeString(link_list_t*, const char* str, list_node_t* after);
155 156

/* Add a list of strings to the linked list, allocating and copying each */
157
DLLEXPORT long		DLLCALL	listAddStringList(link_list_t*, str_list_t, list_node_t* after);
158

159
/* Add a list of nodes from a source linked list */
160
DLLEXPORT long		DLLCALL	listAddNodeList(link_list_t*, const link_list_t* src, list_node_t* after); 
161 162 163

/* Merge a source linked list into the destination linked list */
/* after merging, the nodes in the source linked list should not be modified or freed */
164
DLLEXPORT long		DLLCALL	listMerge(link_list_t* dest, const link_list_t* src, list_node_t* after);
165

166
/* Swap the data pointers and flags for 2 nodes (possibly in separate lists) */
167
DLLEXPORT BOOL		DLLCALL	listSwapNodes(list_node_t* node1, list_node_t* node2);
168

169 170
/* Convenience macros for pushing, popping, and inserting nodes */
#define	listPushNode(list, data)				listAddNode(list, data, listLastNode(list))
deuce's avatar
deuce committed
171
#define listInsertNode(list, data)				listAddNode(list, data, FIRST_NODE)
172
#define listPushNodeData(list, data, length)	listAddNodeData(list, data, length, listLastNode(list))
173
#define	listInsertNodeData(list, data, length)	listAddNodeData(list, data, length, FIRST_NODE)
174
#define	listPushNodeString(list, str)			listAddNodeString(list, str, listLastNode(list))
175
#define listInsertNodeString(list, str)			listAddNodeString(list, str, FIRST_NODE)
176
#define	listPushStringList(list, str_list)		listAddStringList(list, str_list, listLastNode(list))
177
#define listInsertStringList(list, str_list)	listAddStringList(list, str_list, FIRST_NODE)
178 179
#define listPopNode(list)						listRemoveNode(list, listLastNode(list), FALSE)
#define listShiftNode(list)						listRemoveNode(list, FIRST_NODE, FALSE)
180 181

/* Remove node from list, returning the node's data (if not free'd) */
182
DLLEXPORT void*		DLLCALL	listRemoveNode(link_list_t*, list_node_t* /* NULL=first */, BOOL free_data);
183 184

/* Remove multiple nodes from list, returning the number of nodes removed */
185
long			listRemoveNodes(link_list_t*, list_node_t* /* NULL=first */, long count, BOOL free_data);
186 187 188 189 190 191

#if defined(__cplusplus)
}
#endif

#endif	/* Don't add anything after this line */