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