Skip to content
Snippets Groups Projects
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
Branches
Tags
No related merge requests found
...@@ -69,7 +69,7 @@ void listFreeNodes(link_list_t* list) ...@@ -69,7 +69,7 @@ void listFreeNodes(link_list_t* list)
for(node=list->first; node!=NULL; node=next) { 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); listFreeNodeData(node);
next = node->next; next = node->next;
...@@ -95,13 +95,13 @@ link_list_t* listFree(link_list_t* list) ...@@ -95,13 +95,13 @@ link_list_t* listFree(link_list_t* list)
return(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; list_node_t* node;
if(list==NULL) if(list==NULL)
return(0); return(-1);
if(list->count) if(list->count)
return(list->count); return(list->count);
...@@ -112,6 +112,60 @@ size_t listCountNodes(const link_list_t* list) ...@@ -112,6 +112,60 @@ size_t listCountNodes(const link_list_t* list)
return(count); 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) list_node_t* listFirstNode(const link_list_t* list)
{ {
if(list==NULL) if(list==NULL)
...@@ -137,6 +191,38 @@ list_node_t* listLastNode(const link_list_t* list) ...@@ -137,6 +191,38 @@ list_node_t* listLastNode(const link_list_t* list)
return(last); 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) list_node_t* listNextNode(const list_node_t* node)
{ {
if(node==NULL) if(node==NULL)
...@@ -178,8 +264,9 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after) ...@@ -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 */ if(after==list->last) /* append to list */
list->last = node; list->last = node;
if(after==NULL && list->first!=NULL) { /* insert at beginning of list */ if(after==NULL) { /* insert at beginning of list */
list->first->prev = node; if(list->first!=NULL)
list->first->prev = node;
list->first = node; list->first = node;
} }
if(after!=NULL) { if(after!=NULL) {
...@@ -195,17 +282,6 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after) ...@@ -195,17 +282,6 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after)
return(node); 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* listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_t* after)
{ {
list_node_t* node; list_node_t* node;
...@@ -219,20 +295,11 @@ list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length, ...@@ -219,20 +295,11 @@ list_node_t* listAddNodeData(link_list_t* list, const void* data, size_t length,
free(buf); free(buf);
return(NULL); return(NULL);
} }
node->flags |= LINK_LIST_MALLOC;
return(node); 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* listAddNodeString(link_list_t* list, const char* str, list_node_t* after)
{ {
list_node_t* node; list_node_t* node;
...@@ -252,25 +319,35 @@ list_node_t* listAddNodeString(link_list_t* list, const char* str, list_node_t* ...@@ -252,25 +319,35 @@ list_node_t* listAddNodeString(link_list_t* list, const char* str, list_node_t*
free(buf); free(buf);
return(NULL); return(NULL);
} }
node->flags |= LINK_LIST_MALLOC;
return(node); 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) if(str_list==NULL)
{ return(NULL);
return(listAddNodeString(list, str, 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* listRemoveNode(link_list_t* list, list_node_t* node)
{ {
void* data; void* data;
if(list==NULL || node==NULL) if(list==NULL)
return(NULL);
if(node==NULL)
node=list->first;
if(node==NULL)
return(NULL); return(NULL);
if(node->prev!=NULL) if(node->prev!=NULL)
...@@ -282,9 +359,10 @@ void* listRemoveNode(link_list_t* list, list_node_t* node) ...@@ -282,9 +359,10 @@ void* listRemoveNode(link_list_t* list, list_node_t* node)
if(list->last==node) if(list->last==node)
list->last = node->prev; 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); listFreeNodeData(node);
data=node->data;
data = node->data;
free(node); free(node);
...@@ -294,16 +372,44 @@ void* listRemoveNode(link_list_t* list, list_node_t* node) ...@@ -294,16 +372,44 @@ void* listRemoveNode(link_list_t* list, list_node_t* node)
return(data); 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) if(list==NULL)
free(data); 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 @@ ...@@ -39,26 +39,28 @@
#define _LINK_LIST_H #define _LINK_LIST_H
#include <stddef.h> /* size_t */ #include <stddef.h> /* size_t */
#include "str_list.h" /* string list functions and types */
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
/* Valid link_list_t.flags bits */ /* Valid link_list_t.flags bits */
#define LINK_LIST_MALLOC (1<<0) /* List allocated with malloc() */ #define LINK_LIST_MALLOC (1<<0) /* List/node allocated with malloc() */
#define LINK_LIST_AUTO_FREE (1<<1) /* Free node data automatically */ #define LINK_LIST_ALWAYS_FREE (1<<1) /* Always free node data when removing */
typedef struct list_node { typedef struct list_node {
void* data; /* pointer to some kind of data */ void* data; /* pointer to some kind of data */
struct list_node* next; /* next node in list (or NULL) */ struct list_node* next; /* next node in list (or NULL) */
struct list_node* prev; /* previous node in list (or NULL) */ struct list_node* prev; /* previous node in list (or NULL) */
unsigned long flags; /* private use flags */
} list_node_t; } list_node_t;
typedef struct { typedef struct {
list_node_t* first; /* first node in list (or NULL) */ list_node_t* first; /* first node in list (or NULL) */
list_node_t* last; /* last node in list (or NULL) */ list_node_t* last; /* last node in list (or NULL) */
unsigned long flags; /* flags passed to listInit() */ 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; } link_list_t;
/* Initialization, Allocation, and Freeing of Lists and Nodes */ /* Initialization, Allocation, and Freeing of Lists and Nodes */
...@@ -67,33 +69,55 @@ link_list_t* listFree(link_list_t*); ...@@ -67,33 +69,55 @@ link_list_t* listFree(link_list_t*);
void listFreeNodes(link_list_t*); void listFreeNodes(link_list_t*);
void listFreeNodeData(list_node_t* node); 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 */ /* Convenience functions */
size_t listCountNodes(const link_list_t*);
list_node_t* listFirstNode(const link_list_t*); list_node_t* listFirstNode(const link_list_t*);
list_node_t* listLastNode(const link_list_t*); list_node_t* listLastNode(const link_list_t*);
list_node_t* listNextNode(const list_node_t*); list_node_t* listNextNode(const list_node_t*);
list_node_t* listPrevNode(const list_node_t*); list_node_t* listPrevNode(const list_node_t*);
void* listNodeData(const list_node_t*); void* listNodeData(const list_node_t*);
/* Add node to list, returns pointer to new node */ /* 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); list_node_t* listAddNode(link_list_t*, void* data, list_node_t* after /* NULL=insert */);
list_node_t* listPushNode(link_list_t*, void* data);
list_node_t* listInsertNode(link_list_t*, void* data);
/* Add node to list, allocating and copying the data for the node */ /* 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* 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* 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) */ /* 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* /* NULL=first */);
void* listRemoveNode(link_list_t*, list_node_t*);
void listRemoveNodeData(link_list_t* list, list_node_t* node); /* 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) #if defined(__cplusplus)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment