267 lines
4.9 KiB
C
267 lines
4.9 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;
|
|
if (l != NULL) {
|
|
l_node_remove(l, node);
|
|
}
|
|
|
|
if (node == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
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: */
|