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