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/mpl/logical.hpp>
00010 #include <boost/type_traits.hpp>
00011 #include <boost/utility/enable_if.hpp>
00012 
00013 namespace stk {
00014 namespace util {
00015 
00024 template <typename OuterRange,
00025           typename InnerRange,
00026           typename OuterToInnerConverter
00027          >
00028 class nested_iterator
00029   : public boost::iterator_facade<
00030         nested_iterator<OuterRange,InnerRange,OuterToInnerConverter>
00031       , typename boost::range_value<InnerRange>::type //value
00032       , boost::forward_traversal_tag // traversal tag
00033     >
00034 {
00035   public:
00036     typedef typename boost::range_iterator<OuterRange>::type outer_iterator;
00037     typedef typename boost::range_iterator<InnerRange>::type inner_iterator;
00038 
00039     typedef OuterRange outer_range_type;
00040     typedef InnerRange inner_range_type;
00041 
00042     typedef OuterToInnerConverter converter_type;
00043 
00044   private:
00045     typedef nested_iterator<outer_range_type,inner_range_type,converter_type> self;
00046 
00047     typedef typename  boost::range_value<outer_range_type>::type outer_value;
00048 
00049 
00050   public:
00051     nested_iterator()
00052       : m_outer_current()
00053       , m_outer_end()
00054       , m_inner_current()
00055       , m_inner_end()
00056       , m_converter()
00057     {}
00058 
00059     nested_iterator( outer_range_type & outer_range, converter_type converter = converter_type() )
00060       : m_outer_current(boost::begin(outer_range))
00061       , m_outer_end(boost::end(outer_range))
00062       , m_inner_current()
00063       , m_inner_end()
00064       , m_converter(converter)
00065     {
00066       if ( boost::empty(outer_range) ) {
00067         m_outer_current = boost::none;
00068         m_outer_end     = boost::none;
00069       }
00070       else {
00071         find_inner_range_helper();
00072       }
00073     }
00074 
00075     friend class nested_iterator<typename boost::add_const<outer_range_type>::type,
00076                                  inner_range_type,converter_type>;
00077 
00078 
00079     //
00080   private:
00081     friend class boost::iterator_core_access;
00082 
00083     //functions necessary to implement core operations
00084     // increment
00085     // equal
00086     // dereference
00087 
00088     void increment()
00089     {
00090       if (m_inner_current) {
00091         ++(*m_inner_current);
00092         //at end of current inner range
00093         if (m_inner_current == m_inner_end) {
00094           ++(*m_outer_current);
00095           find_inner_range_helper();
00096         }
00097       }
00098     }
00099 
00100     bool equal( const self & rhs ) const
00101     {
00102       return    (m_outer_current == rhs.m_outer_current)
00103              && (m_inner_current == rhs.m_inner_current);
00104     }
00105 
00106     typename boost::iterator_reference<inner_iterator>::type dereference() const
00107     {
00108       return **m_inner_current;
00109     }
00110 
00111     void find_inner_range_helper()
00112     {
00113       // find the next none-empty inner_range
00114       while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
00115       {
00116         ++(*m_outer_current);
00117       }
00118 
00119       if (m_outer_current != m_outer_end) {
00120         m_inner_current = boost::begin((*m_converter)(**m_outer_current));
00121         m_inner_end = boost::end((*m_converter)(**m_outer_current));
00122       }
00123       else { //at end of outer range
00124         m_outer_current = boost::none;
00125         m_outer_end = boost::none;
00126 
00127         m_inner_current = boost::none;
00128         m_inner_end = boost::none;
00129       }
00130     }
00131 
00132 
00133   private:
00134     boost::optional<outer_iterator> m_outer_current;
00135     boost::optional<outer_iterator> m_outer_end;
00136 
00137     boost::optional<inner_iterator> m_inner_current;
00138     boost::optional<inner_iterator> m_inner_end;
00139 
00140     boost::optional<converter_type> m_converter;
00141 };
00142 
00143 template <typename OuterRange,
00144           typename InnerRange,
00145           typename OuterToInnerConverter
00146          >
00147 class nested_iterator<const OuterRange, InnerRange,OuterToInnerConverter>
00148   : public boost::iterator_facade<
00149         nested_iterator<const OuterRange,InnerRange,OuterToInnerConverter>
00150       , typename boost::add_const<typename boost::range_value<const InnerRange>::type>::type //value
00151       , boost::forward_traversal_tag // traversal tag
00152     >
00153 {
00154   public:
00155     typedef typename boost::range_iterator<const OuterRange>::type outer_iterator;
00156     typedef typename boost::range_iterator<const InnerRange>::type inner_iterator;
00157 
00158     typedef const OuterRange outer_range_type;
00159     typedef InnerRange inner_range_type;
00160 
00161     typedef OuterToInnerConverter converter_type;
00162 
00163   private:
00164     typedef nested_iterator<outer_range_type,inner_range_type,converter_type> self;
00165 
00166     typedef typename  boost::range_value<outer_range_type>::type outer_value;
00167 
00168 
00169   public:
00170     nested_iterator()
00171       : m_outer_current()
00172       , m_outer_end()
00173       , m_inner_current()
00174       , m_inner_end()
00175       , m_converter()
00176     {}
00177 
00178     nested_iterator( outer_range_type & outer_range, converter_type converter = converter_type() )
00179       : m_outer_current(boost::begin(outer_range))
00180       , m_outer_end(boost::end(outer_range))
00181       , m_inner_current()
00182       , m_inner_end()
00183       , m_converter(converter)
00184     {
00185       if ( boost::empty(outer_range) ) {
00186         m_outer_current = boost::none;
00187         m_outer_end     = boost::none;
00188       }
00189       else {
00190         find_inner_range_helper();
00191       }
00192     }
00193 
00194     nested_iterator( nested_iterator<typename boost::remove_const<outer_range_type>::type,
00195                                      inner_range_type,converter_type> const & itr)
00196       : m_outer_current(itr.m_outer_current)
00197       , m_outer_end(itr.m_outer_end)
00198       , m_inner_current(itr.m_inner_current)
00199       , m_inner_end(itr.m_inner_end)
00200       , m_converter(itr.m_converter)
00201     {}
00202    
00203     //
00204   private:
00205     friend class boost::iterator_core_access;
00206 
00207     //functions necessary to implement core operations
00208     // increment
00209     // equal
00210     // dereference
00211 
00212     void increment()
00213     {
00214       if (m_inner_current) {
00215         ++(*m_inner_current);
00216         //at end of current inner range
00217         if (m_inner_current == m_inner_end) {
00218           ++(*m_outer_current);
00219           find_inner_range_helper();
00220         }
00221       }
00222     }
00223 
00224     bool equal( const self & rhs ) const
00225     {
00226       return    (m_outer_current == rhs.m_outer_current)
00227              && (m_inner_current == rhs.m_inner_current);
00228     }
00229 
00230     typename boost::iterator_reference<inner_iterator>::type dereference() const
00231     {
00232       return **m_inner_current;
00233     }
00234 
00235     void find_inner_range_helper()
00236     {
00237       // find the next none-empty inner_range
00238       while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
00239       {
00240         ++(*m_outer_current);
00241       }
00242 
00243       if (m_outer_current != m_outer_end) {
00244         m_inner_current = boost::begin((*m_converter)(**m_outer_current));
00245         m_inner_end = boost::end((*m_converter)(**m_outer_current));
00246       }
00247       else { //at end of outer range
00248         m_outer_current = boost::none;
00249         m_outer_end = boost::none;
00250 
00251         m_inner_current = boost::none;
00252         m_inner_end = boost::none;
00253       }
00254     }
00255 
00256   private:
00257     boost::optional<outer_iterator> m_outer_current;
00258     boost::optional<outer_iterator> m_outer_end;
00259 
00260     boost::optional<inner_iterator> m_inner_current;
00261     boost::optional<inner_iterator> m_inner_end;
00262 
00263     boost::optional<converter_type> m_converter;
00264 };
00265 
00266 
00267 } // util
00268 } // stk
00269 
00270 
00271 #endif //STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends