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