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
map_adapter(I & iter)17 template <typename I, typename E> E map_adapter(I &iter) {
18 return iter->second;
19 }
20
vector_adapter(I & iter)21 template <typename I, typename E> E vector_adapter(I &iter) { return *iter; }
22
list_adapter(I & iter)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
AdaptedConstIterator(BackingIterator backing_iterator)31 AdaptedConstIterator(BackingIterator backing_iterator)
32 : m_iter(backing_iterator) {}
33
34 // Default-constructible
AdaptedConstIterator()35 AdaptedConstIterator() : m_iter() {}
36
37 // Copy-constructible
AdaptedConstIterator(const AdaptedConstIterator & rhs)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 &)>
swap(AdaptedConstIterator<C,E,A> & lhs,AdaptedConstIterator<C,E,A> & rhs)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:
AdaptedIterable(const C & container)158 AdaptedIterable(const C &container) : m_container(container) {}
159
begin()160 AdaptedConstIterator<C, E, A> begin() {
161 return AdaptedConstIterator<C, E, A>(m_container.begin());
162 }
163
end()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:
LockingAdaptedIterable(C & container,MutexType & mutex)173 LockingAdaptedIterable(C &container, MutexType &mutex)
174 : AdaptedIterable<C, E, A>(container), m_mutex(&mutex) {
175 m_mutex->lock();
176 }
177
LockingAdaptedIterable(LockingAdaptedIterable && rhs)178 LockingAdaptedIterable(LockingAdaptedIterable &&rhs)
179 : AdaptedIterable<C, E, A>(rhs), m_mutex(rhs.m_mutex) {
180 rhs.m_mutex = nullptr;
181 }
182
~LockingAdaptedIterable()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