Sierra Toolkit  Version of the Day
nested_iterator.hpp
1 #ifndef STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
2 #define STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
3 
4 #include <boost/range.hpp>
5 #include <boost/iterator.hpp>
6 #include <boost/optional.hpp>
7 
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>
12 
13 namespace stk_classic {
14 namespace util {
15 
24 template <typename OuterRange,
25  typename InnerRange,
26  typename OuterToInnerConverter
27  >
29  : public boost::iterator_facade<
30  nested_iterator<OuterRange,InnerRange,OuterToInnerConverter>
31  , typename boost::range_value<InnerRange>::type //value
32  , boost::forward_traversal_tag // traversal tag
33  >
34 {
35  public:
36  typedef typename boost::range_iterator<OuterRange>::type outer_iterator;
37  typedef typename boost::range_iterator<InnerRange>::type inner_iterator;
38 
39  typedef OuterRange outer_range_type;
40  typedef InnerRange inner_range_type;
41 
42  typedef OuterToInnerConverter converter_type;
43 
44  private:
46 
47  typedef typename boost::range_value<outer_range_type>::type outer_value;
48 
49 
50  public:
52  : m_outer_current()
53  , m_outer_end()
54  , m_inner_current()
55  , m_inner_end()
56  , m_converter()
57  {}
58 
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))
62  , m_inner_current()
63  , m_inner_end()
64  , m_converter(converter)
65  {
66  if ( boost::empty(outer_range) ) {
67  m_outer_current = boost::none;
68  m_outer_end = boost::none;
69  }
70  else {
71  find_inner_range_helper();
72  }
73  }
74 
75  friend class nested_iterator<typename boost::add_const<outer_range_type>::type,
76  inner_range_type,converter_type>;
77 
78 
79  //
80  private:
81  friend class boost::iterator_core_access;
82 
83  //functions necessary to implement core operations
84  // increment
85  // equal
86  // dereference
87 
88  void increment()
89  {
90  if (m_inner_current) {
91  ++(*m_inner_current);
92  //at end of current inner range
93  if (m_inner_current == m_inner_end) {
94  ++(*m_outer_current);
95  find_inner_range_helper();
96  }
97  }
98  }
99 
100  bool equal( const self & rhs ) const
101  {
102  return (m_outer_current == rhs.m_outer_current)
103  && (m_inner_current == rhs.m_inner_current);
104  }
105 
106  typename boost::iterator_reference<inner_iterator>::type dereference() const
107  {
108  return **m_inner_current;
109  }
110 
111  void find_inner_range_helper()
112  {
113  // find the next none-empty inner_range
114  while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
115  {
116  ++(*m_outer_current);
117  }
118 
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));
122  }
123  else { //at end of outer range
124  m_outer_current = boost::none;
125  m_outer_end = boost::none;
126 
127  m_inner_current = boost::none;
128  m_inner_end = boost::none;
129  }
130  }
131 
132 
133  private:
134  boost::optional<outer_iterator> m_outer_current;
135  boost::optional<outer_iterator> m_outer_end;
136 
137  boost::optional<inner_iterator> m_inner_current;
138  boost::optional<inner_iterator> m_inner_end;
139 
140  boost::optional<converter_type> m_converter;
141 };
142 
143 template <typename OuterRange,
144  typename InnerRange,
145  typename OuterToInnerConverter
146  >
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 //value
151  , boost::forward_traversal_tag // traversal tag
152  >
153 {
154  public:
155  typedef typename boost::range_iterator<const OuterRange>::type outer_iterator;
156  typedef typename boost::range_iterator<const InnerRange>::type inner_iterator;
157 
158  typedef const OuterRange outer_range_type;
159  typedef InnerRange inner_range_type;
160 
161  typedef OuterToInnerConverter converter_type;
162 
163  private:
165 
166  typedef typename boost::range_value<outer_range_type>::type outer_value;
167 
168 
169  public:
171  : m_outer_current()
172  , m_outer_end()
173  , m_inner_current()
174  , m_inner_end()
175  , m_converter()
176  {}
177 
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))
181  , m_inner_current()
182  , m_inner_end()
183  , m_converter(converter)
184  {
185  if ( boost::empty(outer_range) ) {
186  m_outer_current = boost::none;
187  m_outer_end = boost::none;
188  }
189  else {
190  find_inner_range_helper();
191  }
192  }
193 
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)
201  {}
202 
203  //
204  private:
205  friend class boost::iterator_core_access;
206 
207  //functions necessary to implement core operations
208  // increment
209  // equal
210  // dereference
211 
212  void increment()
213  {
214  if (m_inner_current) {
215  ++(*m_inner_current);
216  //at end of current inner range
217  if (m_inner_current == m_inner_end) {
218  ++(*m_outer_current);
219  find_inner_range_helper();
220  }
221  }
222  }
223 
224  bool equal( const self & rhs ) const
225  {
226  return (m_outer_current == rhs.m_outer_current)
227  && (m_inner_current == rhs.m_inner_current);
228  }
229 
230  typename boost::iterator_reference<inner_iterator>::type dereference() const
231  {
232  return **m_inner_current;
233  }
234 
235  void find_inner_range_helper()
236  {
237  // find the next none-empty inner_range
238  while ( (m_outer_current != m_outer_end) && boost::empty((*m_converter)(**m_outer_current)) )
239  {
240  ++(*m_outer_current);
241  }
242 
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));
246  }
247  else { //at end of outer range
248  m_outer_current = boost::none;
249  m_outer_end = boost::none;
250 
251  m_inner_current = boost::none;
252  m_inner_end = boost::none;
253  }
254  }
255 
256  private:
257  boost::optional<outer_iterator> m_outer_current;
258  boost::optional<outer_iterator> m_outer_end;
259 
260  boost::optional<inner_iterator> m_inner_current;
261  boost::optional<inner_iterator> m_inner_end;
262 
263  boost::optional<converter_type> m_converter;
264 };
265 
266 
267 } // util
268 } // stk
269 
270 
271 #endif //STK_UTIL_STK_UTIL_UTIL_NESTED_ITERATOR_HPP
Sierra Toolkit.