diff --git a/src/xpdev/link_list.c b/src/xpdev/link_list.c index 1f2d60cb0a36b3f2e8cc6fd30785717efc745250..ee899af2b0bd1a21adbc5e55078e67075954028a 100644 --- a/src/xpdev/link_list.c +++ b/src/xpdev/link_list.c @@ -69,7 +69,7 @@ void listFreeNodes(link_list_t* list) for(node=list->first; node!=NULL; node=next) { - if(list->flags&LINK_LIST_AUTO_FREE) + if(list->flags&LINK_LIST_ALWAYS_FREE || node->flags&LINK_LIST_MALLOC) listFreeNodeData(node); next = node->next; @@ -95,13 +95,13 @@ link_list_t* listFree(link_list_t* list) return(list); } -size_t listCountNodes(const link_list_t* list) +long listCountNodes(const link_list_t* list) { - size_t count=0; + long count=0; list_node_t* node; if(list==NULL) - return(0); + return(-1); if(list->count) return(list->count); @@ -112,6 +112,60 @@ size_t listCountNodes(const link_list_t* list) return(count); } +list_node_t* listFindNode(const link_list_t* list, void* data, size_t length) +{ + list_node_t* node; + + if(list==NULL) + return(NULL); + + for(node=list->first; node!=NULL; node=node->next) + if(node->data!=NULL && memcmp(node->data,data,length)==0) + break; + + return(node); +} + +str_list_t listStringList(const link_list_t* list) +{ + list_node_t* node; + str_list_t str_list; + + if(list==NULL) + return(NULL); + + if((str_list=strListAlloc())==NULL) + return(NULL); + + for(node=list->first; node!=NULL; node=node->next) { + if(node->data!=NULL) + strListAdd(&str_list, node->data); + } + + return(str_list); +} + +str_list_t listSubStringList(const list_node_t* node, long max) +{ + long count=0; + str_list_t str_list; + + if(node==NULL) + return(NULL); + + if((str_list=strListAlloc())==NULL) + return(NULL); + + for(count=0; count<max && node!=NULL; node=node->next) { + if(node->data!=NULL) { + strListAdd(&str_list, node->data); + count++; + } + } + + return(str_list); +} + list_node_t* listFirstNode(const link_list_t* list) { if(list==NULL) @@ -137,6 +191,38 @@ list_node_t* listLastNode(const link_list_t* list) return(last); } +long listNodeIndex(const link_list_t* list, list_node_t* find_node) +{ + long i=0; + list_node_t* node; + + if(list==NULL) + return(-1); + + for(node=list->first; node!=NULL; node=node->next) + if(node==find_node) + break; + + if(node==NULL) + return(-1); + + return(i); +} + +list_node_t* listNodeAt(const link_list_t* list, long index) +{ + long i=0; + list_node_t* node; + + if(list==NULL || index<0) + return(NULL); + + for(node=list->first; node!=NULL && i<index; node=node->next) + i++; + + return(node); +} + list_node_t* listNextNode(const list_node_t* node) { if(node==NULL) @@ -178,8 +264,9 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after) if(after==list->last) /* append to list */ list->last = node; - if(after==NULL && list->first!=NULL) { /* insert at beginning of list */ - list->first->prev = node; + if(after==NULL) { /* insert at beginning of list */ + if(list->first!=NULL) + list->first->prev = node; list->first = node; } if(after!=NULL) { @@ -195,17 +282,6 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after) return(node); } - -list_node_t* listPushNode(link_list_t* list, void* data) -{ - return(listAddNode(list, data, listLastNode(list))); -} - -list_node_t* listInsertNode(link_list_t* list, void* data) -{ - return(listAddNode(list, data, NULL)); -} - list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_t* after) { list_node_t* node; @@ -219,20 +295,11 @@ list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length, free(buf); return(NULL); } + node->flags |= LINK_LIST_MALLOC; return(node); } -list_node_t* listPushNodeData(link_list_t* list, const void* data, size_t length) -{ - return(listAddNodeData(list, data, length, listLastNode(list))); -} - -list_node_t* listInsertNodeData(link_list_t* list, const void* data, size_t length) -{ - return(listAddNodeData(list, data, length, NULL)); -} - list_node_t* listAddNodeString(link_list_t* list, const char* str, list_node_t* after) { list_node_t* node; @@ -252,25 +319,35 @@ list_node_t* listAddNodeString(link_list_t* list, const char* str, list_node_t* free(buf); return(NULL); } - + node->flags |= LINK_LIST_MALLOC; + return(node); } -list_node_t* listPushNodeString(link_list_t* list, const char* str) +list_node_t* listAddStringList(link_list_t* list, str_list_t str_list, list_node_t* node) { - return(listAddNodeString(list, str, listLastNode(list))); -} + size_t i; -list_node_t* listInsertNodeString(link_list_t* list, const char* str) -{ - return(listAddNodeString(list, str, NULL)); + if(str_list==NULL) + return(NULL); + + for(i=0;str_list[i];i++) + if((node=listAddNodeString(list,str_list[i],node))==NULL) + return(NULL); + + return(node); } void* listRemoveNode(link_list_t* list, list_node_t* node) { void* data; - if(list==NULL || node==NULL) + if(list==NULL) + return(NULL); + + if(node==NULL) + node=list->first; + if(node==NULL) return(NULL); if(node->prev!=NULL) @@ -282,9 +359,10 @@ void* listRemoveNode(link_list_t* list, list_node_t* node) if(list->last==node) list->last = node->prev; - if(list->flags&LINK_LIST_AUTO_FREE) + if(list->flags&LINK_LIST_ALWAYS_FREE || node->flags&LINK_LIST_MALLOC) listFreeNodeData(node); - data=node->data; + + data = node->data; free(node); @@ -294,16 +372,44 @@ void* listRemoveNode(link_list_t* list, list_node_t* node) return(data); } -void listRemoveNodeData(link_list_t* list, list_node_t* node) +long listRemoveNodes(link_list_t* list, list_node_t* node, long max) { - void* data; + long count; - if((data=listRemoveNode(list, node))!=NULL) - free(data); + if(list==NULL) + return(-1); + + if(node==NULL) + node=list->first; + + for(count=0; node!=NULL && count<max; node=node->next, count++) + listRemoveNode(list, node); + + return(count); } +#if 0 -void* listPopNode(link_list_t* list) +#include <stdio.h> /* printf, sprintf */ + +int main(int arg, char** argv) { - return(listRemoveNode(list, listLastNode(list))); + int i; + char* p; + char str[32]; + link_list_t list; + + listInit(&list,0); + for(i=0;i<100;i++) { + sprintf(str,"%u",i); + listPushNodeString(&list,str); + } + + while((p=listRemoveNode(&list,NULL))!=NULL) + printf("%d %s\n",listCountNodes(&list),p), free(p); + + gets(str); + return 0; } + +#endif \ No newline at end of file diff --git a/src/xpdev/link_list.h b/src/xpdev/link_list.h index 3f720335068a95bbf66e0ffe67e40a8a4e7f798d..9cb107dc349cbcbbc702d9cfd6c740224d60776b 100644 --- a/src/xpdev/link_list.h +++ b/src/xpdev/link_list.h @@ -39,26 +39,28 @@ #define _LINK_LIST_H #include <stddef.h> /* size_t */ +#include "str_list.h" /* string list functions and types */ #if defined(__cplusplus) extern "C" { #endif /* Valid link_list_t.flags bits */ -#define LINK_LIST_MALLOC (1<<0) /* List allocated with malloc() */ -#define LINK_LIST_AUTO_FREE (1<<1) /* Free node data automatically */ +#define LINK_LIST_MALLOC (1<<0) /* List/node allocated with malloc() */ +#define LINK_LIST_ALWAYS_FREE (1<<1) /* Always free node data when removing */ typedef struct list_node { 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) */ + unsigned long flags; /* private use flags */ } list_node_t; typedef struct { list_node_t* first; /* first node in list (or NULL) */ list_node_t* last; /* last node in list (or NULL) */ unsigned long flags; /* flags passed to listInit() */ - size_t count; /* number of nodes in list */ + long count; /* number of nodes in list */ } link_list_t; /* Initialization, Allocation, and Freeing of Lists and Nodes */ @@ -67,33 +69,55 @@ link_list_t* listFree(link_list_t*); void listFreeNodes(link_list_t*); void listFreeNodeData(list_node_t* node); +/* Return count or index of nodes, or -1 on error */ +long listCountNodes(const link_list_t*); +long listNodeIndex(const link_list_t*, list_node_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*); + +/* 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); + +/* Simple search functions returning found node or NULL on error */ +list_node_t* listNodeAt(const link_list_t*, long index); +list_node_t* listFindNode(const link_list_t*, void* data, size_t length); + /* Convenience functions */ -size_t listCountNodes(const link_list_t*); list_node_t* listFirstNode(const link_list_t*); list_node_t* listLastNode(const link_list_t*); list_node_t* listNextNode(const list_node_t*); list_node_t* listPrevNode(const list_node_t*); void* listNodeData(const list_node_t*); -/* Add node to list, returns pointer to new node */ -list_node_t* listAddNode(link_list_t*, void* data, list_node_t* after); -list_node_t* listPushNode(link_list_t*, void* data); -list_node_t* listInsertNode(link_list_t*, void* data); +/* Add node to list, returns pointer to new node or NULL on error */ +list_node_t* listAddNode(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); -list_node_t* listPushNodeData(link_list_t*, const void* data, size_t length); -list_node_t* listInsertNodeData(link_list_t*, const void* data, size_t length); -/* Add node to list, allocating and copying string (ACIIZ / null-terminated char*) */ +/* Add node to list, allocating and copying ASCIIZ string data */ list_node_t* listAddNodeString(link_list_t*, const char* str, list_node_t* after); -list_node_t* listPushNodeString(link_list_t*, const char* str); -list_node_t* listInsertNodeString(link_list_t*, const char* str); + +/* Add a list of strings to the linked list, allocating and copying each */ +list_node_t* listAddStringList(link_list_t*, str_list_t, list_node_t* after); + +/* Convenience macros for pushing, popping, and inserting nodes */ +#define listPushNode(list, data) listAddNode(list, data, listLastNode(list)) +#define listInsertNode(link, data) listAddNode(list, data, NULL) +#define listPushNodeData(list, data, length) listAddNodeData(list, data, length, listLastNode(list)) +#define listInsertNodeData(list, data, length) listAddNodeData(list, data, length, NULL) +#define listPushNodeString(list, str) listAddNodeString(list, str, listLastNode(list)) +#define listInsertNodeString(list, str) listAddNodeString(list, str, NULL) +#define listPushStringList(list, str_list) listAddStringList(list, str_list, listLastNode(list)) +#define listInsertStringList(list, str_list) listAddStringList(list, str_list, NULL) +#define listPopNode(list) listRemoveNode(list, listLastNode(list)) /* Remove node from list, returning the node's data (if not free'd) */ -void* listPopNode(link_list_t*); -void* listRemoveNode(link_list_t*, list_node_t*); -void listRemoveNodeData(link_list_t* list, list_node_t* node); +void* listRemoveNode(link_list_t*, list_node_t* /* NULL=first */); + +/* Remove multiple nodes from list, returning the number of nodes removed */ +long listRemoveNodes(link_list_t*, list_node_t* /* NULL=first */, long count); #if defined(__cplusplus) }