//****************************************************************************
// Copyright (C) 2000-2004 ARW Elektronik Germany
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// This product is not authorized for use as critical component in
// life support systems without the express written approval of
// ARW Elektronik Germany.
//
// Please announce changes and hints to ARW Elektronik
//
// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
//
//****************************************************************************
//****************************************************************************
//
// list.c - provide list management functions to the driver,
// like C++ templates.
//
// $Log: list.c,v $
// Revision 1.6 2004/08/12 19:59:19 klaus
// conversion to kernel-version 2.6, released version 6.0
//
// Revision 1.5 2003/05/11 11:12:03 klaus
// matched to kernel 2.4 PCI handling, debug messages improved
//
// Revision 1.4 2001/11/20 20:12:50 klaus
// included new header and CVS log
//
//
// created by D. Muehlenberg and H.J.Mathes 1999
// added getNextNode and getPrevNode AR 18.02.2000
// MODVERSIONS included AR 24.04.2000
//
//****************************************************************************
#include "common.h" /* must be the first include */
#include "list.h"
Node *newNode(void)
{
Node *mynode;
mynode = (Node *)kmalloc(sizeof(Node), GFP_ATOMIC);
if (!mynode) return NULL;
mynode->pred = NULL;
mynode->succ = NULL;
mynode->data = NULL;
return mynode;
}
Node *addNode(Node *pos, void *insert, enum NodePosition p)
{
Node *mynode;
mynode = (Node *)kmalloc(sizeof(Node), GFP_ATOMIC);
if (!mynode) return NULL;
if (p == CurrentLeft) {
mynode->pred = pos;
mynode->succ = pos->succ;
pos->succ = mynode;
} else {
mynode->pred = pos->pred;
pos->pred = mynode;
mynode->succ = pos;
}
mynode->data = insert;
return mynode;
}
Node *delNodeAndData(Node *pos)
{
Node *tail = NULL;
if (!pos->pred) return NULL;
/* can't delete head */
if (!pos->succ) {
tail = pos->pred;
tail->succ = NULL;
} else {
pos->pred->succ = pos->succ;
pos->succ->pred = pos->pred;
}
kfree_s(pos->data, sizeof(*pos->data)); // FREE(pos->data);
kfree_s(pos, sizeof(*pos)); // FREE(pos);
return tail;
}
Node *delNode(Node *pos)
{
Node *tail = NULL;
if (!pos) return NULL;
if (!pos->pred) return NULL;
/* can't delete head */
if (!pos->succ) {
tail = pos->pred;
tail->succ = NULL;
} else {
pos->pred->succ = pos->succ;
pos->succ->pred = pos->pred;
}
kfree_s(pos, sizeof(*pos)); // FREE(pos);
return tail;
}
/* ------------------------------ */
List *newList(void)
{
List *ret = (List *)kmalloc(sizeof(List), GFP_ATOMIC);
if (!ret) return NULL;
ret->head = ret->tail = newNode();
if (!ret->head) {
kfree_s(ret, sizeof(*ret)); // FREE(ret);
return NULL;
}
ret->nodes = 0;
return ret;
}
void deleteList(List *l, void (*delete)(void *))
{
if (l) {
resetList(l,delete);
kfree_s(l->head, sizeof(*l->head)); // FREE(l->head);
kfree_s(l, sizeof(*l)); // FREE(l);
}
}
Node *addTail(List *list, void *insert)
{
Node *tail;
if (!list) return NULL;
tail = addNode(list->tail,insert,CurrentLeft);
if (!tail)
{
#ifdef __DEBUG__
printk("addTail(): addNode failed!\n");
#endif
return NULL;
}
list->tail = tail;
list->nodes++;
return tail;
}
Node *addHead(List *list, void *insert)
{
Node *node;
if (!list) return NULL;
if (!list->head->succ) {
return addTail(list,insert);
} else {
node = addNode(list->head,insert,CurrentRight);
}
if (node) list->nodes++;
return node;
}
Node *searchList(List *list, void *c, int (*comp)(void *, void *))
{
register Node *n;
if (!list) return NULL;
n = list->head->succ;
while (n) {
if (!comp(c,n->data)) {
return n;
}
n = n->succ;
}
return NULL;
}
void delNodeAndDataInList(List *l, Node *pos)
{
Node *n;
if (!l) return;
if ((n = delNodeAndData(pos))) l->tail = n;
l->nodes--;
}
void delNodeInList(List *l, Node *pos)
{
Node *n;
if (!l) return;
if ((n = delNode(pos))) l->tail = n;
l->nodes--;
}
int emptyList(List *l)
{
if (!l) return 1;
return l->head->succ ? 0 : 1;
}
void delTailAndData(List *l)
{
Node *t;
if (!l) return;
t = l->tail;
if (emptyList(l)) return;
l->tail = l->tail->pred;
l->tail->succ = NULL;
kfree_s(t->data, sizeof(*t->data)); // FREE(t->data);
kfree_s(t, sizeof(*t)); // FREE(t);
l->nodes--;
}
void delTail(List *l)
{
Node *t;
if (!l) return;
t = l->tail;
if (emptyList(l)) return;
l->tail = l->tail->pred;
l->tail->succ = NULL;
kfree_s(t, sizeof(*t)); // FREE(t);
l->nodes--;
}
void resetList(List *l, void (*delete)(void *))
{
register Node *n;
register void *data;
if (!l) return;
n = l->tail;
while (n->pred) {
data = n->data;
if (delete) {
delete(data);
}
else
{
kfree_s(data, sizeof(*data)); // FREE(data);
}
#if 0
n = delNode(n);
#endif
delNode(n);
n = n->pred;
}
l->tail = l->head;
l->nodes = 0;
}
Node *getFirstNode(List *l)
{
if (!l) return NULL;
return l->head->succ;
}
Node *getNextNode(Node *n)
{
if (n)
return n->succ;
else
return NULL;
}
Node *getPrevNode(Node *n)
{
if (n)
return n->pred;
else
return NULL;
}
void *getContent(Node *n)
{
return n->data;
}
Node *getLastNode(List *l)
{
if (!l) return NULL;
return l->tail;
}
void delFirstNode(List *l)
{
if (!l) return;
delNodeInList(l,getFirstNode(l));
}
void delFirstNodeAndData(List *l)
{
if (!l) return;
delNodeAndDataInList(l,getFirstNode(l));
}
void delLastNode(List *l)
{
if (!l) return;
delNodeInList(l,getLastNode(l));
}
void delLastNodeAndData(List *l)
{
if (!l) return;
delNodeAndDataInList(l,getLastNode(l));
}
#ifndef USE_MACROS
int getNumOfNodesInList(List *l)
{
if (!l) return 0;
return l->nodes;
}
#endif
void printList(List *l, char *(*StructToString)(void *))
{
register Node *n = l->head;
int i=1;
if (!l) return;
if (!n->succ)
{
printk("List empty!\n");
return;
}
while (n->succ)
{
printk("Node %d: %s",i++,StructToString(n->succ->data));
n = n->succ;
}
printk("\n");
}
#undef printk