/*-----------------------------------------------------------------------------+ Copyright (c) 2009-2009: Joachim Faulhaber +------------------------------------------------------------------------------+ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENCE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +-----------------------------------------------------------------------------*/ #ifndef BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104 #define BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104 #include #include #include #include namespace boost{namespace icl { //------------------------------------------------------------------------------ template struct is_std_pair { typedef is_std_pair type; BOOST_STATIC_CONSTANT(bool, value = false); }; template struct is_std_pair > { typedef is_std_pair > type; BOOST_STATIC_CONSTANT(bool, value = true); }; //------------------------------------------------------------------------------ template struct first_element { typedef Type type; }; template struct first_element > { typedef FirstT type; }; //------------------------------------------------------------------------------ template class element_iterator; template struct is_reverse { typedef is_reverse type; BOOST_STATIC_CONSTANT(bool, value = false); }; template struct is_reverse > { typedef is_reverse > type; BOOST_STATIC_CONSTANT(bool, value = true); }; template struct is_reverse > { typedef is_reverse > type; BOOST_STATIC_CONSTANT(bool, value = is_reverse::value); }; //------------------------------------------------------------------------------ template struct elemental; #ifdef ICL_USE_INTERVAL_TEMPLATE_TEMPLATE template struct elemental { typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type; typedef segment_type interval_type; typedef DomainT type; typedef DomainT domain_type; typedef DomainT codomain_type; typedef DomainT transit_type; }; template< class DomainT, class CodomainT, ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval > struct elemental > { typedef std::pair segment_type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type; typedef std::pair type; typedef DomainT domain_type; typedef CodomainT codomain_type; typedef mapped_reference transit_type; }; #else //ICL_USE_INTERVAL_TEMPLATE_TYPE template struct elemental { typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type; typedef segment_type interval_type; typedef typename interval_traits::domain_type domain_type; typedef domain_type type; typedef domain_type codomain_type; typedef domain_type transit_type; }; template< class CodomainT, ICL_INTERVAL(ICL_COMPARE) Interval > struct elemental > { typedef std::pair segment_type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type; typedef typename interval_traits::domain_type domain_type; typedef CodomainT codomain_type; typedef std::pair type; typedef mapped_reference transit_type; }; #endif //ICL_USE_INTERVAL_TEMPLATE_TEMPLATE //------------------------------------------------------------------------------ //- struct segment_adapter //------------------------------------------------------------------------------ template struct segment_adapter; #ifdef ICL_USE_INTERVAL_TEMPLATE_TEMPLATE template struct segment_adapter { typedef segment_adapter type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type; typedef segment_type interval_type; typedef typename interval_type::difference_type domain_difference_type; typedef DomainT domain_type; typedef DomainT codomain_type; typedef domain_type element_type; typedef domain_type& transit_type; static domain_type first (const SegmentIteratorT& leaper){ return leaper->first(); } static domain_type last (const SegmentIteratorT& leaper){ return leaper->last(); } static domain_difference_type length(const SegmentIteratorT& leaper){ return leaper->length();} static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper, const domain_difference_type& sneaker) { inter_pos = is_reverse::value ? leaper->last() - sneaker : leaper->first() + sneaker; return inter_pos; } }; template < class SegmentIteratorT, class DomainT, class CodomainT, ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval > struct segment_adapter > { typedef segment_adapter type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type; typedef DomainT domain_type; typedef std::pair element_type; typedef CodomainT codomain_type; typedef mapped_reference transit_type; typedef typename difference_type_of >::type domain_difference_type; static domain_type first (const SegmentIteratorT& leaper){ return leaper->first.first(); } static domain_type last (const SegmentIteratorT& leaper){ return leaper->first.last(); } static domain_difference_type length(const SegmentIteratorT& leaper){ return leaper->first.length();} static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper, const domain_difference_type& sneaker) { inter_pos = is_reverse::value ? leaper->first.last() - sneaker : leaper->first.first() + sneaker; return transit_type(inter_pos, leaper->second); } }; #else // ICL_USE_INTERVAL_TEMPLATE_TYPE template struct segment_adapter { typedef segment_adapter type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type; typedef segment_type interval_type; typedef typename interval_traits::domain_type domain_type; typedef domain_type codomain_type; typedef domain_type element_type; typedef domain_type& transit_type; typedef typename difference_type_of >::type domain_difference_type; static domain_type first (const SegmentIteratorT& leaper){ return leaper->first(); } static domain_type last (const SegmentIteratorT& leaper){ return leaper->last(); } static domain_difference_type length(const SegmentIteratorT& leaper){ return icl::length(*leaper);} static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper, const domain_difference_type& sneaker) { inter_pos = is_reverse::value ? icl::last(*leaper) - sneaker : icl::first(*leaper) + sneaker; return inter_pos; } }; template < class SegmentIteratorT, class CodomainT, ICL_INTERVAL(ICL_COMPARE) Interval > struct segment_adapter > { typedef segment_adapter type; typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type; typedef typename interval_traits::domain_type domain_type; typedef CodomainT codomain_type; typedef std::pair element_type; typedef mapped_reference transit_type; typedef typename difference_type_of >::type domain_difference_type; static domain_type first (const SegmentIteratorT& leaper){ return leaper->first.first(); } static domain_type last (const SegmentIteratorT& leaper){ return leaper->first.last(); } static domain_difference_type length(const SegmentIteratorT& leaper){ return icl::length(leaper->first);} static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper, const domain_difference_type& sneaker) { inter_pos = is_reverse::value ? icl::last(leaper->first) - sneaker : icl::first(leaper->first) + sneaker; return transit_type(inter_pos, leaper->second); } }; #endif // ICL_USE_INTERVAL_TEMPLATE_TEMPLATE template class element_iterator : public boost::iterator_facade< element_iterator , typename elemental::transit_type , boost::bidirectional_traversal_tag , typename elemental::transit_type > { public: typedef element_iterator type; typedef SegmentIteratorT segment_iterator; typedef typename SegmentIteratorT::value_type segment_type; typedef typename first_element::type interval_type; typedef typename elemental::type element_type; typedef typename elemental::domain_type domain_type; typedef typename elemental::codomain_type codomain_type; typedef typename elemental::transit_type transit_type; typedef transit_type value_type; typedef typename difference_type_of >::type domain_difference_type; private: typedef typename segment_adapter::type adapt; struct enabler{}; public: element_iterator() : _saltator(identity_element::value()) , _reptator(identity_element::value()){} explicit element_iterator(segment_iterator jumper) : _saltator(jumper), _reptator(identity_element::value()) {} template element_iterator ( element_iterator const& other , typename enable_if, enabler>::type = enabler()) : _saltator(other._saltator), _reptator(other._reptator) {} private: friend class boost::iterator_core_access; template friend class element_iterator; template bool equal(element_iterator const& other) const { return this->_saltator == other._saltator && this->_reptator == other._reptator; } void increment() { if(_reptator < icl::pred(adapt::length(_saltator))) ++_reptator; else { ++_saltator; _reptator = identity_element::value(); } } void decrement() { if(identity_element::value() < _reptator) --_reptator; else { --_saltator; _reptator = adapt::length(_saltator); --_reptator; } } value_type dereference()const { return adapt::transient_element(_inter_pos, _saltator, _reptator); } private: segment_iterator _saltator; // satltare: to jump : the fast moving iterator mutable domain_difference_type _reptator; // reptare: to sneak : the slow moving iterator 0 based mutable domain_type _inter_pos; // inter position : Position within the current segment // _saltator->first.first() <= _inter_pos <= _saltator->first.last() }; }} // namespace icl boost #endif // BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104