/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkTreeNode_hxx #define itkTreeNode_hxx #include "itkMacro.h" #include namespace itk { /** Destructor */ template TreeNode::~TreeNode() { if (m_Parent) { m_Parent->Remove(this); } const auto numberOfChildren = static_cast(m_Children.size()); for (ChildIdentifier i = numberOfChildren; i > 0; i--) { m_Children[i - 1]->SetParent(nullptr); } m_Children.clear(); m_Parent = nullptr; m_Data = 0; } /** Return the parent node */ template TreeNode * TreeNode::GetParent() const { return m_Parent; } /** Get a child */ template TreeNode * TreeNode::GetChild(ChildIdentifier number) const { const auto numberOfChildren = static_cast(m_Children.size()); if (number < numberOfChildren) { return m_Children[number]; } else { return nullptr; } } /** Set the value of a node */ template TValue TreeNode::Set(const TValue data) { TValue help = m_Data; m_Data = data; return help; } /** Get the data of node */ template const TValue & TreeNode::Get() const { return m_Data; } /** Return true if has a parent */ template bool TreeNode::HasParent() const { return (m_Parent) ? true : false; } /** Set the parent node */ template void TreeNode::SetParent(TreeNode * node) { // keep ourself alive just a bit longer Pointer ourself = this; if (m_Parent != nullptr) { m_Parent->Remove(this); } m_Parent = node; } /** Return true if the node has children */ template bool TreeNode::HasChildren() const { return (!m_Children.empty()) ? true : false; } /** Return the number of children */ template auto TreeNode::CountChildren() const -> ChildIdentifier { return static_cast(m_Children.size()); } /** Remove a child node from the current node */ template bool TreeNode::Remove(Self * n) { typename std::vector::iterator pos; pos = std::find(m_Children.begin(), m_Children.end(), n); if (pos != m_Children.end()) { // keep node alive just a bit longer Pointer position = n; m_Children.erase(pos); n->SetParent(nullptr); return true; } return false; } /** Replace a child by a new one */ template bool TreeNode::ReplaceChild(Self * oldChild, Self * newChild) { const auto numberOfChildren = static_cast(m_Children.size()); for (ChildIdentifier i = 0; i < numberOfChildren; ++i) { if (m_Children[i] == oldChild) { m_Children[i] = newChild; return true; } } return false; } /** Return the child position given a node */ template OffsetValueType TreeNode::ChildPosition(const Self * node) const { const auto numberOfChildren = static_cast(m_Children.size()); for (ChildIdentifier i = 0; i < numberOfChildren; ++i) { if (m_Children[i] == node) { return i; } } return -1; } /** Return the child position given an element, the first child found. */ template auto TreeNode::ChildPosition(TValue element) const -> ChildIdentifier { const auto numberOfChildren = static_cast(m_Children.size()); for (ChildIdentifier i = 0; i < numberOfChildren; ++i) { if (m_Children[i]->Get() == element) { return i; } } return -1; } /** Add a child node */ template void TreeNode::AddChild(Self * node) { Pointer nodeKeepAlive = node; node->SetParent(this); m_Children.push_back(node); } /** Add a child at a specific position in the children list */ template void TreeNode::AddChild(ChildIdentifier number, Self * node) { const auto numberOfChildren = static_cast(m_Children.size()); auto childId = static_cast(number); if (childId > numberOfChildren) { m_Children.resize(childId); for (ChildIdentifier i = numberOfChildren; i <= childId; ++i) { m_Children[i] = nullptr; } m_Children[number] = node; return; } m_Children[number] = node; } /** Get the number of children given a name and a depth */ template auto TreeNode::GetNumberOfChildren(unsigned int depth, char * name) const -> ChildIdentifier { auto it = m_Children.begin(); auto itEnd = m_Children.end(); ChildIdentifier cnt = 0; while (it != itEnd) { if (name == nullptr || strstr(typeid(**it).name(), name)) { ++cnt; } ++it; } it = m_Children.begin(); itEnd = m_Children.end(); if (depth > 0) { while (it != itEnd) { cnt += (*it)->GetNumberOfChildren(depth - 1, name); ++it; } } return cnt; } /** Get children given a name and a depth */ #if !defined(ITK_WRAPPING_PARSER) template auto TreeNode::GetChildren(unsigned int depth, char * name) const -> ChildrenListType * { auto * children = new ChildrenListType; auto childrenListIt = m_Children.begin(); auto childrenListEnd = m_Children.end(); while (childrenListIt != childrenListEnd) { if (name == nullptr || strstr(typeid(**childrenListIt).name(), name)) { children->push_back(*childrenListIt); } if (depth > 0) { ChildrenListType * nextchildren = (**childrenListIt).GetChildren(depth - 1, name); // Add the child to the current list typename ChildrenListType::const_iterator nextIt = nextchildren->begin(); while (nextIt != nextchildren->end()) { children->push_back(*nextIt); ++nextIt; } delete nextchildren; } ++childrenListIt; } return children; } #endif } // namespace itk #endif