1 //===-- Iterable.h ----------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_Iterable_h_
11 #define liblldb_Iterable_h_
12
13 #include <utility>
14
15
16 namespace lldb_private {
17
map_adapter(I & iter)18 template <typename I, typename E> E map_adapter(I &iter) {
19 return iter->second;
20 }
21
vector_adapter(I & iter)22 template <typename I, typename E> E vector_adapter(I &iter) { return *iter; }
23
list_adapter(I & iter)24 template <typename I, typename E> E list_adapter(I &iter) { return *iter; }
25
26 template <typename C, typename E, E (*A)(typename C::const_iterator &)>
27 class AdaptedConstIterator {
28 public:
29 typedef typename C::const_iterator BackingIterator;
30
31 // Wrapping constructor
AdaptedConstIterator(BackingIterator backing_iterator)32 AdaptedConstIterator(BackingIterator backing_iterator)
33 : m_iter(backing_iterator) {}
34
35 // Default-constructible
AdaptedConstIterator()36 AdaptedConstIterator() : m_iter() {}
37
38 // Copy-constructible
AdaptedConstIterator(const AdaptedConstIterator & rhs)39 AdaptedConstIterator(const AdaptedConstIterator &rhs) : m_iter(rhs.m_iter) {}
40
41 // Copy-assignable
42 AdaptedConstIterator &operator=(const AdaptedConstIterator &rhs) {
43 m_iter = rhs.m_iter;
44 return *this;
45 }
46
47 // Destructible
48 ~AdaptedConstIterator() = default;
49
50 // Comparable
51 bool operator==(const AdaptedConstIterator &rhs) {
52 return m_iter == rhs.m_iter;
53 }
54
55 bool operator!=(const AdaptedConstIterator &rhs) {
56 return m_iter != rhs.m_iter;
57 }
58
59 // Rvalue dereferenceable
60 E operator*() { return (*A)(m_iter); }
61
62 E operator->() { return (*A)(m_iter); }
63
64 // Offset dereferenceable
65 E operator[](typename BackingIterator::difference_type offset) {
66 return AdaptedConstIterator(m_iter + offset);
67 }
68
69 // Incrementable
70 AdaptedConstIterator &operator++() {
71 m_iter++;
72 return *this;
73 }
74
75 // Decrementable
76 AdaptedConstIterator &operator--() {
77 m_iter--;
78 return *this;
79 }
80
81 // Compound assignment
82 AdaptedConstIterator &
83 operator+=(typename BackingIterator::difference_type offset) {
84 m_iter += offset;
85 return *this;
86 }
87
88 AdaptedConstIterator &
89 operator-=(typename BackingIterator::difference_type offset) {
90 m_iter -= offset;
91 return *this;
92 }
93
94 // Arithmetic
95 AdaptedConstIterator
96 operator+(typename BackingIterator::difference_type offset) {
97 return AdaptedConstIterator(m_iter + offset);
98 }
99
100 AdaptedConstIterator
101 operator-(typename BackingIterator::difference_type offset) {
102 return AdaptedConstIterator(m_iter - offset);
103 }
104
105 // Comparable
106 bool operator<(AdaptedConstIterator &rhs) { return m_iter < rhs.m_iter; }
107
108 bool operator<=(AdaptedConstIterator &rhs) { return m_iter <= rhs.m_iter; }
109
110 bool operator>(AdaptedConstIterator &rhs) { return m_iter > rhs.m_iter; }
111
112 bool operator>=(AdaptedConstIterator &rhs) { return m_iter >= rhs.m_iter; }
113
114 template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
115 friend AdaptedConstIterator<C1, E1, A1>
116 operator+(typename C1::const_iterator::difference_type,
117 AdaptedConstIterator<C1, E1, A1> &);
118
119 template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
120 friend typename C1::const_iterator::difference_type
121 operator-(AdaptedConstIterator<C1, E1, A1> &,
122 AdaptedConstIterator<C1, E1, A1> &);
123
124 template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
125 friend void swap(AdaptedConstIterator<C1, E1, A1> &,
126 AdaptedConstIterator<C1, E1, A1> &);
127
128 private:
129 BackingIterator m_iter;
130 };
131
132 template <typename C, typename E, E (*A)(typename C::const_iterator &)>
133 AdaptedConstIterator<C, E, A> operator+(
134 typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type
135 offset,
136 AdaptedConstIterator<C, E, A> &rhs) {
137 return rhs.operator+(offset);
138 }
139
140 template <typename C, typename E, E (*A)(typename C::const_iterator &)>
141 typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type
142 operator-(AdaptedConstIterator<C, E, A> &lhs,
143 AdaptedConstIterator<C, E, A> &rhs) {
144 return (lhs.m_iter - rhs.m_iter);
145 }
146
147 template <typename C, typename E, E (*A)(typename C::const_iterator &)>
swap(AdaptedConstIterator<C,E,A> & lhs,AdaptedConstIterator<C,E,A> & rhs)148 void swap(AdaptedConstIterator<C, E, A> &lhs,
149 AdaptedConstIterator<C, E, A> &rhs) {
150 std::swap(lhs.m_iter, rhs.m_iter);
151 }
152
153 template <typename C, typename E, E (*A)(typename C::const_iterator &)>
154 class AdaptedIterable {
155 private:
156 const C &m_container;
157
158 public:
AdaptedIterable(const C & container)159 AdaptedIterable(const C &container) : m_container(container) {}
160
begin()161 AdaptedConstIterator<C, E, A> begin() {
162 return AdaptedConstIterator<C, E, A>(m_container.begin());
163 }
164
end()165 AdaptedConstIterator<C, E, A> end() {
166 return AdaptedConstIterator<C, E, A>(m_container.end());
167 }
168 };
169
170 template <typename C, typename E, E (*A)(typename C::const_iterator &),
171 typename MutexType>
172 class LockingAdaptedIterable : public AdaptedIterable<C, E, A> {
173 public:
LockingAdaptedIterable(C & container,MutexType & mutex)174 LockingAdaptedIterable(C &container, MutexType &mutex)
175 : AdaptedIterable<C, E, A>(container), m_mutex(&mutex) {
176 m_mutex->lock();
177 }
178
LockingAdaptedIterable(LockingAdaptedIterable && rhs)179 LockingAdaptedIterable(LockingAdaptedIterable &&rhs)
180 : AdaptedIterable<C, E, A>(rhs), m_mutex(rhs.m_mutex) {
181 rhs.m_mutex = nullptr;
182 }
183
~LockingAdaptedIterable()184 ~LockingAdaptedIterable() {
185 if (m_mutex)
186 m_mutex->unlock();
187 }
188
189 private:
190 MutexType *m_mutex = nullptr;
191
192 LockingAdaptedIterable(const LockingAdaptedIterable &) = delete;
193 LockingAdaptedIterable &operator=(const LockingAdaptedIterable &) = delete;
194 };
195
196 } // namespace lldb_private
197
198 #endif // liblldb_Iterable_h_
199