MADARA  3.4.1
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  void)
27 {
28 }
29 
32 
34  const ExpressionTree& tree, bool end_iter)
35  : ExpressionTreeIteratorImpl(tree), 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 
54 
56 operator*(void)
57 {
58  return stack_.top();
59 }
60 
62 
65 {
66  return stack_.top();
67 }
68 
70 
72 {
73  // we know that at this point there is no left () of top ()
74  // because we would have already visited it.
75 
76  if (!stack_.is_empty())
77  {
78  // if we have nodes greater than ourselves
79  if (!stack_.top().right().is_null())
80  {
81  // push the right child node onto the stack
82  // and pop the old parent (it's been visited now)
83  stack_.push(stack_.pop().right());
84 
85  // keep pushing until we get to the left most child
86  while (!stack_.top().left().is_null())
87  stack_.push(stack_.top().left());
88  }
89  else
90  stack_.pop();
91  }
92 }
93 
95 
97  const ExpressionTreeIteratorImpl& rhs) const
98 {
99  const InOrderIteratorImpl* in_order_rhs =
100  dynamic_cast<const InOrderIteratorImpl*>(&rhs);
101 
102  // if the rhs was not a level_order iterator then we've already
103  // discovered the relation is false.
104 
105  if (in_order_rhs)
106  {
107  // Check if the container we are iterating over has the same
108  // root node and that the size of the queues are equal. The
109  // latter doesn't truly determine equality. However, this is an
110  // easy check for determining most inequalities and it allows us
111  // to assume the queue at least has a front node (coupled with
112  // the is_empty () function later).
113 
114  ExpressionTree& t1 = const_cast<ExpressionTree&>(tree_);
115  ExpressionTree& t2 = const_cast<ExpressionTree&>(in_order_rhs->tree_);
116 
117  if (t1.get_root() == t2.get_root() &&
118  stack_.size() == in_order_rhs->stack_.size())
119  {
120  // Check for both being is_empty (special condition).
121  if (stack_.is_empty() && in_order_rhs->stack_.is_empty())
122  return true;
123 
124  // check the front's node pointer. If the node pointers are
125  // equal, then both iterators are pointing to the same
126  // position in the tree.
127 
128  if (stack_.top().get_root() == in_order_rhs->stack_.top().get_root())
129  return true;
130  }
131  }
132 
133  // either we were trying to compare a non-level order iterator or we
134  // were comparing two level order iterators that were obviously at
135  // different points in the tree (their queue sizes were different)
136 
137  return false;
138 }
139 
141 
143  const ExpressionTreeIteratorImpl& rhs) const
144 {
145  return !(*this == rhs);
146 }
147 
150 
153 {
154  return new InOrderIteratorImpl(*this);
155 }
156 
159 
161  const ExpressionTree& tree, bool end_iter)
162  : ExpressionTreeIteratorImpl(tree), stack_()
163 {
164  // if the caller doesn't want an end iterator, insert the root tree
165  // into the queue.
166  if (!end_iter && !this->tree_.is_null())
167  stack_.push(const_cast<ExpressionTree&>(tree));
168 }
169 
171 
173 
175 
177 operator*(void)
178 {
179  return stack_.top();
180 }
181 
183 
186 {
187  return stack_.top();
188 }
189 
191 
193 {
194  // we know that at this point there is no left () of top ()
195  // because we would have already visited it.
196 
197  if (!stack_.is_empty())
198  {
199  // we need to pop the node off the stack before pushing the
200  // children, or else we'll revisit this node later
201 
202  ExpressionTree current = stack_.pop();
203 
204  // note the order here: right first, then left. Since this is
205  // LIFO, this results in the left child being the first
206  // evaluated, which fits into the Pre-order traversal strategy
207 
208  if (!current.right().is_null())
209  stack_.push(current.right());
210  if (!current.left().is_null())
211  stack_.push(current.left());
212  }
213 }
214 
216 
218  const ExpressionTreeIteratorImpl& rhs) const
219 {
220  const PreOrderIteratorImpl* pre_order_rhs =
221  dynamic_cast<const PreOrderIteratorImpl*>(&rhs);
222 
223  // if the rhs was not a level_order iterator
224  // then we've already discovered the relation is false
225 
226  if (pre_order_rhs)
227  {
228  // check if the container we are iterating over has the same
229  // root node and that the size of the queues are equal. The
230  // latter doesn't truly determine equality. However, this is an
231  // easy check for determining most inequalities and it allows us
232  // to assume the queue at least has a front node (coupled with
233  // the is_empty () function later).
234 
235  ExpressionTree& t1 = const_cast<ExpressionTree&>(tree_);
236  ExpressionTree& t2 = const_cast<ExpressionTree&>(pre_order_rhs->tree_);
237 
238  if (t1.get_root() == t2.get_root() &&
239  stack_.size() == pre_order_rhs->stack_.size())
240  {
241  // check for both being is_empty (special condition)
242  if (stack_.is_empty() && pre_order_rhs->stack_.is_empty())
243  return true;
244 
245  // check the front's node pointer. If the node pointers
246  // are equal, then both iterators are pointing to the same
247  // position in the tree.
248 
249  if (stack_.top().get_root() == pre_order_rhs->stack_.top().get_root())
250  return true;
251  }
252  }
253 
254  // either we were trying to compare a non-level order iterator or
255  // we were comparing two level order iterators that were obviously
256  // at different points in the tree (their queue sizes were different)
257 
258  return false;
259 }
260 
262 
264  const ExpressionTreeIteratorImpl& rhs) const
265 {
266  return !(*this == rhs);
267 }
268 
271 
274 {
275  return new PreOrderIteratorImpl(*this);
276 }
277 
280 
282  const ExpressionTree& tree, bool end_iter)
283  : ExpressionTreeIteratorImpl(tree), stack_()
284 {
285  // if the caller doesn't want an end iterator, insert the root tree
286  // into the queue.
287  if (!end_iter && !this->tree_.is_null())
288  {
289  ExpressionTree current = const_cast<ExpressionTree&>(tree);
290  stack_.push(current);
291 
292  // the commented code does not work on unary operator nodes with
293  // no left child, but a right child - or at least, there is a
294  // certain depth that this will not go down
295 
296  while (!current.is_null())
297  {
298  if (!current.right().is_null())
299  stack_.push(current.right());
300  if (!current.left().is_null())
301  {
302  // if there was a left, then update current
303  // this is the case for all non-negations
304  stack_.push(current.left());
305  current = current.left();
306  }
307  else
308  // if there was not a left, then current = current->right_
309  // this handles cases of unary nodes, like negations
310  current = current.right();
311  }
312  }
313 }
314 
316 
318 
320 
322 operator*(void)
323 {
324  return stack_.top();
325 }
326 
328 
331 {
332  return stack_.top();
333 }
334 
336 
338 {
339  // we know that at this point there is no left () of top ()
340  // because we would have already visited it.
341 
342  if (!stack_.is_empty())
343  {
344  // we need to pop the node off the stack before pushing the
345  // children, or else we'll revisit this node later
346 
347  ExpressionTree current = stack_.pop();
348 
349  // This is where stuff gets a little confusing.
350 
351  if (!stack_.is_empty() &&
352  stack_.top().left().get_root() != current.get_root() &&
353  stack_.top().right().get_root() != current.get_root())
354 
355  {
356  current = stack_.top();
357 
358  while (!current.is_null())
359  {
360  if (!current.right().is_null())
361  stack_.push(current.right());
362  if (!current.left().is_null())
363  {
364  // if there was a left, then update current
365  // this is the case for all non-negations
366  stack_.push(current.left());
367  current = current.left();
368  }
369  else
370  {
371  // if there was not a left, then current = current->right_
372  // this handles cases of unary nodes, like negations
373  current = current.right();
374  }
375  }
376  }
377  }
378 }
379 
381 
383  const ExpressionTreeIteratorImpl& rhs) const
384 {
385  const PostOrderIteratorImpl* post_order_rhs =
386  dynamic_cast<const PostOrderIteratorImpl*>(&rhs);
387 
388  // if the rhs was not a level_order iterator
389  // then we've already discovered the relation is false
390 
391  if (post_order_rhs)
392  {
393  // check if the container we are iterating over has the same
394  // root node and that the size of the queues are equal. The
395  // latter doesn't truly determine equality. However, this is an
396  // easy check for determining most inequalities and it allows us
397  // to assume the queue at least has a front node (coupled with
398  // the is_empty () function later).
399 
400  ExpressionTree& t1 = const_cast<ExpressionTree&>(tree_);
401  ExpressionTree& t2 = const_cast<ExpressionTree&>(post_order_rhs->tree_);
402 
403  if (t1.get_root() == t2.get_root() &&
404  stack_.size() == post_order_rhs->stack_.size())
405  {
406  // check for both being is_empty (special condition)
407  if (stack_.is_empty() && post_order_rhs->stack_.is_empty())
408  return true;
409 
410  // check the front's node pointer. If the node pointers are
411  // equal, then both iterators are pointing to the same
412  // position in the tree.
413 
414  if (stack_.top().get_root() == post_order_rhs->stack_.top().get_root())
415  return true;
416  }
417  }
418 
419  // either we were trying to compare a non-level order iterator or
420  // we were comparing two level order iterators that were obviously
421  // at different points in the tree (their queue sizes were different)
422 
423  return false;
424 }
425 
427 
429  const ExpressionTreeIteratorImpl& rhs) const
430 {
431  return !(*this == rhs);
432 }
433 
436 
439 {
440  return new PostOrderIteratorImpl(*this);
441 }
442 
445 
448  const ExpressionTree& tree, bool end_iter)
449  : ExpressionTreeIteratorImpl(tree), queue_(LQUEUE_SIZE)
450 {
451  // if the caller doesn't want an end iterator, insert the root tree
452  // into the queue.
453  if (!end_iter && !this->tree_.is_null())
454  queue_.enqueue(const_cast<ExpressionTree&>(tree));
455 }
456 
458 
461 {
462 }
463 
465 
468 {
469  return queue_.front();
470 }
471 
473 
476  void)const
477 {
478  return queue_.front();
479 }
480 
482 
484 {
485  if (!queue_.is_empty())
486  {
487  // If the queue is not empty, dequeue an element
488  ExpressionTree root = queue_.dequeue();
489 
490  if (!root.is_null())
491  {
492  // If the element wasn't null, enqueue its children
493  if (!root.left().is_null())
494  queue_.enqueue(root.left());
495  if (!root.right().is_null())
496  queue_.enqueue(root.right());
497  }
498  }
499 }
500 
502 
504  const ExpressionTreeIteratorImpl& rhs) const
505 {
506  const LevelOrderExpressionTreeIteratorImpl* level_order_rhs =
507  dynamic_cast<const LevelOrderExpressionTreeIteratorImpl*>(&rhs);
508 
509  // if the rhs was not a level_order iterator then we've already
510  // discovered the relation is false.
511 
512  if (level_order_rhs)
513  {
514  // check if the container we are iterating over has the same
515  // root node and that the size of the queues are equal. The
516  // latter doesn't truly determine equality. However, this is an
517  // easy check for determining most inequalities and it allows us
518  // to assume the queue at least has a front node (coupled with
519  // the is_empty () function later).
520 
521  ExpressionTree& t1 = const_cast<ExpressionTree&>(tree_);
522  ExpressionTree& t2 = const_cast<ExpressionTree&>(level_order_rhs->tree_);
523 
524  if (t1.get_root() == t2.get_root() &&
525  queue_.size() == level_order_rhs->queue_.size())
526  {
527  // check for both being is_empty (special condition)
528  if (queue_.is_empty() && level_order_rhs->queue_.is_empty())
529  return true;
530 
531  // check the front's node pointer. If the node pointers
532  // are equal, then both iterators are pointing to the same
533  // position in the tree.
534 
535  if (queue_.front().get_root() ==
536  level_order_rhs->queue_.front().get_root())
537  return true;
538  }
539  }
540 
541  // either we were trying to compare a non-level order iterator or we
542  // were comparing two level order iterators that were obviously at
543  // different points in the tree (their queue sizes were different)
544 
545  return false;
546 }
547 
549 
551  const ExpressionTreeIteratorImpl& rhs) const
552 {
553  return !(*this == rhs);
554 }
555 
558 
561 {
562  return new LevelOrderExpressionTreeIteratorImpl(*this);
563 }
564 
565 #endif // _MADARA_NO_KARL_
566 
567 #endif /* _TREE_ITERATOR_IMPL_CPP */
const size_t LQUEUE_SIZE
virtual ComponentNode * right(void) const
Returns the right expression.
Implementation of the ExpressionTreeIterator pattern that is used to define the various iterations al...
Definition: IteratorImpl.h:42
ExpressionTreeIteratorImpl(const ExpressionTree &tree)
Construct an ExpressionTreeIteratorImpl to iterate over a tree.
const ExpressionTree & tree_
The tree we are iterating over.
Definition: IteratorImpl.h:81
Encapsulates a MADARA KaRL expression into an evaluatable tree.
ExpressionTree left(void)
Returns the left expression of this tree.
bool is_null(void) const
Checks if root pointer is null.
ExpressionTree right(void)
Returns the right expression of this tree.
ComponentNode * get_root(void)
Returns the root node of the expression tree.
Iterates through an ExpressionTree in in-order.
Definition: IteratorImpl.h:92
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
InOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an InOrderIteratorImpl.
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:134
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
Iterates through an ExpressionTree in level-order.
Definition: IteratorImpl.h:251
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
madara::utility::LQueue< ExpressionTree > queue_
Our current position in the iteration.
Definition: IteratorImpl.h:295
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
LevelOrderExpressionTreeIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an LevelOrderExpressionTreeIterator.
Iterates through an ExpressionTree in post-order.
Definition: IteratorImpl.h:198
PostOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an PostOrderIteratorImpl.
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:240
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
Iterates through an ExpressionTree in level-order.
Definition: IteratorImpl.h:145
virtual bool operator!=(const ExpressionTreeIteratorImpl &lhs) const
Nonequality operator.
madara::utility::LStack< ExpressionTree > stack_
Our current position in the iteration.
Definition: IteratorImpl.h:187
virtual ExpressionTree operator*(void)
Dereference operator returns a reference to the item contained at the current position.
virtual ExpressionTreeIteratorImpl * clone(void)
Method for cloning an impl. Necessary for post increments.
virtual bool operator==(const ExpressionTreeIteratorImpl &rhs) const
Equality operator.
virtual void operator++(void)
Increment operator (used for both pre- and post-increment).
PreOrderIteratorImpl(const ExpressionTree &tree, bool end_iter=false)
Construct an LevelOrderExpressionTreeIterator.