OSVR-Core
TreeNode.h
Go to the documentation of this file.
1 
11 // Copyright 2014 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_TreeNode_h_GUID_EEC6C5AF_332A_4780_55C2_D794B3BF5106
26 #define INCLUDED_TreeNode_h_GUID_EEC6C5AF_332A_4780_55C2_D794B3BF5106
27 
28 // Internal Includes
29 #include <osvr/Util/TreeNode_fwd.h>
30 
31 // Library/third-party includes
32 #include <boost/noncopyable.hpp>
33 #include <boost/operators.hpp>
34 #include <boost/assert.hpp>
35 
36 // Standard includes
37 #include <string>
38 #include <vector>
39 #include <algorithm>
40 #include <stdexcept>
41 
42 namespace osvr {
43 namespace util {
47  namespace tree {
48  struct NoSuchChild : std::runtime_error {
49  NoSuchChild(std::string const &name)
50  : std::runtime_error("No child found with the name " + name) {}
51  };
71  template <typename ValueType>
72  class TreeNode : boost::noncopyable,
73  boost::operators<TreeNode<ValueType> > {
74  public:
77 
81 
84  typedef type *parent_ptr_type;
85 
87  typedef ValueType value_type;
88 
92  static type &create(TreeNode &parent, std::string const &name);
93 
97  static type &create(TreeNode &parent, std::string const &name,
98  value_type const &val);
99 
101  static ptr_type createRoot();
102 
104  static ptr_type createRoot(value_type const &val);
105 
107  type &getOrCreateChildByName(std::string const &name);
108 
111  type const &getChildByName(std::string const &name) const;
112 
116  std::string const &getName() const;
117 
119  bool isRoot() const;
120 
123  parent_ptr_type getParent() const;
124 
128  bool hasChildren() const;
129 
131  size_t numChildren() const;
132 
134  value_type &value() { return m_value; }
135 
137  value_type const &value() const { return m_value; }
138 
141  template <typename F> void visitChildren(F &visitor) {
142  typedef typename ChildList::size_type size_type;
143  for (size_type i = 0; i < m_children.size(); ++i) {
146  visitor(*(m_children[i]));
147  }
148  }
149 
152  template <typename F> void visitConstChildren(F &visitor) const {
153  for (auto const &node : m_children) {
154  visitor(const_cast<type const &>(*node));
155  }
156  }
157 
162  template <typename F> void visitChildren(F &visitor) const {
163  visitConstChildren(visitor);
164  }
165 
167  bool operator==(const type &x) const { return this == &x; }
168 
169  private:
170  typedef type *weak_ptr_type;
171 
173  TreeNode(type &parent, std::string const &name);
174 
176  TreeNode(type &parent, std::string const &name,
177  value_type const &val);
178 
180  TreeNode();
181 
183  explicit TreeNode(value_type const &val);
184 
187  weak_ptr_type m_getChildByName(std::string const &name) const;
188 
191  void m_addChild(ptr_type const &child);
192 
194  value_type m_value;
195 
196  typedef std::vector<ptr_type> ChildList;
198  ChildList m_children;
199 
201  std::string const m_name;
202 
204  parent_ptr_type m_parent;
205  };
206 
207  template <typename ValueType>
208  inline TreeNode<ValueType> &
210  std::string const &name) {
211  if (parent.m_getChildByName(name)) {
212  throw std::logic_error(
213  "Can't create a child with the same name as "
214  "an existing child!");
215  }
216  ptr_type ret(new TreeNode(parent, name));
217  parent.m_addChild(ret);
218  return *ret;
219  }
220 
221  template <typename ValueType>
222  inline TreeNode<ValueType> &
224  std::string const &name,
225  ValueType const &val) {
226  if (parent.m_getChildByName(name)) {
227  throw std::logic_error(
228  "Can't create a child with the same name as "
229  "an existing child!");
230  }
231  ptr_type ret(new TreeNode(parent, name, val));
232  parent.m_addChild(ret);
233  return *ret;
234  }
235 
236  template <typename ValueType>
237  inline typename TreeNode<ValueType>::ptr_type
239  ptr_type ret(new TreeNode());
240  return ret;
241  }
242 
243  template <typename ValueType>
244  inline typename TreeNode<ValueType>::ptr_type
245  TreeNode<ValueType>::createRoot(ValueType const &val) {
246  ptr_type ret(new TreeNode(val));
247  return ret;
248  }
249 
250  template <typename ValueType>
251  inline TreeNode<ValueType> &
253  weak_ptr_type child = m_getChildByName(name);
254  if (child != nullptr) {
255  return *child;
256  }
257  return TreeNode::create(*this, name);
258  }
259 
260  template <typename ValueType>
261  inline TreeNode<ValueType> const &
262  TreeNode<ValueType>::getChildByName(std::string const &name) const {
263  weak_ptr_type child = m_getChildByName(name);
264  if (child != nullptr) {
265  return *child;
266  }
267  throw NoSuchChild(name);
268  }
269 
270  template <typename ValueType>
271  inline std::string const &TreeNode<ValueType>::getName() const {
272  return m_name;
273  }
274 
275  template <typename ValueType>
276  inline bool TreeNode<ValueType>::isRoot() const {
277  BOOST_ASSERT_MSG(
278  (getParent() == nullptr) == m_name.empty(),
279  "The root and only the root should have an empty name "
280  "and no parent!");
281  return getParent() == nullptr;
282  }
283 
284  template <typename ValueType>
287  return m_parent;
288  }
289 
290  template <typename ValueType>
291  inline bool TreeNode<ValueType>::hasChildren() const {
292  return !m_children.empty();
293  }
294 
295  template <typename ValueType>
296  inline size_t TreeNode<ValueType>::numChildren() const {
297  BOOST_ASSERT_MSG((m_children.size() != 0) == hasChildren(),
298  "hasChildren should return true iff size != 0!");
299  return m_children.size();
300  }
301 
302  template <typename ValueType>
303  inline typename TreeNode<ValueType>::weak_ptr_type
304  TreeNode<ValueType>::m_getChildByName(std::string const &name) const {
307  auto it = std::find_if(
308  begin(m_children), end(m_children),
309  [&](ptr_type const &n) { return n->getName() == name; });
310  weak_ptr_type ret = nullptr;
311  if (it != end(m_children)) {
312  ret = (*it).get();
313  }
314  return ret;
315  }
316 
317  template <typename ValueType>
319  typename TreeNode<ValueType>::ptr_type const &child) {
320  m_children.push_back(child);
321  }
322 
323  template <typename ValueType>
325  std::string const &name)
326  : m_value(), m_children(), m_name(name), m_parent(&parent) {
327  if (m_name.empty()) {
328  throw std::logic_error(
329  "Can't create a named tree node with an empty name!");
330  }
331  }
332 
333  template <typename ValueType>
335  std::string const &name,
336  ValueType const &val)
337  : m_value(val), m_children(), m_name(name), m_parent(&parent) {
338  if (m_name.empty()) {
339  throw std::logic_error(
340  "Can't create a named tree node with an empty name!");
341  }
342  }
343 
344  template <typename ValueType>
346  : m_value(), m_children(), m_name(), m_parent(nullptr) {
348  }
349 
350  template <typename ValueType>
351  inline TreeNode<ValueType>::TreeNode(ValueType const &val)
352  : m_value(val), m_children(), m_name(), m_parent(nullptr) {
354  }
355 
356  } // namespace tree
357 } // namespace util
358 } // namespace osvr
359 
360 #endif // INCLUDED_TreeNode_h_GUID_EEC6C5AF_332A_4780_55C2_D794B3BF5106
type * parent_ptr_type
The pointer for accessing a node&#39;s parent.
Definition: TreeNode.h:84
std::string const & getName() const
Gets the name of the current node.
Definition: TreeNode.h:271
Definition: RunLoopManager.h:42
TreeNode< ValueType > type
This template instantiation&#39;s type.
Definition: TreeNode.h:76
A node in a generic tree, which can contain an object by value.
Definition: TreeNode.h:72
ValueType value_type
The contained value type.
Definition: TreeNode.h:87
Definition: TreeNode.h:48
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
bool hasChildren() const
Does the node have any children?
Definition: TreeNode.h:291
shared_ptr< TreeNode< ValueType > > type
Tree node pointer type (metafunction result type)
Definition: TreeNode_fwd.h:46
type const & getChildByName(std::string const &name) const
Get the named child, throwing NoSuchChild if it doesn&#39;t exist.
Definition: TreeNode.h:262
value_type & value()
Reference accessor for contained value.
Definition: TreeNode.h:134
size_t numChildren() const
How many children does the node have?
Definition: TreeNode.h:296
void visitConstChildren(F &visitor) const
Generic constant visitation method that calls a functor on each of the children (as const) in an unde...
Definition: TreeNode.h:152
TreeNodePointer< ValueType >::type ptr_type
The pointer for holding this template instantiation - used primarily/only in holding the root node...
Definition: TreeNode.h:80
type & getOrCreateChildByName(std::string const &name)
Get the named child, creating it if it doesn&#39;t exist.
Definition: TreeNode.h:252
bool operator==(const type &x) const
Equality comparison operator - tests object identity.
Definition: TreeNode.h:167
void visitChildren(F &visitor)
Generic visitation method that calls a functor on each of the children in an undefined order...
Definition: TreeNode.h:141
static type & create(TreeNode &parent, std::string const &name)
Create a child tree node.
Definition: TreeNode.h:209
value_type const & value() const
Const reference accessor for contained value.
Definition: TreeNode.h:137
bool isRoot() const
Is the current node a root node?
Definition: TreeNode.h:276
static ptr_type createRoot()
Create a root.
Definition: TreeNode.h:238
parent_ptr_type getParent() const
Gets the node&#39;s parent, or nullptr if no parent (root node)
Definition: TreeNode.h:286
void visitChildren(F &visitor) const
Generic constant visitation method that calls a functor on each of the children in an undefined order...
Definition: TreeNode.h:162