|
Sierra Toolkit
Version of the Day
|
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_classic { 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