1 /*=========================================================================
2 *
3 * Copyright Insight Software Consortium
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18 #ifndef itkTreeNode_hxx
19 #define itkTreeNode_hxx
20
21 #include "itkMacro.h"
22 #include "itkTreeNode.h"
23 #include <cstring>
24
25 namespace itk
26 {
27
28 /** Destructor */
29 template< typename TValue >
30 TreeNode< TValue >
~TreeNode()31 ::~TreeNode()
32 {
33 if ( m_Parent )
34 {
35 m_Parent->Remove(this);
36 }
37
38 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
39
40 for ( ChildIdentifier i = numberOfChildren; i > 0; i-- )
41 {
42 m_Children[i - 1]->SetParent(nullptr);
43 }
44 m_Children.clear();
45 m_Parent = nullptr;
46 m_Data = 0;
47 }
48
49 /** Return the parent node */
50 template< typename TValue >
51 TreeNode< TValue > *
52 TreeNode< TValue >
GetParent() const53 ::GetParent() const
54 {
55 return m_Parent;
56 }
57
58 /** Get a child */
59 template< typename TValue >
60 TreeNode< TValue > *
61 TreeNode< TValue >
GetChild(ChildIdentifier number) const62 ::GetChild(ChildIdentifier number) const
63 {
64 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
65
66 if ( number < numberOfChildren )
67 {
68 return m_Children[number];
69 }
70 else
71 {
72 return nullptr;
73 }
74 }
75
76 /** Set the value of a node */
77 template< typename TValue >
78 TValue
79 TreeNode< TValue >
Set(const TValue data)80 ::Set(const TValue data)
81 {
82 TValue help = m_Data;
83
84 m_Data = data;
85 return help;
86 }
87
88 /** Get the data of node */
89 template< typename TValue >
90 const TValue &
91 TreeNode< TValue >
Get() const92 ::Get() const
93 {
94 return m_Data;
95 }
96
97 /** Return true if has a parent */
98 template< typename TValue >
99 bool
100 TreeNode< TValue >
HasParent() const101 ::HasParent() const
102 {
103 return ( m_Parent ) ? true : false;
104 }
105
106 /** Set the parent node */
107 template< typename TValue >
108 void
109 TreeNode< TValue >
SetParent(TreeNode<TValue> * node)110 ::SetParent(TreeNode< TValue > *node)
111 {
112 //keep ourself alive just a bit longer
113 Pointer ourself = this;
114
115 if ( m_Parent != nullptr )
116 {
117 m_Parent->Remove(this);
118 }
119 m_Parent = node;
120 }
121
122 /** Return true if the node has children */
123 template< typename TValue >
124 bool
125 TreeNode< TValue >
HasChildren() const126 ::HasChildren() const
127 {
128 return ( !m_Children.empty() ) ? true : false;
129 }
130
131 /** Return the number of children */
132 template< typename TValue >
133 typename TreeNode< TValue >::ChildIdentifier
134 TreeNode< TValue >
CountChildren() const135 ::CountChildren() const
136 {
137 return static_cast< ChildIdentifier >( m_Children.size() );
138 }
139
140 /** Remove a child node from the current node */
141 template< typename TValue >
142 bool
143 TreeNode< TValue >
Remove(Self * n)144 ::Remove(Self *n)
145 {
146 typename std::vector< Pointer >::iterator pos;
147 pos = std::find(m_Children.begin(), m_Children.end(), n);
148 if ( pos != m_Children.end() )
149 {
150 //keep node alive just a bit longer
151 Pointer position = n;
152 m_Children.erase(pos);
153 n->SetParent(nullptr);
154 return true;
155 }
156 return false;
157 }
158
159 /** Replace a child by a new one */
160 template< typename TValue >
161 bool
162 TreeNode< TValue >
ReplaceChild(Self * oldChild,Self * newChild)163 ::ReplaceChild(Self *oldChild, Self *newChild)
164 {
165 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
166
167 for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
168 {
169 if ( m_Children[i] == oldChild )
170 {
171 m_Children[i] = newChild;
172 return true;
173 }
174 }
175 return false;
176 }
177
178 /** Return the child position given a node */
179 template< typename TValue >
180 OffsetValueType
181 TreeNode< TValue >
ChildPosition(const Self * node) const182 ::ChildPosition(const Self *node) const
183 {
184 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
185
186 for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
187 {
188 if ( m_Children[i] == node )
189 {
190 return i;
191 }
192 }
193 return -1;
194 }
195
196 /** Return the child position given an element, the first child found. */
197 template< typename TValue >
198 typename TreeNode< TValue >::ChildIdentifier
199 TreeNode< TValue >
ChildPosition(TValue element) const200 ::ChildPosition(TValue element) const
201 {
202 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
203
204 for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
205 {
206 if ( m_Children[i]->Get() == element )
207 {
208 return i;
209 }
210 }
211 return -1;
212 }
213
214 /** Add a child node */
215 template< typename TValue >
216 void
217 TreeNode< TValue >
AddChild(Self * node)218 ::AddChild(Self *node)
219 {
220 Pointer nodeKeepAlive = node;
221
222 node->SetParent(this);
223 m_Children.push_back(node);
224 }
225
226 /** Add a child at a specific position in the children list */
227 template< typename TValue >
228 void
229 TreeNode< TValue >
AddChild(ChildIdentifier number,Self * node)230 ::AddChild(ChildIdentifier number, Self *node)
231 {
232 const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
233 auto childId = static_cast<ChildIdentifier>( number );
234
235 if ( childId > numberOfChildren )
236 {
237 m_Children.resize(childId);
238 for ( ChildIdentifier i = numberOfChildren; i <= childId; i++ )
239 {
240 m_Children[i] = nullptr;
241 }
242 m_Children[number] = node;
243 return;
244 }
245
246 m_Children[number] = node;
247 }
248
249 /** Get the number of children given a name and a depth */
250 template< typename TValue >
251 typename TreeNode< TValue >::ChildIdentifier
252 TreeNode< TValue >
GetNumberOfChildren(unsigned int depth,char * name) const253 ::GetNumberOfChildren(unsigned int depth, char *name) const
254 {
255 auto it = m_Children.begin();
256 auto itEnd = m_Children.end();
257
258 ChildIdentifier cnt = 0;
259 while ( it != itEnd )
260 {
261 if ( name == nullptr || strstr(typeid( **it ).name(), name) )
262 {
263 ++cnt;
264 }
265 ++it;
266 }
267
268 it = m_Children.begin();
269 itEnd = m_Children.end();
270 if ( depth > 0 )
271 {
272 while ( it != itEnd )
273 {
274 cnt += ( *it )->GetNumberOfChildren(depth - 1, name);
275 ++it;
276 }
277 }
278
279 return cnt;
280 }
281
282 /** Get children given a name and a depth */
283 #if !defined( ITK_WRAPPING_PARSER )
284 template< typename TValue >
285 typename TreeNode< TValue >::ChildrenListType *
286 TreeNode< TValue >
GetChildren(unsigned int depth,char * name) const287 ::GetChildren(unsigned int depth, char *name) const
288 {
289 auto * children = new ChildrenListType;
290
291 auto childrenListIt = m_Children.begin();
292 auto childrenListEnd = m_Children.end();
293
294 while ( childrenListIt != childrenListEnd )
295 {
296 if ( name == nullptr || strstr(typeid( **childrenListIt ).name(), name) )
297 {
298 children->push_back(*childrenListIt);
299 }
300 if ( depth > 0 )
301 {
302 ChildrenListType *nextchildren = ( **childrenListIt ).GetChildren(depth - 1,
303 name);
304 // Add the child to the current list
305 typename ChildrenListType::const_iterator nextIt = nextchildren->begin();
306 while ( nextIt != nextchildren->end() )
307 {
308 children->push_back(*nextIt);
309 ++nextIt;
310 }
311 delete nextchildren;
312 }
313 ++childrenListIt;
314 }
315
316 return children;
317 }
318
319 #endif
320 } // namespace itk
321
322 #endif
323