/* Linked lists.
 *
 * J.Cupitt, 8/4/93.
 */

/*

    This file is part of VIPS.
    
    VIPS is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 */

/*

    These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk

 */

#ifndef IM_LIST_H
#define IM_LIST_H

#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/

/* List type.
 */
typedef struct list_type {
	struct list_type *next;
	void *data;
} List;

/* Macros.
 */
#define hd(L) ((L)->data)
#define tl(L) ((L)->next)

/* Type of functions we map over lists.
 */
typedef void *(*im_list_map_fn)( void *, void *, void * );
typedef void *(*im_list_fold_fn)( void *, void *, void *, void * );
typedef void (*im_list_free_fn)( void *, void *, void * );

/* Length of list.
 */
int im_list_len( List *l );

/* Position of item in list. Index from zero, -1 for not present.
 */
int im_list_pos( List *l, void *t );

/* Non-zero if list contains element.
 */
int im_list_member( List *l, void *t );

/* Return the object at index n in a list. Index from 0. NULL for index out 
 * of range.
 */
void *im_list_index( List *l, int n );

/* Test two void * pointers for equality, returning the pointer if equal and
 * NULL if not equal. With im_list_map, makes a list search function.
 */
void *im_list_eq( void *a, void *b );

/* Apply fn to every element in the List. If fn returns NULL, keep looking. If
 * it returns non-NULL, stop and return that value. If we reach the end of the
 * list, return NULL.
 */
void *im_list_map( List *l, im_list_map_fn fn, void *a, void *b );

/* As above, but map in reverse order. This is much slower!
 */
void *im_list_map_rev( List *l, im_list_map_fn fn, void *a, void *b );

/* Fold up a list. If a list has [1,2], return fn( 2, fn( 1, start ) ).
 */
void *im_list_fold( List *l, 
	void *start, im_list_fold_fn fn, void *a, void *b );

/* Repeatedly map a function over a list, until the map returns NULL. The
 * function can alter the list safely.
 */
void im_list_fix( List **base, im_list_map_fn fn, void *a, void *b );

/* Add new to the head of the list.
 */
int im_list_add( List **base, void *data );

/* Insert a new element in a list before an object already there. 
 */
int im_list_insert( List **base, void *data, void *old );

/* Add new to the end of the list.
 */
int im_list_append( List **base, void *data );

/* Remove t from the list.
 */
int im_list_remove( List **base, void *t );

/* Free the list, applying a user free function to every node as we free it.
 */
void im_list_free( List **base, im_list_free_fn fn, void *a, void *b );

#ifdef __cplusplus
}
#endif /*__cplusplus*/

#endif /*IM_LIST_H*/
