Files
lcdproc/shared/LL.c
T

815 lines
16 KiB
C
Raw Normal View History

1999-12-09 23:15:14 +00:00
#include <stdlib.h>
#include <stdio.h>
#include "LL.h"
#ifdef DEBUG
#undef DEBUG
#endif
//TODO: Comment everything
//TODO: Test everything?
//////////////////////////////////////////////////////////////////////
// Creates a new list...
LL *
LL_new ()
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL *list;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
list = malloc (sizeof (LL));
if (!list)
return NULL;
2000-04-03 22:13:57 +00:00
list->head.data = NULL;
list->head.prev = NULL;
list->head.next = &list->tail;
list->tail.data = NULL;
list->tail.prev = &list->head;
list->tail.next = NULL;
list->current = &list->head;
2000-04-03 22:13:57 +00:00
return list;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// TODO: test this function
// Destroys the entire list
// Warning! Does not free the list data! (only the list itself)
int
LL_Destroy (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *node, *next;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
2000-04-03 22:13:57 +00:00
node = &list->head;
2000-04-03 22:13:57 +00:00
for (node = node->next; node && node->next; node = next) {
// Avoid accessing "node" after it's freed.. :)
next = node->next;
if (LL_node_Destroy (node) < 0)
return -1;
}
2000-04-03 22:13:57 +00:00
free (list);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// TODO: test this function
// Warning! This does not assert that the node data is free!
int
LL_node_Destroy (LL_node * node)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!node)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (LL_node_Unlink (node) < 0)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
free (node);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_node_Unlink (LL_node * node)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *next, *prev;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!node)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
next = node->next;
prev = node->prev;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (next)
next->prev = prev;
if (prev)
prev->next = next;
2000-04-03 22:13:57 +00:00
node->next = NULL;
node->prev = NULL;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Frees the data in a list node, if not NULL...
int
LL_node_DestroyData (LL_node * node)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!node)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (node->data)
free (node->data);
else
return -1;
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Returns to the beginning of the list...
int
LL_Rewind (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
1999-12-09 23:15:14 +00:00
/*
printf("LL_Rewind: list=%8x\n", list);
printf("LL_Rewind: list.head=%8x\n", &list->head);
printf("LL_Rewind: list.tail=%8x\n", &list->tail);
*/
2000-04-03 22:13:57 +00:00
if (list->head.next != &list->tail)
list->current = list->head.next;
else
list->current = &list->head;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Goes to the end of the list...
int
LL_End (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (list->tail.prev != &list->head)
list->current = list->tail.prev;
else
list->current = &list->tail;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Go to the next node
int
LL_Next (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!list->current)
return -1;
2000-04-03 22:13:57 +00:00
if (list->current->next != &list->tail) {
list->current = list->current->next;
return 0;
} else {
return -1;
}
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Go to the previous node
int
LL_Prev (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!list->current)
return -1;
2000-04-03 22:13:57 +00:00
if (list->current->prev != &list->head) {
list->current = list->current->prev;
return 0;
} else {
return -1;
}
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Data manipulation
void *
LL_Get (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
if (!list->current)
return NULL;
2000-04-03 22:13:57 +00:00
return list->current->data;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_Put (LL * list, void *data)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!list->current)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
list->current->data = data;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
LL_node *
LL_GetNode (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return list->current;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Don't use this unless you know what you're doing.
int
LL_PutNode (LL * list, LL_node * node)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!node)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
list->current = node;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_GetFirst (LL * list) // gets data from first node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Rewind (list))
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return LL_Get (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
//
void *
2000-04-03 22:13:57 +00:00
LL_GetNext (LL * list) // ... next node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Next (list))
return NULL;
2000-04-03 22:13:57 +00:00
return LL_Get (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_GetPrev (LL * list) // ... prev node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Prev (list))
return NULL;
2000-04-03 22:13:57 +00:00
return LL_Get (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_GetLast (LL * list) // ... last node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_End (list))
return NULL;
2000-04-03 22:13:57 +00:00
return LL_Get (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_AddNode (LL * list, void *add) // Adds node AFTER current one
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *node;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
//if(!add) return -1; // Nevermind.. NULL entries can be good...
if (!list->current)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
//LL_dprint(list);
2000-04-03 22:13:57 +00:00
node = malloc (sizeof (LL_node));
if (!node)
return -1;
//printf("Allocated node\n");
1999-12-09 23:15:14 +00:00
/* printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */
/* (int)list->current->prev, */
/* (int)list->current, */
/* (int)list->current->next); */
2000-04-03 22:13:57 +00:00
if (list->current == &list->tail) {
list->current = list->current->prev;
1999-12-09 23:15:14 +00:00
/* printf("Was at end of list...\n"); */
/* printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */
/* (int)list->current->prev, */
/* (int)list->current, */
/* (int)list->current->next); */
2000-04-03 22:13:57 +00:00
}
1999-12-09 23:15:14 +00:00
// printf("Setting node data\n");
2000-04-03 22:13:57 +00:00
node->next = list->current->next;
node->prev = list->current;
node->data = add;
1999-12-09 23:15:14 +00:00
// printf("...done\n");
/* printf("NewNode: prev: %8x\tnode: %8x\tnext: %8x\n", */
/* (int)node->prev, */
/* (int)node, */
/* (int)node->next); */
1999-12-09 23:15:14 +00:00
// printf("Relinking...\n");
2000-04-03 22:13:57 +00:00
if (node->next)
node->next->prev = node;
1999-12-09 23:15:14 +00:00
// printf("...\n");
2000-04-03 22:13:57 +00:00
list->current->next = node;
1999-12-09 23:15:14 +00:00
// printf("...done\n");
2000-04-03 22:13:57 +00:00
list->current = node;
1999-12-09 23:15:14 +00:00
// printf("Added node\n");
// LL_dprint(list);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_InsertNode (LL * list, void *add) // Adds node BEFORE current one
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *node;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!add)
return -1;
if (!list->current)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
node = malloc (sizeof (LL_node));
if (!node)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (list->current == &list->head)
list->current = list->current->next;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
node->next = list->current;
node->prev = list->current->prev;
node->data = add;
2000-04-03 22:13:57 +00:00
if (list->current->prev)
list->current->prev->next = node;
2000-04-03 22:13:57 +00:00
list->current->prev = node;
2000-04-03 22:13:57 +00:00
list->current = node;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
////////////////////////////////////////////////////////////////////////
// Removes a node from the link
// ... and advances one node forward
void *
LL_DeleteNode (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *next, *prev;
void *data;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
if (!list->current)
return NULL;
if (list->current == &list->head)
return NULL;
if (list->current == &list->tail)
return NULL;
1999-12-09 23:15:14 +00:00
#ifdef DEBUG
2000-04-03 22:13:57 +00:00
printf ("LL_DeleteNode: Before...\n");
LL_dprint (list);
#endif
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
next = list->current->next;
prev = list->current->prev;
data = list->current->data;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (prev)
prev->next = next;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (next)
next->prev = prev;
2000-04-03 22:13:57 +00:00
list->current->prev = NULL;
list->current->next = NULL;
// This should not free things; the user should do it explicitly.
//if(list->current->data) free(list->current->data);
list->current->data = NULL;
2000-04-03 22:13:57 +00:00
free (list->current);
2000-04-03 22:13:57 +00:00
list->current = next;
#ifdef DEBUG
2000-04-03 22:13:57 +00:00
printf ("LL_DeleteNode: After...\n");
LL_dprint (list);
#endif
2000-04-03 22:13:57 +00:00
return data;
1999-12-09 23:15:14 +00:00
}
1999-12-09 23:15:14 +00:00
//////////////////////////////////////////////////////////////////////
// Removes a specific node...
void *
LL_Remove (LL * list, void *data)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
void *find;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
2000-04-03 22:13:57 +00:00
LL_Rewind (list);
do {
find = LL_Get (list);
if (find == data)
return LL_DeleteNode (list);
} while (LL_Next (list) == 0);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return NULL;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Stack operations
int
2000-04-03 22:13:57 +00:00
LL_Push (LL * list, void *add) // Add node to end of list
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!add)
return -1;
1999-12-09 23:15:14 +00:00
// printf("Going to end of list...\n");
2000-04-03 22:13:57 +00:00
LL_End (list);
1999-12-09 23:15:14 +00:00
// printf("Adding node...\n");
2000-04-03 22:13:57 +00:00
return LL_AddNode (list, add);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_Pop (LL * list) // Remove node from end of list
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
2000-04-03 22:13:57 +00:00
if (0 > LL_End (list))
return NULL;
2000-04-03 22:13:57 +00:00
return LL_DeleteNode (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_Top (LL * list) // Peek at end node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
return LL_GetLast (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_Shift (LL * list) // Remove node from start of list
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Rewind (list))
return NULL;
2000-04-03 22:13:57 +00:00
return LL_DeleteNode (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
void *
2000-04-03 22:13:57 +00:00
LL_Look (LL * list) // Peek at first node
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
return LL_GetFirst (list);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_Unshift (LL * list, void *add) // Add node to beginning of list
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!add)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
LL_Rewind (list);
2000-04-03 22:13:57 +00:00
return LL_InsertNode (list, add);
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
2000-04-03 22:13:57 +00:00
LL_Roll (LL * list) // Make last node first
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *node, *next;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
//if(!list->current) return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_End (list))
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// Avoid rolling an empty list, or unlinking the head/tail...
if (list->current == &list->head)
list->current = list->current->next;
if (list->current == &list->tail)
list->current = list->current->prev;
// List is empty
if (list->current == &list->head)
return 0;
// List has one item
if (list->current->prev == &list->head)
return 0;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
node = list->current;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
LL_node_Unlink (node);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Rewind (list))
return -1;
2000-04-03 22:13:57 +00:00
next = list->head.next;
2000-04-03 22:13:57 +00:00
list->head.next = node;
next->prev = node;
node->prev = &list->head;
node->next = next;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
2000-04-03 22:13:57 +00:00
LL_UnRoll (LL * list) // Roll the other way...
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *node, *prev;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
//if(!list->current) return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_Rewind (list))
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// Avoid rolling an empty list, or unlinking the head/tail...
if (list->current == &list->tail)
list->current = list->current->prev;
if (list->current == &list->head)
list->current = list->current->next;
// List is empty
if (list->current == &list->tail)
return 0;
// List has one item
if (list->current->next == &list->tail)
return 0;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
node = list->current;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
LL_node_Unlink (node);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (0 > LL_End (list))
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
prev = list->tail.prev;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
list->tail.prev = node;
prev->next = node;
node->next = &list->tail;
node->prev = prev;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Add an item to the end of its "priority group"
// The list is assumed to be sorted already...
int
LL_PriorityEnqueue (LL * list, void *add, int compare (void *, void *))
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
void *data;
int i;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!add)
return -1;
if (!compare)
return -1;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// From the end of the list, keep searching while we're "less than"
// the given nodes...
LL_End (list);
do {
data = LL_Get (list);
if (data) {
i = compare (add, data);
if (i >= 0) // If we're in the right place, add it and exit
{
LL_AddNode (list, add);
return 0;
}
}
} while (LL_Prev (list) == 0);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// If we're less than *everything*, put it at the beginning
LL_Unshift (list, add);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
1999-12-09 23:15:14 +00:00
//////////////////////////////////////////////////////////////////////
int
LL_SwapNodes (LL_node * one, LL_node * two) // Switch two nodes positions...
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *firstprev, *firstnext;
LL_node *secondprev, *secondnext;
2000-04-03 22:13:57 +00:00
if (!one || !two)
return -1;
if (one == two)
return 0; // Do nothing
2000-04-03 22:13:57 +00:00
firstprev = one->prev; // Look up the nodes neighbors...
firstnext = one->next;
secondprev = two->prev;
secondnext = two->next;
2000-04-03 22:13:57 +00:00
if (firstprev != NULL)
firstprev->next = two; // Swap the neighboring
if (firstnext != NULL)
firstnext->prev = two; // nodes pointers...
if (secondprev != NULL)
secondprev->next = one;
if (secondprev != NULL)
secondnext->prev = one;
2000-04-03 22:13:57 +00:00
one->next = secondnext; // Swap the nodes pointers
one->prev = secondprev;
two->next = firstnext;
two->prev = firstprev;
2000-04-03 22:13:57 +00:00
if (firstnext == two)
one->prev = two; // Fix things in case
if (firstprev == two)
one->next = two; // they were next to
if (secondprev == one)
two->next = one; // each other...
if (secondnext == one)
two->prev = one;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
int
LL_nSwapNodes (int one, int two) // Switch two nodes positions...
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
return -1;
}
1999-12-09 23:15:14 +00:00
//////////////////////////////////////////////////////////////////////
int
2000-04-03 22:13:57 +00:00
LL_Length (LL * list) // Returns # of nodes in entire list
{
2000-04-03 22:13:57 +00:00
LL_node *node;
int num = 0;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
2000-04-03 22:13:57 +00:00
node = &list->head;
2000-04-03 22:13:57 +00:00
for (num = -1; node != &list->tail; num++)
node = node->next;
2000-04-03 22:13:57 +00:00
return num;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Searching...
// Goes to the list item which matches "value", and returns the
// data found there.
//
// The "compare" function should return 0 for a "match"
//
// Note that this does *not* rewind the list first! You should do
// it yourself if you want to start from the beginning!
void *
LL_Find (LL * list, int compare (void *, void *), void *value)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
void *data;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return NULL;
if (!compare)
return NULL;
if (!value)
return NULL;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
do {
data = LL_Get (list);
if (0 == compare (data, value))
return data;
2000-04-03 22:13:57 +00:00
} while (LL_Next (list) == 0);
2000-04-03 22:13:57 +00:00
return NULL;
1999-12-09 23:15:14 +00:00
}
//////////////////////////////////////////////////////////////////////
// Sorts the list, then rewinds it...
//
int
LL_Sort (LL * list, int compare (void *, void *))
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int i, j; // Junk / loop variables
int numnodes; // number of nodes in list
LL_node *best, *last; // best match and last node in the list
LL_node *current;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!list)
return -1;
if (!compare)
return -1;
2000-04-03 22:13:57 +00:00
numnodes = LL_Length (list); // get the number of nodes...
if (0 > LL_End (list))
return -1; // Find the last node.
last = LL_GetNode (list);
2000-04-03 22:13:57 +00:00
if (numnodes < 2)
return 0;
2000-04-03 22:13:57 +00:00
for (i = numnodes - 1; i > 0; i--) {
LL_Rewind (list); // get the first node again
best = last; // reset our "best" node
2000-04-03 22:13:57 +00:00
for (j = 0; j < i; j++) {
current = LL_GetNode (list);
// If we found a better match...
if (compare (current->data, best->data) > 0) {
best = current; // keep track of the "best" match
}
LL_Next (list); // Go to the next node.
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
LL_SwapNodes (last, best); // Switch two nodes...
if (best)
last = best->prev;
else
return -1;
2000-04-03 22:13:57 +00:00
//last = LL_FindPrev(best); // And go backwards by one node.
}
2000-04-03 22:13:57 +00:00
//return LLFindFirst(current); // return pointer to the first node.
LL_Rewind (list);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
void
LL_dprint (LL * list)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
LL_node *current;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
current = &list->head;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
printf ("Head: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", (int) list->head.prev, (int) &list->head, (int) list->head.next);
2000-04-03 22:13:57 +00:00
for (current = current->next; current != &list->tail; current = current->next) {
printf ("node: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", (int) current->prev, (int) current, (int) current->next);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
printf ("Tail: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", (int) list->tail.prev, (int) &list->tail, (int) list->tail.next);
1999-12-09 23:15:14 +00:00
}