Commit bdb1abde authored by rswindell's avatar rswindell
Browse files

Better support for auto allocation/free of node data/strings.

Using macros for pop/insert functions.
Support for string lists (adding, querying, etc).
parent 768279fb
......@@ -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
......@@ -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)
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment