/**\file n_list.h
 *  Pointer list structures and definitions
 *\author Castagnier Mickaël
 *\version 1.0
 *\date 24/04/13
 */

#ifndef N_GENERIC_LIST
#define N_GENERIC_LIST

#ifdef __cplusplus
extern "C"
{
#endif

/**\defgroup LIST LIST: generic type list
   \addtogroup LIST 
  @{
*/

#include "stdio.h"
#include "stdlib.h"
#include "n_log.h"
#include "n_common.h"

   /*! Structure of a generic list node */
   typedef struct LIST_NODE
   {
      /*! void pointer to store */
      void *ptr ;

      /*! pointer to destructor function if any, else NULL */
      void (*destroy_func)(void *ptr );

      /*! pointer to the next node */
      struct LIST_NODE *next ;
      /*! pointer to the previous node */
      struct LIST_NODE *prev ;

   } LIST_NODE ;



   /*! Structure of a generic LIST container */
   typedef struct LIST
   {
      /*! number of item currently in the list */
      int nb_items ;
      /*! maximum number of item in the list. Unlimited 0 or negative */
      int nb_max_items ;

      /*! pointer to the start of the list */
      LIST_NODE *start ;
      /*! pointer to the end of the list */
      LIST_NODE *end ;

   } LIST ;



   /*! Macro helper for linking two nodes */
#define link_node( __NODE_1 , __NODE_2 ) \
   do \
   { \
      __NODE_2 -> prev = __NODE_1 ; \
      __NODE_1 -> next = __NODE_2 ; \
   } \
   while( 0 )

   /*! ForEach macro helper */
#define list_foreach( __ITEM_ , __LIST_  ) \
   if( !__LIST_ ) \
   { \
      n_log( LOG_ERR , "Error in list_foreach, %s is NULL" , #__LIST_ ); \
   } \
   else \
   for( LIST_NODE *__ITEM_ = __LIST_ -> start ; __ITEM_ != NULL; __ITEM_ = __ITEM_ -> next ) \

   /*! Pop macro helper for void pointer casting */
#define list_pop( __LIST_ , __TYPE_ ) ( __TYPE_ *)list_pop_f( __LIST_ )
   /*! Shift macro helper for void pointer casting */
#define list_shift( __LIST_ , __TYPE_ ) (__TYPE_ *)list_shift_f( __LIST_ ) 
   /*! Remove macro helper for void pointer casting */
#define remove_list_node( __LIST_ ,__NODE_ , __TYPE_ ) (__TYPE_ *)remove_list_node_f( __LIST_ , __NODE_ ) 

   /* initialize a list */    
   LIST *new_generic_list( int max_items );
   /* create a new node */
   LIST_NODE *new_list_node( void *ptr , void (*destructor)( void *ptr ) );
   /* remove a node */
   void *remove_list_node_f( LIST *list , LIST_NODE *node );

   /* add a pointer at the end of the list */
   int list_push( LIST *list , void *ptr , void (*destructor)( void *ptr ) ) ;
   /* add a pointer sorted via comparator from the end of the list */
   int list_push_sorted( LIST *list , void *ptr , int (*comparator)( const void *a , const void *b ) , void (*destructor)( void *ptr ) );
   /* put a pointer at the beginning of list */
   int list_unshift( LIST *list , void *ptr , void (*destructor)( void *ptr ) );
   /* put a point pointer sorted via comparator from the start to the end */
   int list_unshift_sorted( LIST *list , void *ptr , int (*comparator)( void *a , void *b ) , void (*destructor)( void *ptr ) );

   /* get last ptr from list */
   void *list_pop_f( LIST *list ) ;
   /* get first ptr from list */
   void *list_shift_f( LIST *list );

   /* empty the list */
   int list_empty( LIST *list );
   int list_empty_with_f( LIST *list , void (*free_fnct)( void *ptr ) );
   /* free the list */
   int list_destroy( LIST **list );

/*@}*/   
   
#ifdef __cplusplus
}
#endif

#endif
