MADARA  3.1.8
IteratorImpl.cpp
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 #ifndef _TREE_ITERATOR_IMPL_CPP
3 #define _TREE_ITERATOR_IMPL_CPP
4 
5 #ifndef _MADARA_NO_KARL_
6 
11 
12 const size_t LQUEUE_SIZE = 40;
13 
14 // Constructor for ExpressionTreeIteratorImpl that takes a tree
15 // to iterate over
16 
18  const ExpressionTree &tree)
19  : tree_ (tree)
20 {
21 }
22 
23 // Destructor
24 
26 {
27 }
28 
31 
33  const ExpressionTree &tree, bool end_iter)
35  stack_ ()
36 {
37  // if the caller doesn't want an end iterator, insert the root tree
38  // into the queue.
39  if (!end_iter && !this->tree_.is_null ())
40  {
41  stack_.push (const_cast <ExpressionTree &> (tree));
42 
43  // start at the smallest element (left-most)
44  while (!stack_.top ().left ().is_null ())
45  stack_.push (stack_.top ().left ());
46  }
47 }
48 
50 
52 {
53 }
54 
56 
59 {
60  return stack_.top ();
61 }
62 
64 
67 {
68  return stack_.top ();
69 }
70 
72 
73 void
75 {
76  // we know that at this point there is no left () of top ()
77  // because we would have already visited it.
78 
79  if (!stack_.is_empty ())
80  {
81  // if we have nodes greater than ourselves
82  if (!stack_.top ().right ().is_null ())
83  {
84  // push the right child node onto the stack
85  // and pop the old parent (it's been visited now)
86  stack_.push (stack_.pop ().right ());
87 
88  // keep pushing until we get to the left most child
89  while (!stack_.top ().left ().is_null ())
90  stack_.push (stack_.top ().left ());
91  }
92  else
93  stack_.pop ();
94  }
95 }
96 
98 
99 bool
101  const ExpressionTreeIteratorImpl &rhs) const
102 {
103  const InOrderIteratorImpl * in_order_rhs = dynamic_cast
104  <const InOrderIteratorImpl *> (&rhs);
105 
106  // if the rhs was not a level_order iterator then we've already
107  // discovered the relation is false.
108 
109  if (in_order_rhs)
110  {
111  // Check if the container we are iterating over has the same
112  // root node and that the size of the queues are equal. The
113  // latter doesn't truly determine equality. However, this is an
114  // easy check for determining most inequalities and it allows us
115  // to assume the queue at least has a front node (coupled with
116  // the is_empty () function later).
117 
118  ExpressionTree &t1 =
119  const_cast <ExpressionTree &> (tree_);
120  ExpressionTree &t2 =
121  const_cast <ExpressionTree &> (in_order_rhs->tree_);
122 
123  if (t1.get_root () == t2.get_root ()
124  && stack_.size () == in_order_rhs->stack_.size ())
125  {
126  // Check for both being is_empty (special condition).
127  if (stack_.is_empty () && in_order_rhs->stack_.is_empty ())
128  return true;
129 
130  // check the front's node pointer. If the node pointers are
131  // equal, then both iterators are pointing to the same
132  // position in the tree.
133 
134  if (stack_.top ().get_root () ==
135  in_order_rhs->stack_.top ().get_root ())
136  return true;
137  }
138  }
139 
140  // either we were trying to compare a non-level order iterator or we
141  // were comparing two level order iterators that were obviously at
142  // different points in the tree (their queue sizes were different)
143 
144  return false;
145 }
146 
148 
149 bool
151  const ExpressionTreeIteratorImpl &rhs) const
152 {
153  return ! (*this == rhs);
154 }
155 
158 
161 {
162  return new InOrderIteratorImpl (*this);
163 }
164 
167 
169  const ExpressionTree &tree, bool end_iter)
170  : ExpressionTreeIteratorImpl (tree),
171  stack_ ()
172 {
173  // if the caller doesn't want an end iterator, insert the root tree
174  // into the queue.
175  if (!end_iter && !this->tree_.is_null ())
176  stack_.push (const_cast <ExpressionTree &> (tree));
177 }
178 
180 
182  void)
183 {
184 
185 }
186 
188 
191 {
192  return stack_.top ();
193 }
194 
196 
199 {
200  return stack_.top ();
201 }
202 
204 
205 void
207 {
208  // we know that at this point there is no left () of top ()
209  // because we would have already visited it.
210 
211  if (!stack_.is_empty ())
212  {
213  // we need to pop the node off the stack before pushing the
214  // children, or else we'll revisit this node later
215 
216  ExpressionTree current = stack_.pop ();
217 
218  // note the order here: right first, then left. Since this is
219  // LIFO, this results in the left child being the first
220  // evaluated, which fits into the Pre-order traversal strategy
221 
222  if (!current.right ().is_null ())
223  stack_.push (current.right ());
224  if (!current.left ().is_null ())
225  stack_.push (current.left ());
226  }
227 }
228 
230 
231 bool
233  const ExpressionTreeIteratorImpl &rhs) const
234 {
235  const PreOrderIteratorImpl *pre_order_rhs = dynamic_cast
236  <const PreOrderIteratorImpl *> (&rhs);
237 
238  // if the rhs was not a level_order iterator
239  // then we've already discovered the relation is false
240 
241  if (pre_order_rhs)
242  {
243  // check if the container we are iterating over has the same
244  // root node and that the size of the queues are equal. The
245  // latter doesn't truly determine equality. However, this is an
246  // easy check for determining most inequalities and it allows us
247  // to assume the queue at least has a front node (coupled with
248  // the is_empty () function later).
249 
250  ExpressionTree &t1 = const_cast <ExpressionTree &> (tree_);
251  ExpressionTree &t2 = const_cast <ExpressionTree &> (
252  pre_order_rhs->tree_);
253 
254  if (t1.get_root () == t2.get_root ()
255  && stack_.size () == pre_order_rhs->stack_.size ())
256  {
257  // check for both being is_empty (special condition)
258  if (stack_.is_empty () && pre_order_rhs->stack_.is_empty ())
259  return true;
260 
261  // check the front's node pointer. If the node pointers
262  // are equal, then both iterators are pointing to the same
263  // position in the tree.
264 
265  if (stack_.top ().get_root () ==
266  pre_order_rhs->stack_.top ().get_root ())
267  return true;
268  }
269  }
270 
271  // either we were trying to compare a non-level order iterator or
272  // we were comparing two level order iterators that were obviously
273  // at different points in the tree (their queue sizes were different)
274 
275  return false;
276 }
277 
279 
280 bool
282  const ExpressionTreeIteratorImpl &rhs) const
283 {
284  return ! (*this == rhs);
285 }
286 
287 
290 
293 {
294  return new PreOrderIteratorImpl (*this);
295 }
296 
299 
301  const ExpressionTree &tree, bool end_iter)
302  : ExpressionTreeIteratorImpl (tree),
303  stack_ ()
304 {
305  // if the caller doesn't want an end iterator, insert the root tree
306  // into the queue.
307  if (!end_iter && !this->tree_.is_null ())
308  {
309  ExpressionTree current = const_cast <ExpressionTree &> (tree);
310  stack_.push (current);
311 
312  // the commented code does not work on unary operator nodes with
313  // no left child, but a right child - or at least, there is a
314  // certain depth that this will not go down
315 
316  while (!current.is_null ())
317  {
318  if (!current.right ().is_null ())
319  stack_.push (current.right ());
320  if (!current.left ().is_null ())
321  {
322  // if there was a left, then update current
323  // this is the case for all non-negations
324  stack_.push (current.left ());
325  current = current.left ();
326  }
327  else
328  // if there was not a left, then current = current->right_
329  // this handles cases of unary nodes, like negations
330  current = current.right ();
331  }
332  }
333 }
334 
336 
338  void)
339 {
340 }
341 
343 
346 {
347  return stack_.top ();
348 }
349 
351 
354 {
355  return stack_.top ();
356 }
357 
359 
360 void
362 {
363  // we know that at this point there is no left () of top ()
364  // because we would have already visited it.
365 
366  if (!stack_.is_empty ())
367  {
368  // we need to pop the node off the stack before pushing the
369  // children, or else we'll revisit this node later
370 
371  ExpressionTree current = stack_.pop ();
372 
373  // This is where stuff gets a little confusing.
374 
375  if (!stack_.is_empty ()
376  && stack_.top ().left ().get_root () != current.get_root ()
377  && stack_.top ().right ().get_root () != current.get_root () )
378 
379  {
380  current = stack_.top ();
381 
382  while (!current.is_null ())
383  {
384  if (!current.right ().is_null ())
385  stack_.push (current.right ());
386  if (!current.left ().is_null ())
387  {
388  // if there was a left, then update current
389  // this is the case for all non-negations
390  stack_.push (current.left ());
391  current = current.left ();
392  }
393  else
394  {
395  // if there was not a left, then current = current->right_
396  // this handles cases of unary nodes, like negations
397  current = current.right ();
398  }
399  }
400  }
401  }
402 }
403 
405 
406 bool
408  const ExpressionTreeIteratorImpl &rhs) const
409 {
410  const PostOrderIteratorImpl * post_order_rhs = dynamic_cast
411  <const PostOrderIteratorImpl *> (&rhs);
412 
413  // if the rhs was not a level_order iterator
414  // then we've already discovered the relation is false
415 
416  if (post_order_rhs)
417  {
418  // check if the container we are iterating over has the same
419  // root node and that the size of the queues are equal. The
420  // latter doesn't truly determine equality. However, this is an
421  // easy check for determining most inequalities and it allows us
422  // to assume the queue at least has a front node (coupled with
423  // the is_empty () function later).
424 
425  ExpressionTree &t1 = const_cast <ExpressionTree &> (tree_);
426  ExpressionTree &t2 = const_cast <ExpressionTree &> (
427  post_order_rhs->tree_);
428 
429  if (t1.get_root () == t2.get_root ()
430  && stack_.size () == post_order_rhs->stack_.size ())
431  {
432  // check for both being is_empty (special condition)
433  if (stack_.is_empty () && post_order_rhs->stack_.is_empty ())
434  return true;
435 
436  // check the front's node pointer. If the node pointers are
437  // equal, then both iterators are pointing to the same
438  // position in the tree.
439 
440  if (stack_.top ().get_root () ==
441  post_order_rhs->stack_.top ().get_root ())
442  return true;
443  }
444  }
445 
446  // either we were trying to compare a non-level order iterator or
447  // we were comparing two level order iterators that were obviously
448  // at different points in the tree (their queue sizes were different)
449 
450  return false;
451 }
452 
454 
455 bool
457  const ExpressionTreeIteratorImpl &rhs) const
458 {
459  return ! (*this == rhs);
460 }
461 
464 
467 {
468  return new PostOrderIteratorImpl (*this);
469 }
470 
473 
475  const ExpressionTree &tree, bool end_iter)
476  : ExpressionTreeIteratorImpl (tree),
477  queue_ (LQUEUE_SIZE)
478 {
479  // if the caller doesn't want an end iterator, insert the root tree
480  // into the queue.
481  if (!end_iter && !this->tree_.is_null ())
482  queue_.enqueue (const_cast <ExpressionTree &> (tree));
483 }
484 
486 
488  void)
489 {
490 }
491 
493 
496  void)
497 {
498  return queue_.front ();
499 }
500 
502 
505  void) const
506 {
507  return queue_.front ();
508 }
509 
511 
512 void
514  void)
515 {
516  if (!queue_.is_empty ())
517  {
518  // If the queue is not empty, dequeue an element
519  ExpressionTree root = queue_.dequeue ();
520 
521  if (!root.is_null ())
522  {
523  // If the element wasn't null, enqueue its children
524  if (!root.left ().is_null ())
525  queue_.enqueue (root.left ());
526  if (!root.right ().is_null ())
527  queue_.enqueue (root.right ());
528  }
529  }
530 }
531 
533 
534 bool
536  const ExpressionTreeIteratorImpl &rhs) const
537 {
538  const LevelOrderExpressionTreeIteratorImpl * level_order_rhs =
539  dynamic_cast<const LevelOrderExpressionTreeIteratorImpl *> (&rhs);
540 
541  // if the rhs was not a level_order iterator then we've already
542  // discovered the relation is false.
543 
544  if (level_order_rhs)
545  {
546  // check if the container we are iterating over has the same
547  // root node and that the size of the queues are equal. The
548  // latter doesn't truly determine equality. However, this is an
549  // easy check for determining most inequalities and it allows us
550  // to assume the queue at least has a front node (coupled with
551  // the is_empty () function later).
552 
553  ExpressionTree &t1 = const_cast <ExpressionTree &> (tree_);
554  ExpressionTree &t2 = const_cast <ExpressionTree &> (
555  level_order_rhs->tree_);
556 
557  if (t1.get_root () == t2.get_root ()
558  && queue_.size () == level_order_rhs->queue_.size ())
559  {
560  // check for both being is_empty (special condition)
561  if (queue_.is_empty () && level_order_rhs->queue_.is_empty ())
562  return true;
563 
564  // check the front's node pointer. If the node pointers
565  // are equal, then both iterators are pointing to the same
566  // position in the tree.
567 
568  if (queue_.front ().get_root () ==
569  level_order_rhs->queue_.front ().get_root ())
570  return true;
571  }
572  }
573 
574  // either we were trying to compare a non-level order iterator or we
575  // were comparing two level order iterators that were obviously at
576  // different points in the tree (their queue sizes were different)
577 
578  return false;
579 }
580 
582 
583 bool
585  const ExpressionTreeIteratorImpl &rhs) const
586 {
587  return !(*this == rhs);
588 }
589 
592 
595  void)
596 {
597  return new LevelOrderExpressionTreeIteratorImpl (*this);
598 }
599 
600 #endif // _MADARA_NO_KARL_
601 
602 #endif /* _TREE_ITERATOR_IMPL_CPP */
603 
PreOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an LevelOrderExpressionTreeIterator.
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
Encapsulates a MADARA KaRL expression into an evaluatable tree.
madara::utility::LQueue< ExpressionTree > queue_
Our current position in the iteration.
Definition: IteratorImpl.h:306
bool is_null(void) const
Checks if root pointer is null.
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:138
Iterates through an ExpressionTree in in-order.
Definition: IteratorImpl.h:93
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
LevelOrderExpressionTreeIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an LevelOrderExpressionTreeIterator.
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:250
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
const size_t LQUEUE_SIZE
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
Iterates through an ExpressionTree in post-order.
Definition: IteratorImpl.h:204
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:194
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
ComponentNode * get_root(void)
Returns the root node of the expression tree.
Iterates through an ExpressionTree in level-order.
Definition: IteratorImpl.h:260
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
ExpressionTree left(void)
Returns the left expression of this tree.
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
ExpressionTree right(void)
Returns the right expression of this tree.
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
Iterates through an ExpressionTree in level-order.
Definition: IteratorImpl.h:148
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
ExpressionTreeIteratorImpl(const ExpressionTree &tree)
Construct an ExpressionTreeIteratorImpl to iterate over a tree.
InOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an InOrderIteratorImpl.
Implementation of the ExpressionTreeIterator pattern that is used to define the various iterations al...
Definition: IteratorImpl.h:41
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
PostOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an PostOrderIteratorImpl.
const ExpressionTree & tree_
The tree we are iterating over.
Definition: IteratorImpl.h:83
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.