/* *************************************************************
   RWhois Software

   Copyright (c) 1994 Scott Williamson and Mark Kosters
   Copyright (c) 1996-1998 Network Solutions, Inc.

   See the file LICENSE for conditions of use and distribution.
**************************************************************** */
#ifndef _DL_LIST_H_
#define _DL_LIST_H_

/* includes */

#include <sys/time.h>
#include "common.h"
#include "error.h"


/* definitions */

/* types */
typedef struct _dl_node_type
{
  struct _dl_node_type *next;
  struct _dl_node_type *prev;
  void                 *data;
} dl_node_type;

typedef struct _dl_list_type
{
  dl_node_type        *head;
  dl_node_type        *tail;
  dl_node_type        *current;
  int                 destroy_head_flag;
  int                 (*destroy_data)(void *data);
} dl_list_type;

/* prototypes */


dl_list_type *dl_list_create(int (*destroy_data)());

/* sets the defaults for a dl_list control block.  It initializes the
   list to empty, sets the 'destroy_head_flag', which determines if
   the control block itself is free()d on a destroy, and supplies the
   function pointer to the data free()ing routine. */
int dl_list_default(dl_list_type *list,
                    int destroy_head_flag,
                    int (*destroy_data)());

/* returns the value (a pointer to the data element) at the current
   position */
void *dl_list_value(dl_list_type *list);

/* returns the value at the current position plus n. */
void *dl_list_next_value(dl_list_type *list, int n);

/* returns the value at the current position minus n. */
void *dl_list_prev_value(dl_list_type *list, int n);

/* returns TRUE if the list is empty, false otherwise. */
int dl_list_empty(dl_list_type *list);

/* returns TRUE if we are at the tail, false otherwise. */

int dl_list_at_tail(dl_list_type *list);

/* sets the position to the head of the list */
int dl_list_first(dl_list_type *list);

/* sets the position to the tail of the list */
int dl_list_last(dl_list_type *list);

/* advances the position forward one node. */
int dl_list_next(dl_list_type *list);

/* moves the position backwards one node */
int dl_list_prev(dl_list_type *list);

/* inserts a node containing 'data' right after the current position */
int dl_list_insert(dl_list_type *list, void *data);

/* inserts a node containing 'data' right before the current position */
int dl_list_insert_before(dl_list_type *list, void *data);

/* adds a node containing 'data' to the end of the list */
int dl_list_append(dl_list_type *list, void *data);

/* inserts a node containing 'data' to the beginning of the list */
int dl_list_prepend(dl_list_type *list, void *data);

/* appends list2 to the end of list1 */
int dl_list_append_list(dl_list_type *list1, dl_list_type *list2);

/* returns a pointer to the node at the current position.  This is
   meant to be used as a way of "saving" the current position */
dl_node_type *dl_list_get_pos(dl_list_type *list);

/* sets the current position to the node pointed to by 'pos', which
   was probably obtained by dl_list_get_pos(). */
int dl_list_put_pos(dl_list_type *list, dl_node_type *pos);

/* sets the current position to 'pos' while returning the old
   position. */
dl_node_type *dl_list_exchange_pos(dl_list_type *list,
                                   dl_node_type *pos);

/* free()s the node at the current position.  It does not touch the
   node's held data. */
int dl_list_delete_node(dl_list_type *list);

/* free()s the node at the current position.  If the list was
   initialized with a data_destroy function, it will apply that
   function to the node's value. */
int dl_list_delete(dl_list_type *list);

/* deletes the whole list.  It is up to the user to free any indirect
   memory. */
int dl_list_destroy(dl_list_type *list);

/* a basic data destruction routine.  It simply free()s the data, if
   non-null. */
int simple_destroy_data(void *data);

/* a do-nothing destruction routine. */
int null_destroy_data(void *data);

#endif /* _DL_LIST_H_ */

