/* list.h: generieke lineaire lijsten */

#ifndef _LIST_H_
#define _LIST_H_

typedef struct LIST {
	void 	*pelement;		/* pointer naar een element */
	struct LIST *next;	/* pointer naar de rest van de lijst */
} LIST;

/* creeert een lege lijst */
#ifdef NOLISTMACROS
extern LIST *ListCreate(void);
#else /*NOLISTMACROS*/
#define ListCreate()  ((LIST *)NULL)
#endif /*NOLISTMACROS*/

/* voeg een element toe aan de lijst, geef de wijzer naar de nieuwe lijst 
 * terug */
extern LIST *ListAdd(LIST *list, void *element);

/* telt het aantal elements in de lijst */
extern int ListCount(LIST *list);

/* geeft het index-ste element uit de lijst terug of NULL als er
 * geen index elementen in de lijst zijn. index telt vanaf 0. */
extern void *ListGet(LIST *list, int index);

/* het eerste argument is het adres van een LIST *. 
 * Aanvankelijk moet deze LIST * naar het begin van een lijst wijzen.
 * Bij herhaaldelijke oproepen zal de lijst doorlopen worden.
 * De functie geeft bij herhaaldelijk oproepen een na een alle
 * elementen van de lijst terug. Indien de lijst doorlopen is,
 * wordt een NULL wijzer teruggegeven */
#ifdef NOLISTMACROS
extern void *ListNext(LIST **list);
#else /*NOLISTMACROS*/
extern void *__plistel__;
#define ListNext(plist)	((*(plist)) ? (__plistel__=(*(plist))->pelement, (*(plist))=(*(plist))->next, __plistel__) : (void *)NULL)
#endif /*NOLISTMACROS*/

/* voegt twee lijsten samen: de elementen van lijst list2 komen voor de elementen van 
 * lijst list1. Een wijzer naar de verlengde lijst list1 wordt teruggegeven. */
extern LIST *ListMerge(LIST *list1, LIST *list2);

/* dupliceert een lijst: de elementen zelf worden niet gedupliceerd */
extern LIST *ListDuplicate(LIST *list);

/* verwijdert een element uit de lijst. Geeft een pointer naar de gewijzigde 
 * lijst terug */
extern LIST *ListRemove(LIST *list, void *pelement);

/* iterator: voer de procedure uit vooral alle elementen van de lijst.
 * De procedure heeft als argument een wijzer naar een element */

#ifdef NOLISTMACROS
extern void ListIterate(LIST *list, void (*proc)(void *));
#else /*NOLISTMACROS*/
#define ListIterate(list, proc)						\
{									\
	LIST *_list = (list);						\
	void *pelement;							\
	while (_list) {							\
		pelement = _list->pelement;				\
		_list = _list->next;					\
		((void (*)(void *))proc)(pelement);			\
	}								\
}
#endif /*NOLISTMACROS*/

/* iterator: voer de procedure uit vooral alle elementen van de lijst.
 * De procedure heeft twee argumenten: eerst een wijzer naar
 * het element, dan een wijzer naar andere data de gelijk is voor alle
 * elementen */
#ifdef NOLISTMACROS
extern void ListIterate1A(LIST *list, void (*proc)(void *, void *), void *extra);
#else /*NOLISTMACROS*/
#define ListIterate1A(list, proc, extra)				\
{									\
	LIST *_list = (list);						\
	void *pelement;							\
	while (_list) {							\
		pelement = _list->pelement;				\
		_list = _list->next;					\
		((void (*)(void *, void *))proc)(pelement, (void *)(extra));\
	}								\
}
#endif /*NOLISTMACROS*/

/* iterator: voer de procedure uit vooral alle elementen van de lijst.
 * De procedure heeft twee argumenten: eerst een wijzer naar
 * data die gelijk is voor alle elementen, dan een wijzer naar het element */
#ifdef NOLISTMACROS
extern void ListIterate1B(LIST *list, void (*proc)(void *, void *), void *extra);
#else /*NOLISTMACROS*/
#define ListIterate1B(list, proc, extra)				\
{									\
	LIST *_list = (list);						\
	void *pelement;							\
	while (_list) {							\
		pelement = _list->pelement;				\
		_list = _list->next;					\
		((void (*)(void *, void *))proc)((void *)(extra), pelement);\
	}								\
}
#endif /*NOLISTMACROS*/

/* een volledige lijst vernietigen: vernietigt niet de elementen! */
extern void ListDestroy(LIST *list);

#endif /* _LIST_H_ */

