Skip to content

Instantly share code, notes, and snippets.

@Soft
Created January 26, 2012 21:01
Show Gist options
  • Save Soft/1685084 to your computer and use it in GitHub Desktop.
Save Soft/1685084 to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdbool.h>
#include "list.h"
Node *list_append(Node *list, void *data) {
if (list) list_last(&list);
Node *node = malloc(sizeof(Node));
if (node) {
node->data = data;
node->next = NULL;
node->prev = list;
if (list) {
list->next = node;
}
}
return node;
}
void list_traverse(Node *list, void (*traverser)(void *data)) {
list_head(&list);
for (; list; traverser(list->data), list = list->next);
}
void list_free(Node *list) {
list_head(&list);
for (Node *next; list; list = next) {
next = list->next;
free(list->data);
free(list);
}
}
int list_length(Node *list) {
int len = 1;
Node *temp;
if (!list) return 0;
for (temp = list; temp->prev; ++len, temp = temp->prev);
for (temp = list; temp->next; ++len, temp = temp->next);
return len;
}
Node *list_search(Node *list, bool (*comparer)(void const *data)) {
if (!list) return NULL;
list_head(&list);
for (; list; list = list->next) {
if (comparer(list->data)) {
return list;
}
}
return NULL;
}
Node *list_remove(Node *node) {
if (!node->prev) {
Node *temp = node->next;
temp->prev = NULL;
free(node->data);
free(node);
return temp;
} else {
node->prev->next = node->next;
if (node->next) node->next->prev = node->prev;
free(node->data);
free(node);
return NULL;
}
}
#ifndef LIST_H
#define LIST_H
#include <stdbool.h>
typedef struct _Node {
void *data;
struct _Node *next;
struct _Node *prev;
} Node;
// Appends a new node to the tail of the list
Node *list_append(Node *list, void *data);
// Frees the memory used by the list
void list_free(Node *list);
// Returns length of the list
int list_length(Node *list);
// Finds the first node where comparer returns true.
// Returns first matching node or NULL
Node *list_search(Node *list, bool (*comparer)(void const *data));
// Applies function to each of the nodes
void list_traverse(Node *list, void (*traverser)(void *data));
// Removes node from the list and returns NULL.
// If removed node was head of the list (prev = NULL) return pointer to the new list head
Node *list_remove(Node *node);
// Traverses pointer to the first node of the list
static inline void list_head(Node **list) {
for (; (*list)->prev; *list = (*list)->prev);
}
// Traverses pointer to the last node of the list
static inline void list_last(Node **list) {
for (; (*list)->next; *list = (*list)->next);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment