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(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