diff --git a/src/xpdev/link_list.c b/src/xpdev/link_list.c index 06227959bea8daa498a53b7d757fa94686edb186..e6d099180f1666aee503c33db1d4ab4f809e7e7a 100644 --- a/src/xpdev/link_list.c +++ b/src/xpdev/link_list.c @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -77,7 +77,7 @@ link_list_t* DLLCALL listInit(link_list_t* list, long flags) return(list); } -BOOL listFreeNodeData(list_node_t* node) +BOOL DLLCALL listFreeNodeData(list_node_t* node) { if(node!=NULL && node->data!=NULL && !(node->flags&LINK_LIST_NODE_LOCKED)) { free(node->data); @@ -87,7 +87,7 @@ BOOL listFreeNodeData(list_node_t* node) return(FALSE); } -long listFreeNodes(link_list_t* list) +long DLLCALL listFreeNodes(link_list_t* list) { list_node_t* node; list_node_t* next; @@ -116,7 +116,7 @@ long listFreeNodes(link_list_t* list) return(list->count); } -BOOL listFree(link_list_t* list) +BOOL DLLCALL listFree(link_list_t* list) { if(list==NULL) return(FALSE); @@ -140,7 +140,7 @@ BOOL listFree(link_list_t* list) return(TRUE); } -long listAttach(link_list_t* list) +long DLLCALL listAttach(link_list_t* list) { if(list==NULL) return(-1); @@ -152,7 +152,7 @@ long listAttach(link_list_t* list) return(list->refs); } -long listDettach(link_list_t* list) +long DLLCALL listDettach(link_list_t* list) { int refs; @@ -282,7 +282,7 @@ list_node_t* DLLCALL listFindNode(const link_list_t* list, const void* data, siz return(node); } -str_list_t listStringList(const link_list_t* list) +str_list_t DLLCALL listStringList(const link_list_t* list) { list_node_t* node; str_list_t str_list; @@ -306,7 +306,7 @@ str_list_t listStringList(const link_list_t* list) return(str_list); } -str_list_t listSubStringList(const list_node_t* node, long max) +str_list_t DLLCALL listSubStringList(const list_node_t* node, long max) { long count; str_list_t str_list; @@ -329,7 +329,7 @@ str_list_t listSubStringList(const list_node_t* node, long max) return(str_list); } -void* listFreeStringList(str_list_t list) +void* DLLCALL listFreeStringList(str_list_t list) { strListFree(&list); return(list); @@ -453,7 +453,7 @@ BOOL DLLCALL listUnlockNode(list_node_t* node) return(TRUE); } -static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_node_t* after) +static list_node_t* DLLCALL list_add_node(link_list_t* list, list_node_t* node, list_node_t* after) { if(list==NULL) return(NULL); @@ -463,6 +463,9 @@ static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_nod node->list = list; node->prev = after; + if(after==LAST_NODE) /* e.g. listPushNode() */ + after=list->last; + if(after==list->last) /* append to list */ list->last = node; if(after==FIRST_NODE) { /* insert at beginning of list */ @@ -521,7 +524,7 @@ long DLLCALL listAddNodes(link_list_t* list, void** data, list_node_t* after) return(i); } -list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_t* after) +list_node_t* DLLCALL listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_t* after) { list_node_t* node; void* buf; @@ -539,7 +542,7 @@ list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length, return(node); } -list_node_t* listAddNodeString(link_list_t* list, const char* str, list_node_t* after) +list_node_t* DLLCALL listAddNodeString(link_list_t* list, const char* str, list_node_t* after) { list_node_t* node; char* buf; @@ -634,8 +637,11 @@ void* DLLCALL listRemoveNode(link_list_t* list, list_node_t* node, BOOL free_dat if(list==NULL) return(NULL); + /* Should these lines be mutex protected? */ if(node==FIRST_NODE) node=list->first; + if(node==LAST_NODE) + node=list->last; if(node==NULL) return(NULL); @@ -668,7 +674,7 @@ void* DLLCALL listRemoveNode(link_list_t* list, list_node_t* node, BOOL free_dat return(data); } -long listRemoveNodes(link_list_t* list, list_node_t* node, long max, BOOL free_data) +long DLLCALL listRemoveNodes(link_list_t* list, list_node_t* node, long max, BOOL free_data) { long count; diff --git a/src/xpdev/link_list.h b/src/xpdev/link_list.h index eb33cdfb397dd7364dc4bf2efa23a32cc69194af..74403afed0b64f06091741fa1e2b5f532bf71cce 100644 --- a/src/xpdev/link_list.h +++ b/src/xpdev/link_list.h @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -51,7 +51,8 @@ extern "C" { #endif -#define FIRST_NODE NULL /* Special value to specify first node in list */ +#define FIRST_NODE ((list_node_t*)NULL) /* Special value to specify first node in list */ +#define LAST_NODE ((list_node_t*)-1) /* Special value to specify last node in list */ /* Valid link_list_t.flags bits */ #define LINK_LIST_MALLOC (1<<0) /* List/node allocated with malloc() */ @@ -85,41 +86,41 @@ typedef struct link_list { /* Initialization, Allocation, and Freeing of Lists and Nodes */ DLLEXPORT link_list_t* DLLCALL listInit(link_list_t* /* NULL to auto-allocate */, long flags); -BOOL listFree(link_list_t*); -long listFreeNodes(link_list_t*); -BOOL listFreeNodeData(list_node_t* node); +DLLEXPORT BOOL DLLCALL listFree(link_list_t*); +DLLEXPORT long DLLCALL listFreeNodes(link_list_t*); +DLLEXPORT BOOL DLLCALL listFreeNodeData(list_node_t* node); /* Increment/decrement reference counter (and auto-free when zero), returns -1 on error */ -long listAttach(link_list_t*); -long listDetach(link_list_t*); +DLLEXPORT long DLLCALL listAttach(link_list_t*); +DLLEXPORT long DLLCALL listDetach(link_list_t*); #if defined(LINK_LIST_THREADSAFE) -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); +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); #endif /* Lock/unlock mutex-protected linked lists (no-op for unprotected lists) */ -DLLEXPORT void DLLCALL listLock(const link_list_t*); -DLLEXPORT void DLLCALL listUnlock(const link_list_t*); +DLLEXPORT void DLLCALL listLock(const link_list_t*); +DLLEXPORT void DLLCALL listUnlock(const link_list_t*); /* Return count or index of nodes, or -1 on error */ -DLLEXPORT long DLLCALL listCountNodes(const link_list_t*); -DLLEXPORT long DLLCALL listNodeIndex(const link_list_t*, list_node_t*); +DLLEXPORT long DLLCALL listCountNodes(const link_list_t*); +DLLEXPORT long DLLCALL listNodeIndex(const link_list_t*, list_node_t*); /* Get/Set list private data */ -DLLEXPORT void* DLLCALL listSetPrivateData(link_list_t*, void*); -DLLEXPORT void* DLLCALL listGetPrivateData(link_list_t*); +DLLEXPORT void* DLLCALL listSetPrivateData(link_list_t*, void*); +DLLEXPORT void* DLLCALL listGetPrivateData(link_list_t*); /* Return an allocated string list (which must be freed), array of all strings in linked list */ -str_list_t listStringList(const link_list_t*); +DLLEXPORT str_list_t DLLCALL 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); +DLLEXPORT str_list_t DLLCALL listSubStringList(const list_node_t*, long max); /* Free a string list returned from either of the above functions */ -void* listFreeStringList(str_list_t); +DLLEXPORT void* DLLCALL listFreeStringList(str_list_t); /* 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 */ @@ -137,9 +138,9 @@ DLLEXPORT list_node_t* DLLCALL listPrevNode(const list_node_t*); DLLEXPORT void* DLLCALL listNodeData(const list_node_t*); /* Primitive node locking */ -DLLEXPORT BOOL DLLCALL listLockNode(list_node_t*); -DLLEXPORT BOOL DLLCALL listUnlockNode(list_node_t*); -DLLEXPORT BOOL DLLCALL listNodeIsLocked(const list_node_t*); +DLLEXPORT BOOL DLLCALL listLockNode(list_node_t*); +DLLEXPORT BOOL DLLCALL listUnlockNode(list_node_t*); +DLLEXPORT BOOL DLLCALL listNodeIsLocked(const list_node_t*); /* Add node to list, returns pointer to new node or NULL on error */ DLLEXPORT list_node_t* DLLCALL listAddNode(link_list_t*, void* data, list_node_t* after /* NULL=insert */); @@ -148,10 +149,10 @@ DLLEXPORT list_node_t* DLLCALL listAddNode(link_list_t*, void* data, list_node_t DLLEXPORT long DLLCALL listAddNodes(link_list_t*, void** data, list_node_t* after /* NULL=insert */); /* 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); +DLLEXPORT list_node_t* DLLCALL listAddNodeData(link_list_t*, const void* data, size_t length, list_node_t* after); /* Add node to list, allocating and copying ASCIIZ string data */ -list_node_t* listAddNodeString(link_list_t*, const char* str, list_node_t* after); +DLLEXPORT list_node_t* DLLCALL listAddNodeString(link_list_t*, const char* str, list_node_t* after); /* Add a list of strings to the linked list, allocating and copying each */ DLLEXPORT long DLLCALL listAddStringList(link_list_t*, str_list_t, list_node_t* after); @@ -167,22 +168,22 @@ DLLEXPORT long DLLCALL listMerge(link_list_t* dest, const link_list_t* src, lis DLLEXPORT BOOL DLLCALL listSwapNodes(list_node_t* node1, list_node_t* node2); /* Convenience macros for pushing, popping, and inserting nodes */ -#define listPushNode(list, data) listAddNode(list, data, listLastNode(list)) +#define listPushNode(list, data) listAddNode(list, data, LAST_NODE) #define listInsertNode(list, data) listAddNode(list, data, FIRST_NODE) -#define listPushNodeData(list, data, length) listAddNodeData(list, data, length, listLastNode(list)) +#define listPushNodeData(list, data, length) listAddNodeData(list, data, length, LAST_NODE) #define listInsertNodeData(list, data, length) listAddNodeData(list, data, length, FIRST_NODE) -#define listPushNodeString(list, str) listAddNodeString(list, str, listLastNode(list)) +#define listPushNodeString(list, str) listAddNodeString(list, str, LAST_NODE) #define listInsertNodeString(list, str) listAddNodeString(list, str, FIRST_NODE) -#define listPushStringList(list, str_list) listAddStringList(list, str_list, listLastNode(list)) +#define listPushStringList(list, str_list) listAddStringList(list, str_list, LAST_NODE) #define listInsertStringList(list, str_list) listAddStringList(list, str_list, FIRST_NODE) -#define listPopNode(list) listRemoveNode(list, listLastNode(list), FALSE) +#define listPopNode(list) listRemoveNode(list, LAST_NODE, FALSE) #define listShiftNode(list) listRemoveNode(list, FIRST_NODE, FALSE) /* Remove node from list, returning the node's data (if not free'd) */ -DLLEXPORT void* DLLCALL listRemoveNode(link_list_t*, list_node_t* /* NULL=first */, BOOL free_data); +DLLEXPORT void* DLLCALL listRemoveNode(link_list_t*, list_node_t* /* NULL=first */, BOOL free_data); /* Remove multiple nodes from list, returning the number of nodes removed */ -long listRemoveNodes(link_list_t*, list_node_t* /* NULL=first */, long count, BOOL free_data); +DLLEXPORT long DLLCALL listRemoveNodes(link_list_t*, list_node_t* /* NULL=first */, long count, BOOL free_data); #if defined(__cplusplus) }