/*
 * Doubly-linked list.
 *
 * (C) 1998-2002 Murat Deligonul
 * 
 ***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef __LINKEDLIST_H
#define __LINKEDLIST_H

#include "autoconf.h"

#include "debug.h"

class __list_core 
{
    friend class __list_iter;    
protected:
    struct node 
    {
        void * data;
        node * next;
        node * prev;
    } *_first, * _last;

    node * find_by_idx(int, int * = 0) const;
    void * remove(node *);
    int num_nodes;
    int mod_count;

public:
    __list_core(void);
    ~__list_core(void) { clear(); }
    
    int add(void * data);
    int add(int, void * data);
    void * get(int);
    void * remove(int);
    bool   remove(void *);
    void   clear();

    void * first(void) { return (_first) ? _first->data : 0; }
    void * last(void) { return (_last) ? _last->data : 0; }

    int size() { return num_nodes; }
};  

class __list_iter
{
private:
    __list_core::node * current,
                      * last_returned;
    					
    __list_core * list;
    int mod_count;
    
public:
    __list_iter(__list_core * l) { attach(l); }
    void attach(__list_core * l) { list = l; mod_count = l->mod_count; last_returned = 0; current = l->_first; }
    void * remove();
	void * next();
	
	bool has_next() const
	{
		return (current);
	}
	
    /* Set current pointer to ith item (0-based) */
    void * set(int i)
    {
        __list_core::node * n = list->find_by_idx(i);
        if (n)
            current = n;
        return (n) ? current->data : 0;
    }
};
    
template <class T> class list_iterator : public __list_iter
{
public:
    list_iterator(__list_core * x) : __list_iter(x) { }
    T * next()          { return (T *) __list_iter::next(); }
    T * remove()        { return (T *) __list_iter::remove(); }
    T * set(int x)      { return (T *) __list_iter::set(x); }
};
    
template <class T> class list : public __list_core
{    
public:
    int add(T *x)         { return __list_core::add((void *) x); }
    int add(int w, T * x) { return __list_core::add(w, (void *) x); }
    T * get(int idx)      { return (T *) __list_core::get(idx); }
    T * remove(int idx)   { return (T *) __list_core::remove(idx); }
    bool remove(T * d)    { return __list_core::remove(d); }

    T * first(void)       { return (T *) __list_core::first(); }
    T * last(void)        { return (T *) __list_core::last(); }
};


typedef list<char> strlist;

int strlist_remove(strlist * list, const char * str);

/*
 * delete every element, and destroy it too */
template<class T> int destroy_list(list<T> * l, bool array)
{
    if (!l)
        return 1;
    while (l->first())
    {
        if (array)
            delete[] (T *) l->first();
        else
            delete (T *) l->first();
        l->remove (0);
    }
    return 1;
}

#endif


syntax highlighted by Code2HTML, v. 0.9.1