COPASI API  4.16.103
CNodeIterator.h
Go to the documentation of this file.
1 // Copyright (C) 2012 - 2013 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 /*
7  * CNodeIterator.h
8  *
9  * Created on: May 11, 2012
10  * Author: shoops
11  */
12 
13 #ifndef COPASI_CNodeIterator
14 #define COPASI_CNodeIterator
15 
16 #include <stack>
17 #include <limits>
18 
19 #include "copasi/math/CMathEnum.h"
20 
21 /**
22  * Iterator processing modes determining to which the method
23  * next will advance the iterator.
24  */
26 {
27 public:
28  enum State
29  {
30  Start = 0x00,
31  Before = 0x01,
32  After = 0x02,
33  Intermediate = 0x04,
34  End = 0x08
35  };
36 
38 };
39 
40 template < class Node, class Context > class CNodeContextIterator
41 {
42 private:
43  /**
44  * Internal class handling the traversal of the tree.
45  * For each nested level in the tree an element is pushed onto the stack
46  */
48  {
49  public:
50  /**
51  * Default Constructor
52  */
54  mpNode(NULL),
55  mChildCount(0),
56  mNextChildIndex(0),
57  mContext(),
58  mpParentContext(NULL)
59  {}
60 
61  /**
62  * Copy constructor
63  * @param const CStackElement & src
64  */
66  mpNode(src.mpNode),
69  mContext(src.mContext),
71  {}
72 
73  /**
74  * Constructor
75  * @param Node * pNode
76  * @param Context * pParentContext (default: NULL)
77  */
78  CStackElement(Node * pNode, Context * pParentContext = NULL):
79  mpNode(pNode),
80  mChildCount(0),
81  mNextChildIndex(0),
82  mContext(),
83  mpParentContext(pParentContext)
84  {
85  if (pNode != NULL)
86  {
87  mChildCount = pNode->getNumChildren();
88  }
89  }
90 
91  /**
92  * Destructor
93  */
95 
96  /**
97  * Pointer to the node of the tree represented by the stack element
98  */
99  Node * mpNode;
100 
101  /**
102  * The number of children of the current node
103  */
104  size_t mChildCount;
105 
106  /**
107  * The index of the next child to be processed
108  */
110 
111  /**
112  * The context of the current node.
113  */
114  Context mContext;
115 
116  /**
117  * The pointer to the parent node's context.
118  */
119  Context * mpParentContext;
120  };
121 
122 public:
123  /**
124  * Default constructor
125  */
127  mStack(),
130  {}
131 
132  /**
133  * Copy constructor
134  * @param const CNodeContextIterator & src
135  */
137  mStack(src.mStack),
140  {}
141 
142  /**
143  * Constructor
144  * @param Node * pNode
145  * @param Context * pParentContext (default: NULL)
146  */
147  CNodeContextIterator(Node * pNode, Context * pParentContext = NULL):
148  mStack(),
151  {
152  mStack.push(CStackElement(pNode, pParentContext));
153  }
154 
155  /**
156  * Destructor
157  */
159 
160 private:
161  /**
162  * This method moves the iterator to the next node in the tree. The tree is
163  * traversed depth first. A return value of false indicates that the tree
164  * has been completed traversed.
165  *
166  * Please note that the iterator points to the same node twice, once before
167  * the first child and once after the last child to allow pre and post
168  * processing. This behavior is also true for childless nodes. To determine
169  * whether the iterator is in the pre or post processing phase one may check
170  * the nextChildIndex where zero indicates pre and None indicates post
171  * processing.
172  *
173  * @return bool moreNodes
174  */
175  void increment()
176  {
177  if (mStack.empty())
178  {
180 
181  return;
182  }
183 
184  CStackElement & Current = mStack.top();
185 
186  if (Current.mNextChildIndex < Current.mChildCount)
187  {
188  mStack.push(CStackElement(static_cast< Node * >(Current.mpNode->getChild(Current.mNextChildIndex++)), &Current.mContext));
190 
191  return;
192  }
193 
194  if (Current.mNextChildIndex == Current.mChildCount)
195  {
196  Current.mNextChildIndex++;
198 
199  return;
200  }
201 
202  mStack.pop();
203 
204  if (mStack.empty())
205  {
207 
208  return;
209  }
210 
211  CStackElement & Parent = mStack.top();
212 
213  if (Parent.mNextChildIndex < Parent.mChildCount)
214  {
216  }
217  else
218  {
220  Parent.mNextChildIndex++;
221  }
222 
223  return;
224  }
225 
226 public:
227  /**
228  * This method moves the iterator to the next node based on the
229  * setting of the processing modes and returns the processing mode of the
230  * iterator.
231  * @return const CNodeIteratorMode::State & processingMode
232  */
234  {
236  {
237  increment();
238  }
239  else
240  {
242  }
243 
244  while (!(mProcessingModes & mCurrentMode))
245  {
246  increment();
247  }
248 
249  return mCurrentMode;
250  }
251 
252  /**
253  * This method moves the iterator beyond the last child.
254  */
256  {
257  CStackElement & Current = mStack.top();
258  Current.mNextChildIndex = Current.mChildCount + 1;
260 
261  return mCurrentMode;
262  }
263 
264  /**
265  * Dereference the iterator
266  * @return Node * pNode
267  */
268  Node * operator*() {return mStack.top().mpNode;}
269 
270  /**
271  * Dereference the iterator
272  * @return Node * pNode
273  */
274  Node * operator->() {return mStack.top().mpNode;}
275 
276  /**
277  * Retrieve the processing mode
278  * @return const CNodeIteratorMode::State & processingMode
279  */
281 
282  /**
283  * Retrieve the end of the iterator, i.e., the
284  */
286 
287  /**
288  * Retrieve the context of the current node.
289  * @return Context & context
290  */
291  Context & context() {return mStack.top().mContext;}
292 
293  /**
294  * Retrieve the pointer to the parent node context if it exists.
295  * @return Context * parentContextPtr.
296  */
297  Context * parentContextPtr() {return mStack.top().mpParentContext;}
298 
299  /**
300  * The nesting level of the tree.
301  * Note, the nesting level of the root of the tree is 1. This is to distinguish its level
302  * from the end of the iterator which reports 0.
303  */
304  size_t level() {return mStack.size();}
305 
306  /**
307  * Set the processing modes to which the method next will advance the iterator.
308  * Note, the iterator will always stop at the end.
309  * @param const CNodeIteratorMode::Flag & processingModes
310  */
311  void setProcessingModes(const CNodeIteratorMode::Flag & processingModes) {mProcessingModes = (processingModes | CNodeIteratorMode::End);}
312 
313  /**
314  * Retrieve the processing modes to which the method next will advance the iterator.
315  * @return CNodeIteratorMode::Flag processingModes
316  */
318 
319 private:
320  /**
321  * A stack representing the nested elements of the tree.
322  */
323  std::stack< CStackElement > mStack;
324 
325  /**
326  * The current processing mode.
327  */
329 
330  /**
331  * The processing modes to which the method next will advance the iterator
332  */
334 };
335 
336 /**
337  * A convenient iterator class which has the context type int
338  */
339 template < class Node > class CNodeIterator : public CNodeContextIterator< Node, int >
340 {
341 public:
342  /**
343  * Constructor
344  */
346  CNodeContextIterator< Node, int >()
347  {}
348 
349  /**
350  * Copy constructor.
351  */
353  CNodeContextIterator< Node, int >(src)
354  {}
355 
356  /**
357  * Constructor
358  * @param Node * pNode
359  */
360  CNodeIterator(Node * pNode):
361  CNodeContextIterator< Node, int >(pNode)
362  {}
363 
364  /**
365  * Destructor
366  */
368 };
369 #endif // COPASI_CNodeIterator
std::stack< CStackElement > mStack
CStackElement(Node *pNode, Context *pParentContext=NULL)
Definition: CNodeIterator.h:78
CNodeIteratorMode::Flag getProcessingModes() const
const CNodeIteratorMode::State & next()
CNodeIteratorMode::Flag mProcessingModes
CNodeIterator(Node *pNode)
CStackElement(const CStackElement &src)
Definition: CNodeIterator.h:65
CNodeContextIterator(const CNodeContextIterator &src)
const CNodeIteratorMode::State & skipChildren()
Context * parentContextPtr()
CNodeContextIterator(Node *pNode, Context *pParentContext=NULL)
void setProcessingModes(const CNodeIteratorMode::Flag &processingModes)
const CNodeIteratorMode::State & processingMode() const
CNodeIterator(const CNodeIterator &src)
CNodeIteratorMode::State end() const
CNodeIteratorMode::State mCurrentMode
CMathFlags< State > Flag
Definition: CNodeIterator.h:37