Sierra Toolkit Version of the Day
nested_iterator.hpp
00001 #ifndef STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
00002 #define STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
00003 
00004 #include <boost/range.hpp>
00005 #include <boost/iterator.hpp>
00006 #include <boost/optional.hpp>
00007 
00008 #include <boost/mpl/assert.hpp>
00009 #include <boost/type_traits.hpp>
00010 
00011 namespace stk {
00012 namespace util {
00013 
00035 template <typename OuterIterator,
00036           typename InnerIterator,
00037           typename OuterValueToInnerRange
00038          >
00039 class nested_iterator
00040   : public boost::iterator_facade<
00041         nested_iterator<OuterIterator,InnerIterator,OuterValueToInnerRange>
00042       , typename boost::iterator_value<InnerIterator>::type //value
00043       , boost::forward_traversal_tag // traversal tag
00044     >
00045 {
00046   public:
00047     typedef OuterIterator outer_iterator;
00048     typedef InnerIterator inner_iterator;
00049     typedef OuterValueToInnerRange outer_value_to_inner_range;
00050 
00051     typedef boost::iterator_range<outer_iterator> outer_range_type;
00052     typedef boost::iterator_range<inner_iterator> inner_range_type;
00053 
00054   private:
00055     typedef nested_iterator<outer_iterator,inner_iterator,outer_value_to_inner_range> self;
00056 
00057     typedef typename  boost::iterator_value<outer_iterator>::type outer_value;
00058     typedef typename outer_value_to_inner_range::value_type converter_value;
00059     typedef typename outer_value_to_inner_range::result_type converter_result;
00060 
00061     BOOST_MPL_ASSERT_MSG(
00062         ( boost::is_convertible<
00063             outer_value,
00064             converter_value
00065           >::value
00066         ),
00067         NO_CONVERSION_FOUND,
00068         (
00069          outer_value,
00070          converter_value
00071         )
00072     );
00073 
00074     BOOST_MPL_ASSERT_MSG(
00075         ( boost::is_convertible<
00076             converter_result,
00077             inner_range_type
00078           >::value
00079         ),
00080         NO_CONVERSION_FOUND,
00081         ( converter_result,
00082           inner_range_type
00083         )
00084     );
00085 
00086 
00087   public:
00088     nested_iterator()
00089       : m_outer_current()
00090       , m_outer_end()
00091       , m_inner_current()
00092       , m_inner_end()
00093       , m_converter()
00094     {}
00095 
00096     nested_iterator( const outer_range_type & outer_range, const outer_value_to_inner_range converter )
00097       : m_outer_current(boost::begin(outer_range))
00098       , m_outer_end(boost::end(outer_range))
00099       , m_inner_current()
00100       , m_inner_end()
00101       , m_converter(converter)
00102     {
00103       if ( boost::empty(outer_range) ) {
00104         m_outer_current = boost::none;
00105         m_outer_end     = boost::none;
00106       }
00107       else {
00108         find_inner_range_helper();
00109       }
00110 
00111 
00112     }
00113 
00114     //
00115   private:
00116     friend class boost::iterator_core_access;
00117 
00118     //functions necessary to implement core operations
00119     // increment
00120     // equal
00121     // dereference
00122 
00123     void increment()
00124     {
00125       if (m_inner_current) {
00126         ++(*m_inner_current);
00127         //at end of current inner range
00128         if (m_inner_current == m_inner_end) {
00129           ++(*m_outer_current);
00130           find_inner_range_helper();
00131         }
00132       }
00133     }
00134 
00135     bool equal( const self & rhs ) const
00136     {
00137       return    (m_outer_current == rhs.m_outer_current)
00138              && (m_inner_current == rhs.m_inner_current);
00139     }
00140 
00141     typename boost::iterator_reference<inner_iterator>::type dereference() const
00142     {
00143       return **m_inner_current;
00144     }
00145 
00146     void find_inner_range_helper()
00147     {
00148       // find the next none-empty inner_range
00149       while ( (m_outer_current != m_outer_end) &&
00150                boost::empty((*m_converter)(**m_outer_current)) )
00151       {
00152         ++(*m_outer_current);
00153       }
00154 
00155       if (m_outer_current != m_outer_end) {
00156         m_inner_current = boost::begin((*m_converter)(**m_outer_current));
00157         m_inner_end = boost::end((*m_converter)(**m_outer_current));
00158       }
00159       else { //at end of outer range
00160         m_outer_current = boost::none;
00161         m_outer_end = boost::none;
00162 
00163         m_inner_current = boost::none;
00164         m_inner_end = boost::none;
00165       }
00166     }
00167 
00168 
00169   private:
00170     boost::optional<outer_iterator> m_outer_current;
00171     boost::optional<outer_iterator> m_outer_end;
00172 
00173     boost::optional<inner_iterator> m_inner_current;
00174     boost::optional<inner_iterator> m_inner_end;
00175 
00176     boost::optional<outer_value_to_inner_range> m_converter;
00177 };
00178 
00179 
00180 } // util
00181 } // stk
00182 
00183 
00184 #endif //STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends