section_iterators.hpp
1 #pragma once
2 
3 #include <algorithm> // std::copy
4 #include <deque> // std::deque
5 #include <iterator> // std::back_inserter / std::front_inserter
6 #include <memory> // std::shared_ptr
7 #include <vector> // std::vector
8 
9 #include <morphio/exceptions.h>
10 #include <morphio/types.h>
11 
12 namespace detail {
13 
14 template <typename SectionT, typename MorphologyT>
15 std::vector<SectionT> getChildren(const MorphologyT& morphology) noexcept {
16  return morphology.rootSections();
17 }
18 
19 template <typename SectionT>
20 std::vector<SectionT> getChildren(const SectionT& section) {
21  return section.children();
22 }
23 
24 template <typename SectionT>
25 std::vector<std::shared_ptr<SectionT>> getChildren(const std::shared_ptr<SectionT>& section) {
26  return section->children();
27 }
28 
29 template <typename SectionT>
30 bool isRoot(const SectionT& current) {
31  return current.isRoot();
32 }
33 
34 template <typename SectionT>
35 bool isRoot(const std::shared_ptr<SectionT>& current) {
36  return current->isRoot();
37 }
38 
39 template <typename SectionT>
40 SectionT getParent(const SectionT& current) {
41  return current.parent();
42 }
43 
44 template <typename SectionT>
45 std::shared_ptr<SectionT> getParent(const std::shared_ptr<SectionT>& current) {
46  return current->parent();
47 }
48 } // namespace detail
49 
50 namespace morphio {
51 
52 template <typename SectionT, typename MorphologyT>
54 {
55  public:
56  using iterator_category = std::input_iterator_tag;
57  using value_type = SectionT;
58  using difference_type = std::ptrdiff_t;
59  using pointer = SectionT*;
60  using reference = SectionT&;
61 
62  breadth_iterator_t() = default;
63 
64  inline explicit breadth_iterator_t(const SectionT& section);
65  inline explicit breadth_iterator_t(const MorphologyT& morphology);
66  inline breadth_iterator_t(const breadth_iterator_t& other);
67 
68  inline SectionT operator*() const;
69 
70  inline breadth_iterator_t& operator++();
71  inline breadth_iterator_t operator++(int);
72 
73  inline bool operator==(const breadth_iterator_t& other) const;
74  bool operator!=(const breadth_iterator_t& other) const;
75 
76  private:
77  std::deque<SectionT> deque_;
78 };
79 
80 template <typename SectionT, typename MorphologyT>
82 {
83  public:
84  using iterator_category = std::input_iterator_tag;
85  using value_type = SectionT;
86  using difference_type = std::ptrdiff_t;
87  using pointer = SectionT*;
88  using reference = SectionT&;
89 
90  depth_iterator_t() = default;
91 
92  inline explicit depth_iterator_t(const SectionT& section);
93  inline explicit depth_iterator_t(const MorphologyT& morphology);
94  inline depth_iterator_t(const depth_iterator_t& other);
95 
96  inline SectionT operator*() const;
97 
98  inline depth_iterator_t& operator++();
99  inline depth_iterator_t operator++(int);
100 
101  inline bool operator==(const depth_iterator_t& other) const;
102  inline bool operator!=(const depth_iterator_t& other) const;
103 
104  private:
105  std::deque<SectionT> deque_;
106 };
107 
108 template <typename SectionT>
110 {
111  public:
112  using iterator_category = std::input_iterator_tag;
113  using value_type = SectionT;
114  using difference_type = std::ptrdiff_t;
115  using pointer = SectionT*;
116  using reference = SectionT&;
117 
118  inline upstream_iterator_t();
119  inline explicit upstream_iterator_t(const SectionT& section);
120  inline upstream_iterator_t(const upstream_iterator_t& other);
121  inline ~upstream_iterator_t();
122 
123  inline SectionT operator*() const;
124 
125  inline upstream_iterator_t& operator++();
126  inline upstream_iterator_t operator++(int);
127 
128  inline bool operator==(const upstream_iterator_t& other) const;
129  inline bool operator!=(const upstream_iterator_t& other) const;
130 
131  private:
132  // This is a workaround for not having std::optional until c++17.
133  // Need to have a copy of a section, not a pointer, as the latter are created
134  // on the fly, so we'd have to heap allocate; however, to signal the end()
135  // of iteration, we need a 'default' section or a sentinel. Since the concept
136  // of a default section is nebulous, a sentinel was used instead.
137  union {
138  char unused;
139  SectionT current;
140  };
141  bool end;
142 };
143 
144 // breath_iterator_t class definition
145 
146 template <typename SectionT, typename MorphologyT>
148  deque_.push_front(section);
149 }
150 
151 template <typename SectionT, typename MorphologyT>
152 inline breadth_iterator_t<SectionT, MorphologyT>::breadth_iterator_t(
153  const MorphologyT& morphology) {
154  const auto& children = detail::getChildren<SectionT, MorphologyT>(morphology);
155  std::copy(children.begin(), children.end(), std::back_inserter(deque_));
156 }
157 
158 template <typename SectionT, typename MorphologyT>
159 inline breadth_iterator_t<SectionT, MorphologyT>::breadth_iterator_t(
160  const breadth_iterator_t& other)
161  : deque_(other.deque_) {}
162 
163 template <typename SectionT, typename MorphologyT>
164 inline SectionT breadth_iterator_t<SectionT, MorphologyT>::operator*() const {
165  return deque_.front();
166 }
167 
168 template <typename SectionT, typename MorphologyT>
169 inline breadth_iterator_t<SectionT, MorphologyT>&
170 breadth_iterator_t<SectionT, MorphologyT>::operator++() {
171  if (deque_.empty()) {
172  throw MorphioError("Can't iterate past the end");
173  }
174 
175  const auto& children = detail::getChildren(deque_.front());
176  deque_.pop_front();
177  std::copy(children.begin(), children.end(), std::back_inserter(deque_));
178 
179  return *this;
180 }
181 
182 template <typename SectionT, typename MorphologyT>
183 inline breadth_iterator_t<SectionT, MorphologyT>
184 breadth_iterator_t<SectionT, MorphologyT>::operator++(int) {
185  breadth_iterator_t ret(*this);
186  ++(*this);
187  return ret;
188 }
189 
190 template <typename SectionT, typename MorphologyT>
191 inline bool breadth_iterator_t<SectionT, MorphologyT>::operator==(
192  const breadth_iterator_t& other) const {
193  return deque_ == other.deque_;
194 }
195 
196 template <typename SectionT, typename MorphologyT>
197 inline bool breadth_iterator_t<SectionT, MorphologyT>::operator!=(
198  const breadth_iterator_t& other) const {
199  return !(*this == other);
200 }
201 
202 // depth_iterator_t class definition
203 
204 template <typename SectionT, typename MorphologyT>
205 inline depth_iterator_t<SectionT, MorphologyT>::depth_iterator_t(const SectionT& section) {
206  deque_.push_front(section);
207 }
208 
209 template <typename SectionT, typename MorphologyT>
210 inline depth_iterator_t<SectionT, MorphologyT>::depth_iterator_t(const MorphologyT& morphology) {
211  const auto& children = detail::getChildren<SectionT, MorphologyT>(morphology);
212  std::copy(children.rbegin(), children.rend(), std::front_inserter(deque_));
213 }
214 
215 template <typename SectionT, typename MorphologyT>
216 inline depth_iterator_t<SectionT, MorphologyT>::depth_iterator_t(const depth_iterator_t& other)
217  : deque_(other.deque_) {}
218 
219 template <typename SectionT, typename MorphologyT>
220 inline SectionT depth_iterator_t<SectionT, MorphologyT>::operator*() const {
221  return deque_.front();
222 }
223 
224 template <typename SectionT, typename MorphologyT>
225 inline depth_iterator_t<SectionT, MorphologyT>&
226 depth_iterator_t<SectionT, MorphologyT>::operator++() {
227  if (deque_.empty()) {
228  throw MorphioError("Can't iterate past the end");
229  }
230 
231  const auto children = detail::getChildren(deque_.front());
232  deque_.pop_front();
233  std::copy(children.rbegin(), children.rend(), std::front_inserter(deque_));
234 
235  return *this;
236 }
237 
238 template <typename SectionT, typename MorphologyT>
239 inline depth_iterator_t<SectionT, MorphologyT> depth_iterator_t<SectionT, MorphologyT>::operator++(
240  int) {
241  depth_iterator_t ret(*this);
242  ++(*this);
243  return ret;
244 }
245 
246 template <typename SectionT, typename MorphologyT>
247 inline bool depth_iterator_t<SectionT, MorphologyT>::operator==(
248  const depth_iterator_t& other) const {
249  return deque_ == other.deque_;
250 }
251 
252 template <typename SectionT, typename MorphologyT>
253 inline bool depth_iterator_t<SectionT, MorphologyT>::operator!=(
254  const depth_iterator_t& other) const {
255  return !(*this == other);
256 }
257 
258 // upstream_iterator_t class definition
259 
260 template <typename SectionT>
261 inline upstream_iterator_t<SectionT>::upstream_iterator_t()
262  : unused(0)
263  , end(true) {}
264 
265 template <typename SectionT>
266 inline upstream_iterator_t<SectionT>::upstream_iterator_t(const SectionT& section)
267  : current(section)
268  , end(false) {}
269 
270 template <typename SectionT>
271 inline upstream_iterator_t<SectionT>::upstream_iterator_t(const upstream_iterator_t& other) {
272  end = other.end;
273  if (!other.end) {
274  new (&current) SectionT(other.current);
275  }
276 }
277 
278 template <typename SectionT>
279 inline upstream_iterator_t<SectionT>::~upstream_iterator_t() {
280  if (!end) {
281  this->current.~SectionT();
282  }
283 }
284 
285 template <typename SectionT>
286 inline SectionT upstream_iterator_t<SectionT>::operator*() const {
287  return current;
288 }
289 
290 template <typename SectionT>
291 inline upstream_iterator_t<SectionT>& upstream_iterator_t<SectionT>::operator++() {
292  if (end) {
293  throw MissingParentError("Cannot call iterate upstream past the root node");
294  } else if (detail::isRoot(current)) {
295  end = true;
296  this->current.~SectionT();
297  } else {
298  current = detail::getParent(current);
299  }
300  return *this;
301 }
302 
303 template <typename SectionT>
304 inline upstream_iterator_t<SectionT> upstream_iterator_t<SectionT>::operator++(int) {
305  upstream_iterator_t ret(*this);
306  ++(*this);
307  return ret;
308 }
309 
310 template <typename SectionT>
311 inline bool upstream_iterator_t<SectionT>::operator==(const upstream_iterator_t& other) const {
312  if (end || other.end) {
313  return end == other.end;
314  }
315  return current == other.current;
316 }
317 
318 template <typename SectionT>
319 inline bool upstream_iterator_t<SectionT>::operator!=(const upstream_iterator_t& other) const {
320  return !(*this == other);
321 }
322 
323 } // namespace morphio
Definition: section_iterators.hpp:54
Definition: section_iterators.hpp:82
Definition: section_iterators.hpp:110
Definition: endoplasmic_reticulum.h:5