section_base.h
1 #pragma once
2 
3 #include <cstdint> // uint32_t
4 #include <memory> // std::shared_ptr
5 #include <vector> // std::vector
6 
7 #include <morphio/morphology.h>
8 #include <morphio/properties.h>
9 #include <morphio/types.h>
10 #include <morphio/vector_types.h>
11 
12 namespace morphio {
24 template <typename T>
26 {
27  public:
28  inline bool operator==(const SectionBase& other) const noexcept;
29  inline bool operator!=(const SectionBase& other) const noexcept;
30 
34  bool isRoot() const;
35 
41  T parent() const;
42 
46  std::vector<T> children() const;
47 
49  uint32_t id() const noexcept { return id_; }
50 
51  protected:
52  SectionBase(uint32_t id, const std::shared_ptr<Property::Properties>& properties);
53 
54  template <typename Property>
55  range<const typename Property::Type> get() const;
56 
57  uint32_t id_ = 0;
58  SectionRange range_;
59  std::shared_ptr<Property::Properties> properties_;
60 };
61 
62 template <typename T>
63 SectionBase<T>::SectionBase(uint32_t id, const std::shared_ptr<Property::Properties>& properties)
64  : id_(id)
65  , properties_(properties) {
66  const auto& sections = properties->get<typename T::SectionId>();
67  if (id_ >= sections.size()) {
68  throw RawDataError(
69  "Requested section ID (" + std::to_string(id_) +
70  ") is out of array bounds (array size = " + std::to_string(sections.size()) + ")");
71  }
72 
73  const auto start = static_cast<size_t>(sections[id_][0]);
74  const size_t end = id_ == sections.size() - 1
75  ? properties->get<typename T::PointAttribute>().size()
76  : static_cast<size_t>(sections[id_ + 1][0]);
77 
78  range_ = std::make_pair(start, end);
79 
80  if (range_.second <= range_.first) {
81  std::cerr << "Dereferencing broken properties section " << id_
82  << "\nSection range: " << range_.first << " -> " << range_.second << '\n';
83  }
84 }
85 
86 template <typename T>
87 inline bool SectionBase<T>::operator==(const SectionBase& other) const noexcept {
88  return other.id_ == id_ && other.properties_ == properties_;
89 }
90 
91 template <typename T>
92 inline bool SectionBase<T>::operator!=(const SectionBase& other) const noexcept {
93  return !(*this == other);
94 }
95 
96 template <typename T>
97 template <typename TProperty>
98 range<const typename TProperty::Type> SectionBase<T>::get() const {
99  const auto& data = properties_->get<TProperty>();
100  if (data.empty()) {
101  return {};
102  }
103 
104  auto ptr_start = data.data() + range_.first;
105  return {ptr_start, range_.second - range_.first};
106 }
107 
108 template <typename T>
110  return properties_->get<typename T::SectionId>()[id_][1] == -1;
111 }
112 
113 template <typename T>
115  if (isRoot()) {
116  throw MissingParentError("Cannot call Section::parent() on a root node (section id=" +
117  std::to_string(id_) + ").");
118  }
119 
120  const auto _parent = static_cast<unsigned int>(
121  properties_->get<typename T::SectionId>()[id_][1]);
122  return {_parent, properties_};
123 }
124 
125 template <typename T>
126 std::vector<T> SectionBase<T>::children() const {
127  const auto& section_children = properties_->children<typename T::SectionId>();
128 
129  if (section_children.empty()) {
130  return {};
131  }
132 
133  const auto it = section_children.find(static_cast<int>(id_));
134  if (it == section_children.end()) {
135  return {};
136  }
137 
138  std::vector<T> result;
139  const std::vector<uint32_t> children = it->second;
140  result.reserve(children.size());
141  for (uint32_t id : children) {
142  result.push_back(T(id, properties_));
143  }
144 
145  return result;
146 }
147 
148 
149 } // namespace morphio
morphio::MissingParentError
Definition: exceptions.h:60
morphio::SectionBase::parent
T parent() const
Definition: section_base.h:114
morphio::SectionBase::children
std::vector< T > children() const
Definition: section_base.h:126
morphio::SectionBase::id
uint32_t id() const noexcept
Definition: section_base.h:49
morphio::SectionBase::isRoot
bool isRoot() const
Definition: section_base.h:109
morphio::SectionBase
Definition: section_base.h:25