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