403b196bfd4b8848eb9d65fd02d53320d8c71e72
[pulseview.git] / pv / view / viewitemiterator.hpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #ifndef PULSEVIEW_PV_VIEWS_TRACEVIEW_VIEWITEMITERATOR_HPP
22 #define PULSEVIEW_PV_VIEWS_TRACEVIEW_VIEWITEMITERATOR_HPP
23
24 #include <algorithm>
25 #include <cassert>
26 #include <iterator>
27 #include <memory>
28 #include <stack>
29 #include <type_traits>
30 #include <vector>
31
32 #include <pv/session.hpp>
33
34 namespace pv {
35 namespace views {
36 namespace TraceView {
37
38 template<class Owner, class Item> class ViewItemIterator
39 {
40 public:
41         typedef typename Owner::item_list::const_iterator child_iterator;
42         typedef std::shared_ptr<Item> value_type;
43         typedef ptrdiff_t difference_type;
44         typedef value_type pointer;
45         typedef const value_type& reference;
46         typedef std::forward_iterator_tag iterator_category;
47
48 public:
49         ViewItemIterator(Owner *owner) :
50                 owner_stack_({owner}) {}
51
52         ViewItemIterator(Owner *owner, child_iterator iter) :
53                 owner_stack_({owner}) {
54                 assert(owner);
55                 if (iter != owner->child_items().end())
56                         iter_stack_.push(iter);
57         }
58
59         ViewItemIterator(const ViewItemIterator<Owner, Item> &o) :
60                 owner_stack_(o.owner_stack_),
61                 iter_stack_(o.iter_stack_) {}
62
63         reference operator*() const {
64                 return *iter_stack_.top();
65         }
66
67         reference operator->() const {
68                 return *this;
69         }
70
71         ViewItemIterator<Owner, Item>& operator++() {
72                 using std::dynamic_pointer_cast;
73                 using std::shared_ptr;
74
75                 assert(!owner_stack_.empty());
76                 assert(!iter_stack_.empty());
77
78                 shared_ptr<Owner> owner(dynamic_pointer_cast<Owner>(
79                         *iter_stack_.top()));
80                 if (owner && !owner->child_items().empty()) {
81                         owner_stack_.push(owner.get());
82                         iter_stack_.push(owner->child_items().begin());
83                 } else {
84                         while (!iter_stack_.empty() && (++iter_stack_.top()) ==
85                                 owner_stack_.top()->child_items().end()) {
86                                 owner_stack_.pop();
87                                 iter_stack_.pop();
88                         }
89                 }
90
91                 return *this;
92         }
93
94         ViewItemIterator<Owner, Item> operator++(int) {
95                 ViewItemIterator<Owner, Item> pre = *this;
96                 ++*this;
97                 return pre;
98         }
99
100         bool operator==(const ViewItemIterator &o) const {
101                 return (iter_stack_.empty() && o.iter_stack_.empty()) || (
102                         iter_stack_.size() == o.iter_stack_.size() &&
103                         owner_stack_.top() == o.owner_stack_.top() &&
104                         iter_stack_.top() == o.iter_stack_.top());
105         }
106
107         bool operator!=(const ViewItemIterator &o) const {
108                 return !((const ViewItemIterator&)*this == o);
109         }
110
111         void swap(ViewItemIterator<Owner, Item>& other) {
112                 swap(owner_stack_, other.owner_stack_);
113                 swap(iter_stack_, other.iter_stack_);
114         }
115
116 private:
117         std::stack<Owner*> owner_stack_;
118         std::stack<child_iterator> iter_stack_;
119 };
120
121 template<class Owner, class Item>
122 void swap(ViewItemIterator<Owner, Item>& a, ViewItemIterator<Owner, Item>& b)
123 {
124         a.swap(b);
125 }
126
127 } // namespace TraceView
128 } // namespace views
129 } // namespace pv
130
131 #endif // PULSEVIEW_PV_VIEWS_TRACEVIEW_VIEWITEMITERATOR_HPP