dunst/list.c
2012-07-01 08:06:33 +02:00

260 lines
4.7 KiB
C

#include "stdlib.h"
#include "stdio.h"
#include "list.h"
int l_push(list * l, void *data)
{
l_node *n;
int ret;
/* invalid input */
if (!l || !data) {
return -1;
}
n = l_init_node(data);
if (!n) {
/* something went wrong */
return -2;
}
ret = l_node_push(l, n);
return ret;
}
int l_node_push(list * l, l_node * n)
{
l_node *end;
/* invalid input */
if (!l || !n) {
return -1;
}
n->next = NULL;
/* empty list */
if (!l->head) {
l->head = n;
return 0;
}
for (end = l->head; end->next; end = end->next) ;
if (end != n) {
end->next = n;
}
return 0;
}
void *l_pop(list * l)
{
l_node *penultimate;
void *data;
/* invalid input */
if (!l) {
return NULL;
}
/* empty list */
if (!l->head) {
return NULL;
}
/* len(l) == 1 */
if (!l->head->next) {
data = l->head->data;
free(l->head);
l->head = NULL;
return data;
}
for (penultimate = l->head;
penultimate->next->next; penultimate = penultimate->next) ;
data = penultimate->next->data;
free(penultimate->next);
penultimate->next = NULL;
return data;
}
int l_insert(l_node * node, void *data)
{
int ret;
l_node *to_be_inserted;
/* invalid input */
if (!node || !data) {
return -1;
}
to_be_inserted = l_init_node(data);
if (!to_be_inserted) {
return -2;
}
ret = l_node_insert(node, to_be_inserted);
return ret;
}
int l_node_insert(l_node * node, l_node * to_be_inserted)
{
l_node *tmp;
/* invalid input */
if (!node || !to_be_inserted) {
return -1;
}
tmp = node->next;
node->next = to_be_inserted;
to_be_inserted->next = tmp;
return 0;
}
void *l_remove(list * l, l_node * node)
{
void *data;
l_node_remove(l, node);
data = node->data;
free(node);
return data;
}
l_node *l_node_remove(list * l, l_node * node)
{
l_node *prev;
l_node *next;
/* invalid input */
if (!l || !node) {
return NULL;
}
/* empty list */
if (!l->head) {
return NULL;
}
/* node is head */
if (l->head == node) {
l->head = node->next;
node->next = NULL;
return node;
}
/* find the predecessor of node */
for (prev = l->head;
prev->next && prev->next != node; prev = prev->next) ;
/* node not in list */
if (prev->next != node) {
return node;
}
next = node->next;
prev->next = next;
return node;
}
l_node *l_init_node(void *data)
{
l_node *node;
node = malloc(sizeof(l_node));
if (!node) {
return NULL;
}
node->data = data;
node->next = NULL;
return node;
}
int l_length(list * l)
{
l_node *iter;
int count;
if (!l || !l->head) {
return 0;
}
count = 0;
iter = l->head;
while (iter) {
count++;
iter = iter->next;
}
return count;
}
int l_is_empty(list * l)
{
return l->head == NULL;
}
int l_move(list * from, list * to, l_node * node)
{
if (!from || !to || !node) {
return -1;
}
node = l_node_remove(from, node);
return l_node_push(to, node);
}
list *l_init(void)
{
list *l = malloc(sizeof(list));
l->head = NULL;
return l;
}
void l_sort(list * l, int (*f) (void *, void *))
{
list *old_list;
if (!l || l_length(l) < 2) {
/* nothing to do */
return;
}
old_list = l_init();
old_list->head = l->head;
l->head = NULL;
while (!l_is_empty(old_list)) {
l_node *iter;
l_node *max;
/* find max in old_list */
max = old_list->head;
for (iter = old_list->head; iter; iter = iter->next) {
if (f(max->data, iter->data) < 0) {
max = iter;
}
}
l_move(old_list, l, max);
}
free(old_list);
}
/* vim: set ts=8 sw=8 tw=0: */