// iterJava.h   (c) 2009 adolfo@di-mare.com

#ifdef English_dox
/// \file   iterJava.h
/// \brief  Java iterators for C++.
/// \author Adolfo Di Mare <adolfo@di-mare.com>
/// \date   2009
///
/// - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
#endif
#ifdef Spanish_dox
/// \file   iterJava.h
/// \brief  Iteradores Java para C++.
/// \author Adolfo Di Mare <adolfo@di-mare.com>
/// \date   2009
///
/// - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
#endif

#include <iterator> // std::iterator_traits<Iter>

template <typename Iter>
class iterJava { // Iterate using pointers/iterators
protected:
    Iter itPrev;    // Remember last value returned
    Iter itNext;    // Next value to return
    Iter itEnd;     // Past the last value
    bool isFwd;     // false if it is a reverse_iterator
public:
    iterJava( )
        : itPrev(), itNext(), itEnd(), isFwd(true) { }
    iterJava( Iter first , Iter end )
        : itPrev(), itNext(first), itEnd(end), isFwd(true) { }
    iterJava( const iterJava& o )
        : itPrev(o.itPrev), itNext(o.itNext)
        , itEnd (o.itEnd),  isFwd(o.isFwd) { }
    ~iterJava() { }
    iterJava& operator=( const iterJava& o ) {
        itPrev = o.itPrev;   itNext = o.itNext;
        itEnd  = o.itEnd;    isFwd  = o.isFwd;
        return *this;
    }
public:
    bool hasNext() const {
        return ( itNext != itEnd );
    }
    typename std::iterator_traits<Iter>::
    reference next() {
        if (isFwd) {
            itPrev = itNext; itNext++; return *itPrev;
        }
        else {
            itNext--; itPrev = itNext; return *itPrev;
        }
    }
    typename std::iterator_traits<Iter>::
    reference current() const { return ( *itPrev );  }
    operator  Iter()    const { return    itPrev; }
public:
    void set( Iter first , Iter end )
        { itPrev = Iter(); itNext = first; itEnd = end; isFwd = true; }
    template <typename C> void set( C& CCC )
        { set( CCC.begin(), CCC.end() ); }
    template <typename C> void set( const C& CCC )
        { set( CCC.begin(), CCC.end() ); }
    void setReverse()  {
        if ( itPrev==Iter() ) { // didn't start the iteration yet
            itPrev = itEnd;     // swap itNext <==> itEnd
            itEnd  = itNext;
            itNext = itPrev;
        //  itPrev = itNext;    // redundant
            isFwd  = false;
        }
    }
    bool isForward()   const { return  isFwd; }
    bool isReverse()   const { return !isFwd; }
    void setBackward() { setReverse(); }
    bool isBackward()  const { return isReverse(); }
public:
    inline friend
    bool operator== ( const iterJava<Iter>& l , const iterJava<Iter>& r ) {
        return (
            l.itPrev == r.itPrev && l.itNext == r.itNext &&
            l.itEnd  == r.itEnd  && l.isFwd  == r.isFwd    );
        } ///< ( l == r ) ?
    inline friend
    bool operator!= ( const iterJava<Iter>& l , const iterJava<Iter>& r )
        { return !(l==r); } ///< ( l != r ) ?
};

/*************\
|*  Doxygen  *| ==> http://www.doxygen.org
\*************/

#ifdef English_dox
    /// Doxygen English documentation.
    #define English_dox   "Doxygen English documentation"
   /// \def English_dox  ///< Marks English documentation blocks.
#endif
#ifdef Spanish_dox
    /// Documentación en español.
    #define Spanish_dox "Documentación Doxygen en español"
   /// \def Spanish_dox  ///< Marca los bloques de documentación en español.
#endif

#ifdef English_dox
/** \class iterJava;
    \brief An iterator over a collection.
    Iterators differ from enumerations in two ways:
    - Iterators allow the caller to remove elements from the underlying
      collection during the iteration with well-defined semantics.
    - Method names have been improved.
    - In Java, class \c Iterator takes the place of \c Enumeration in the
      Java collections framework.

    \dontinclude test_iterJava.cpp
    \skipline    test::example()
    \until       }}
    \see         test_iterJava::test_example()

    - Both \c const and non-<code>const</code> iterators work as expected.

    \dontinclude test_iterJava.cpp
    \skipline    test::const_example()
    \until       }}
    \see         test_iterJava::test_const_example()

    - On vectors operation \c remove() cannot be used.

    \dontinclude test_iterJava.cpp
    \skipline    test::examplePtr()
    \until       }}
    \see         test_iterJava::test_examplePtr()
*/
#endif
#ifdef Spanish_dox
/** \class iterJava;
    \brief Iterador sobre una colección.
    Los iteradores difieren de las enumeraciones en 2 formas:
    - Los iteradores permiten que el invocador borre valores de la
      colección que se recorre durante la iteración, con semántica bien definida.
    - Los nombres de los métodos han sido mejorados.
    - En Java, la clase \c Iterator toma el lugar de \c Enumeration
      en el marco de trabajo de colecciones (<em>Java collections framework</em>).

    \dontinclude test_iterJava.cpp
    \skipline    test::example()
    \until       }}
    \see         test_iterJava::test_example()

    - Tanto los iteradores \c const como no-<code>const</code> trabajan
      como se espera.

    \dontinclude test_iterJava.cpp
    \skipline    test::const_example()
    \until       }}
    \see         test_iterJava::test_const_example()

    - En vectores la operación \c remove() no puede ser useda.

    \dontinclude test_iterJava.cpp
    \skipline    test::examplePtr()
    \until       }}
    \see         test_iterJava::test_examplePtr()
*/
#endif

#ifdef English_dox
/**
    \brief Remember last value returned.
    \var   iterJava::itPrev;
*/
/**
    \brief Next value to return.
    \var   iterJava::itNext;
*/
/**
    \brief Past the last value.
    \var   iterJava::itEnd;
*/
/**
    \brief \c "false" if it is a \c reverse_iterator.
    \var   iterJava::isFwd;
*/
#endif
#ifdef Spanish_dox
/**
    \brief Recuerda el último valor retornado.
    \var   iterJava::itPrev;
*/
/**
    \brief Siguiente valor por retornar.
    \var   iterJava::itNext;
*/
/**
    \brief Pasado del último valor.
    \var   iterJava::itEnd;
*/
/**
    \brief \c "false" si es un \c reverse_iterator.
    \var   iterJava::isFwd;
*/
#endif

#ifdef English_dox
/**
    \fn    iterJava::iterJava( );
    \brief Default constructor.

    \fn    iterJava::iterJava( Iter first , Iter end );
    \brief Constructor to traverse from \c first up to \c end.

    \fn    iterJava::iterJava( const iterJava& o );
    \brief Copy constructor.

    \fn    iterJava::~iterJava( );
    \brief Destructor.

    \fn    iterJava::operator=( const iterJava& o );
    \brief Copy.

    \dontinclude test_iterJava.cpp
    \skipline    test::assign()
    \until       }}
    \see         test_iterJava::test_assign()
*/
#endif
#ifdef Spanish_dox
/**
    \fn    iterJava::iterJava( );
    \brief Constructor por defecto.

    \fn    iterJava::iterJava( Iter first , Iter end );
    \brief Constructor para recorrer desde \c first y hasta antes de \c end.

    \fn    iterJava::iterJava( const iterJava& o );
    \brief Constructor de copia.

    \fn    iterJava::~iterJava( );
    \brief Destructor.

    \fn    iterJava::operator=( const iterJava& o );
    \brief Copiador.

    \dontinclude test_iterJava.cpp
    \skipline    test::assign()
    \until       }}
    \see         test_iterJava::test_assign()
*/
#endif

#ifdef English_dox
/**
    \fn    iterJava::hasNext() const;
    \brief Returns \c true if the iteration has more elements.
           (In other words, returns \c true if \c next() would return an element
           rather than breaking up.)
    \returns \c true if the iterator has more elements.

    \fn    iterJava::next();
    \brief Returns the next element in the iteration.
           Calling this method repeatedly until the \c hasNext() method returns
           \c false will return each element in the underlying collection exactly once.
    \returns The next element in the iteration.

    \dontinclude test_iterJava.cpp
    \skipline    test::next()
    \until       }}
    \see         test_iterJava::test_next()

    \fn    iterJava::current() const;
    \brief Returns the value that the last invocation to \c next() returned.
           - Calling this method after the iterator was set but before
             the first invocation to \c next() is an error.
    \returns The value that the last invocation to \c next() returned.

    \fn    iterJava::operator Iter() const;
    \brief Converts into an iterator over the underlying collection.

    - This conversion is usefull to remove from the underlaying collection the
      last value returned by \c next().
    - This conversion works both for \c const and non \c const iterations.

    \returns The value that the last invocation to \c next() returned.

    \dontinclude test_iterJava.cpp
    \skipline    test::erase()
    \until       }}
    \see         test_iterJava::test_erase()

*/
#endif
#ifdef Spanish_dox
/**
    \fn    iterJava::hasNext() const;
    \brief Retorna \c true si la iteración tiene más elementos.
           (En otras palabras, retorna \c true si \c next() retornaría un elemento
           en lugar de fallar.)
    \returns \c true si la iteración tiene más elementos.

    \fn    iterJava::next();
    \brief Retorna el siguiente element de la iteración.
           Al invocar este método repetidamente hasta que el método \c hasNext() retorne
           \c false retornará cada elemento de la collección que se recorre exactamente
           una vez.
    \returns El siguiente element de la iteración.

    \dontinclude test_iterJava.cpp
    \skipline    test::next()
    \until       }}
    \see         test_iterJava::test_next()

    \fn    iterJava::current() const;
    \brief Retorna el valor que la última invocación de \c next() retornó.
           - Invocar este método después de que el valor del iterador iterador fue establecido
             pero antes de la primera invocación de \c next() es aun error.
    \returns El valor que la última invocación de \c next() retornó.

    \fn    iterJava::operator Iter() const;
    \brief Convierte el valor en un iterador sobre la colección que se recorre.

    - Este convertidor es útil para eliminar valores de la colección que se recorre
      el último valor que \c next() retornó.
    - La conversión funciona para operaciones \c const y para las que no son \c const.

    \returns El valor que la última invocación de \c next() retornó.

    \dontinclude test_iterJava.cpp
    \skipline    test::erase()
    \until       }}
    \see         test_iterJava::test_erase()
*/
#endif

#ifdef English_dox
/**
    \fn    iterJava::set( Iter first , Iter end );
    \brief Resets the iterator to traverse from \c first up to \c end.

    \fn    iterJava::set( C& CCC );
    \brief Resets the iterator to traverse from \c C.

    \fn    iterJava::set( const C& CCC );
    \brief Resets the iterator to traverse from \c C (\c const version).

    \dontinclude test_iterJava.cpp
    \skipline    test::set_CCC()
    \until       }}
    \see         test_iterJava::test_set_CCC()
*/
#endif
#ifdef Spanish_dox
/**
    \fn    iterJava::set( Iter first , Iter end );
    \brief Establece que la iteración se hará desde \c first hasta antes de \c end.

    \fn    iterJava::set( C& CCC );
    \brief Establece que la iteración se hará sobre  \c C.

    \fn    iterJava::set( const C& CCC );
    \brief Establece que la iteración se hará sobre  \c C ( versión \c const ).

    \dontinclude test_iterJava.cpp
    \skipline    test::set_CCC()
    \until       }}
    \see         test_iterJava::test_set_CCC()
*/
#endif

#ifdef English_dox
/**
    \fn    iterJava::setReverse();
    \brief Sets the iterator to go reverse (backwards).
    \pre   Method \c next() must not be invoked before using \c setReverse().
    \see         isPalindrome();

    \dontinclude test_iterJava.cpp
    \skipline    test::palindrome()
    \until       }}
    \see         test_iterJava::test_palindrome()
    \see         isPalindrome();

    \fn    iterJava::isForward() const;
    \brief Returns \c true if the iteration is natural, from first to last.

    \fn    iterJava::isReverse() const;
    \brief Returns \c true if the iteration goes in reverse (backwards).
           - Only after \c setReverse() is invoked will \c isReverse() return \c true.

    \dontinclude test_iterJava.cpp
    \skipline    test::setReverse()
    \until       }}
    \see         test_iterJava::test_setReverse()

    \fn    iterJava::setBackward();
    \brief Sets the iterator to go reverse (backwards).
    \pre   Method \c next() must not be invoked before using \c setReverse().
           - Handy sinomim for \c setReverse().

    \fn    iterJava::isBackward() const;
    \brief Returns \c true if the iteration goes in reverse (backwards).
           - Only after \c setReverse() is invoked will \c isReverse() return \c true.
           - Handy sinomim for \c isReverse().

    \dontinclude test_iterJava.cpp
    \skipline    test::setReverse()
    \until       }}
    \see         test_iterJava::test_setReverse()
*/
#endif
#ifdef Spanish_dox
/**
    \fn    iterJava::setReverse();
    \brief Establece que el iterador irá hacia atrás, en reversa.
    \pre   No debe invocarse el método \c next() antes de usar \c setReverse().
    \see         isPalindrome();

    \dontinclude test_iterJava.cpp
    \skipline    test::palindrome()
    \until       }}
    \see         test_iterJava::test_palindrome()
    \see         isPalindrome();

    \fn    iterJava::isForward() const;
    \brief Retorna \c true si la iteración es natural, desde el primero al útlimo.

    \fn    iterJava::isReverse() const;
    \brief Retorna \c true si la iteración va hacia atrás, en reversa.
           - Solo después de que \c setReverse() ocurrirá que \c isReverse() retorne \c true.

    \dontinclude test_iterJava.cpp
    \skipline    test::setReverse()
    \until       }}
    \see         test_iterJava::test_setReverse()

    \fn    iterJava::setBackward();
    \brief Establece que el iterador irá hacia atrás, en reversa.
    \pre   No debe invocarse el método \c next() antes de usar \c setBackward().
           - Cómodo sinónimo de \c setReverse().

    \fn    iterJava::isBackward() const;
    \brief Retorna \c true si la iteración va hacia atrás, en reversa.
           - Solo después de que \c setBackward() ocurrirá que \c isBackward() retorne \c true.
           - Cómodo sinónimo de \c isReverse().

    \dontinclude test_iterJava.cpp
    \skipline    test::setReverse()
    \until       }}
    \see         test_iterJava::test_setReverse()
*/
#endif

#ifdef English_dox
#endif
#ifdef Spanish_dox
#endif

// EOF: iterJava.h
