/*******************************************************************************
+
+  LEDA 3.5
+
+  iteration.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef LEDA_ITERATION_H
#define LEDA_ITERATION_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350067
#include <LEDA/REDEFINE_NAMES.h>
#endif



//------------------------------------------------------------------------------
//   forall_items(it,...)
//   forall_rev_items(it,...)
//------------------------------------------------------------------------------

#define forall_items(x,S)\
for(x = (S).first_item(); x; x = (S).next_item(x) )

#define forall_rev_items(x,S)\
for(x = (S).last_item(); x; x = (S).pred_item(x) )


//------------------------------------------------------------------------------
//   forall(x,...)
//   forall_rev(x,...)   (Forall)
//   forall_defined(x,...)
//------------------------------------------------------------------------------

// As long as the new scoping rules are not supported we avoid multiple 
// declarations of the forall-loop variable by placing it in the else 
// part of a dummy if-statement. 


#if defined(__GNUC__) || defined(__ELSE_SCOPE_BUG__)
#define LEDA_FORALL_PREAMBLE
#define for_loop_cat(x,y) x ## y 
#define for_loop_var(y) for_loop_cat(for_loop_var,y)
#else
#define LEDA_FORALL_PREAMBLE  if (0); else
#define for_loop_var(y) for_loop_var
#endif


#define forall(x,S)\
LEDA_FORALL_PREAMBLE \
for(GenPtr for_loop_var(__LINE__) = (S).first_item();\
(S).forall_loop_test(for_loop_var(__LINE__),x);\
(S).loop_to_succ(for_loop_var(__LINE__)))

#define forall_rev(x,S)\
LEDA_FORALL_PREAMBLE \
for(GenPtr for_loop_var(__LINE__) = (S).last_item();\
(S).forall_loop_test(for_loop_var(__LINE__),x);\
(S).loop_to_pred(for_loop_var(__LINE__)))

#define forall_defined(x,S)\
LEDA_FORALL_PREAMBLE \
for(GenPtr for_loop_var(__LINE__) = (S).first_item();\
(S).forall_defined_test(for_loop_var(__LINE__),x);\
(S).loop_to_succ(for_loop_var(__LINE__)))


// historical
#define Forall forall_rev


// work-around for ztc
#if defined(__ZTC__)
extern GenPtr global_for_loop_var;
#undef forall
#define forall(x,S)\
for(global_for_loop_var = (S).first_item();\
(S).forall_loop_test(global_for_loop_var,x);\
(S).loop_to_succ(global_for_loop_var))
#endif


// Macros for generating STL iterators

#define STL_ITERATORS(DTYPE,ITYPE,ETYPE)\
class iterator {\
  friend class DTYPE;\
  DTYPE* L;\
  ITYPE it;\
  iterator(DTYPE* x, ITYPE y) : L(x), it(y)  {}\
public:\
 iterator() : L(0),it(0)   {}\
 iterator& operator++()    { it = L->next_item(it); return *this; }\
 iterator& operator--()    { it = L->pred_item(it); return *this; }\
 iterator  operator++(int) { iterator tmp = *this; ++(*this); return tmp; }\
 iterator  operator--(int) { iterator tmp = *this; --(*this); return tmp; }\
 ETYPE& operator*() const { return (*L)[it]; }\
 friend bool operator==(const iterator& x, const iterator& y)\
 { return x.it == y.it; }\
/* friend bool operator!=(const iterator& x, const iterator& y)\
 { return x.it != y.it; } */\
 operator ITYPE() { return it; }\
 friend ETYPE* value_type(const iterator&) { return (ETYPE*)0; }\
};\
iterator  begin() { return iterator(this,first_item());}\
iterator  end()   { return iterator(this,next_item(last_item()));  }\
\
class const_iterator {\
  friend class DTYPE;\
  const DTYPE* L;\
  ITYPE it;\
  const_iterator(const DTYPE* x, ITYPE y) : L(x), it(y)  {}\
public:\
 const_iterator() : L(0),it(0)   {}\
 const_iterator& operator++()    { it = L->next_item(it); return *this; }\
 const_iterator& operator--()    { it = L->pred_item(it); return *this; }\
 const_iterator  operator++(int) { const_iterator tmp = *this; ++(*this); return tmp; }\
 const_iterator  operator--(int) { const_iterator tmp = *this; --(*this); return tmp; }\
 const ETYPE& operator*() const { return (*L)[it]; }\
 friend bool operator==(const const_iterator& x, const const_iterator& y) \
 { return x.it == y.it; }\
/* friend bool operator!=(const const_iterator& x, const const_iterator& y) \
 { return x.it != y.it; } */\
 operator ITYPE() { return it; }\
 friend ETYPE* value_type(const const_iterator&) { return (ETYPE*)0; }\
};\
const_iterator begin() const { return const_iterator(this,first_item()); }\
const_iterator end()   const { return const_iterator(this,next_item(last_item()));   }


#if LEDA_ROOT_INCL_ID == 350067
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif

#endif
