1 #ifndef STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP 2 #define STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP 4 #include <boost/range.hpp> 5 #include <boost/iterator.hpp> 6 #include <boost/optional.hpp> 8 #include <boost/mpl/assert.hpp> 9 #include <boost/mpl/logical.hpp> 10 #include <boost/type_traits.hpp> 11 #include <boost/utility/enable_if.hpp> 24 template <
typename OuterRange,
26 typename OuterToInnerConverter
29 :
public boost::iterator_facade<
30 nested_iterator<OuterRange,InnerRange,OuterToInnerConverter>
31 , typename boost::range_value<InnerRange>::type
32 , boost::forward_traversal_tag
36 typedef typename boost::range_iterator<OuterRange>::type outer_iterator;
37 typedef typename boost::range_iterator<InnerRange>::type inner_iterator;
39 typedef OuterRange outer_range_type;
40 typedef InnerRange inner_range_type;
42 typedef OuterToInnerConverter converter_type;
47 typedef typename boost::range_value<outer_range_type>::type outer_value;
59 nested_iterator( outer_range_type & outer_range, converter_type converter = converter_type() )
60 : m_outer_current(boost::begin(outer_range))
61 , m_outer_end(boost::end(outer_range))
64 , m_converter(converter)
66 if ( boost::empty(outer_range) ) {
67 m_outer_current = boost::none;
68 m_outer_end = boost::none;
71 find_inner_range_helper();
76 inner_range_type,converter_type>;
81 friend class boost::iterator_core_access;
90 if (m_inner_current) {
93 if (m_inner_current == m_inner_end) {
95 find_inner_range_helper();
100 bool equal(
const self & rhs )
const 102 return (m_outer_current == rhs.m_outer_current)
103 && (m_inner_current == rhs.m_inner_current);
106 typename boost::iterator_reference<inner_iterator>::type dereference()
const 108 return **m_inner_current;
111 void find_inner_range_helper()
114 while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
116 ++(*m_outer_current);
119 if (m_outer_current != m_outer_end) {
120 m_inner_current = boost::begin((*m_converter)(**m_outer_current));
121 m_inner_end = boost::end((*m_converter)(**m_outer_current));
124 m_outer_current = boost::none;
125 m_outer_end = boost::none;
127 m_inner_current = boost::none;
128 m_inner_end = boost::none;
134 boost::optional<outer_iterator> m_outer_current;
135 boost::optional<outer_iterator> m_outer_end;
137 boost::optional<inner_iterator> m_inner_current;
138 boost::optional<inner_iterator> m_inner_end;
140 boost::optional<converter_type> m_converter;
143 template <
typename OuterRange,
145 typename OuterToInnerConverter
147 class nested_iterator<const OuterRange, InnerRange,OuterToInnerConverter>
148 :
public boost::iterator_facade<
149 nested_iterator<const OuterRange,InnerRange,OuterToInnerConverter>
150 , typename boost::add_const<typename boost::range_value<const InnerRange>::type>::type
151 , boost::forward_traversal_tag
155 typedef typename boost::range_iterator<const OuterRange>::type outer_iterator;
156 typedef typename boost::range_iterator<const InnerRange>::type inner_iterator;
158 typedef const OuterRange outer_range_type;
159 typedef InnerRange inner_range_type;
161 typedef OuterToInnerConverter converter_type;
166 typedef typename boost::range_value<outer_range_type>::type outer_value;
178 nested_iterator( outer_range_type & outer_range, converter_type converter = converter_type() )
179 : m_outer_current(
boost::begin(outer_range))
180 , m_outer_end(
boost::end(outer_range))
183 , m_converter(converter)
185 if ( boost::empty(outer_range) ) {
186 m_outer_current = boost::none;
187 m_outer_end = boost::none;
190 find_inner_range_helper();
194 nested_iterator( nested_iterator<
typename boost::remove_const<outer_range_type>::type,
195 inner_range_type,converter_type>
const & itr)
196 : m_outer_current(itr.m_outer_current)
197 , m_outer_end(itr.m_outer_end)
198 , m_inner_current(itr.m_inner_current)
199 , m_inner_end(itr.m_inner_end)
200 , m_converter(itr.m_converter)
205 friend class boost::iterator_core_access;
214 if (m_inner_current) {
215 ++(*m_inner_current);
217 if (m_inner_current == m_inner_end) {
218 ++(*m_outer_current);
219 find_inner_range_helper();
224 bool equal(
const self & rhs )
const 226 return (m_outer_current == rhs.m_outer_current)
227 && (m_inner_current == rhs.m_inner_current);
230 typename boost::iterator_reference<inner_iterator>::type dereference()
const 232 return **m_inner_current;
235 void find_inner_range_helper()
238 while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
240 ++(*m_outer_current);
243 if (m_outer_current != m_outer_end) {
244 m_inner_current = boost::begin((*m_converter)(**m_outer_current));
245 m_inner_end = boost::end((*m_converter)(**m_outer_current));
248 m_outer_current = boost::none;
249 m_outer_end = boost::none;
251 m_inner_current = boost::none;
252 m_inner_end = boost::none;
257 boost::optional<outer_iterator> m_outer_current;
258 boost::optional<outer_iterator> m_outer_end;
260 boost::optional<inner_iterator> m_inner_current;
261 boost::optional<inner_iterator> m_inner_end;
263 boost::optional<converter_type> m_converter;
271 #endif //STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP