10b57cec5SDimitry Andric //===-- Iterable.h ----------------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9*5ffd83dbSDimitry Andric #ifndef LLDB_UTILITY_ITERABLE_H 10*5ffd83dbSDimitry Andric #define LLDB_UTILITY_ITERABLE_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <utility> 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric namespace lldb_private { 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric template <typename I, typename E> E map_adapter(I &iter) { 180b57cec5SDimitry Andric return iter->second; 190b57cec5SDimitry Andric } 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric template <typename I, typename E> E vector_adapter(I &iter) { return *iter; } 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric template <typename I, typename E> E list_adapter(I &iter) { return *iter; } 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &)> 260b57cec5SDimitry Andric class AdaptedConstIterator { 270b57cec5SDimitry Andric public: 280b57cec5SDimitry Andric typedef typename C::const_iterator BackingIterator; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric // Wrapping constructor 310b57cec5SDimitry Andric AdaptedConstIterator(BackingIterator backing_iterator) 320b57cec5SDimitry Andric : m_iter(backing_iterator) {} 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric // Default-constructible 350b57cec5SDimitry Andric AdaptedConstIterator() : m_iter() {} 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // Copy-constructible 380b57cec5SDimitry Andric AdaptedConstIterator(const AdaptedConstIterator &rhs) : m_iter(rhs.m_iter) {} 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric // Copy-assignable 410b57cec5SDimitry Andric AdaptedConstIterator &operator=(const AdaptedConstIterator &rhs) { 420b57cec5SDimitry Andric m_iter = rhs.m_iter; 430b57cec5SDimitry Andric return *this; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // Destructible 470b57cec5SDimitry Andric ~AdaptedConstIterator() = default; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric // Comparable 500b57cec5SDimitry Andric bool operator==(const AdaptedConstIterator &rhs) { 510b57cec5SDimitry Andric return m_iter == rhs.m_iter; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric bool operator!=(const AdaptedConstIterator &rhs) { 550b57cec5SDimitry Andric return m_iter != rhs.m_iter; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Rvalue dereferenceable 590b57cec5SDimitry Andric E operator*() { return (*A)(m_iter); } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric E operator->() { return (*A)(m_iter); } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Offset dereferenceable 640b57cec5SDimitry Andric E operator[](typename BackingIterator::difference_type offset) { 650b57cec5SDimitry Andric return AdaptedConstIterator(m_iter + offset); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // Incrementable 690b57cec5SDimitry Andric AdaptedConstIterator &operator++() { 700b57cec5SDimitry Andric m_iter++; 710b57cec5SDimitry Andric return *this; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Decrementable 750b57cec5SDimitry Andric AdaptedConstIterator &operator--() { 760b57cec5SDimitry Andric m_iter--; 770b57cec5SDimitry Andric return *this; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Compound assignment 810b57cec5SDimitry Andric AdaptedConstIterator & 820b57cec5SDimitry Andric operator+=(typename BackingIterator::difference_type offset) { 830b57cec5SDimitry Andric m_iter += offset; 840b57cec5SDimitry Andric return *this; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric AdaptedConstIterator & 880b57cec5SDimitry Andric operator-=(typename BackingIterator::difference_type offset) { 890b57cec5SDimitry Andric m_iter -= offset; 900b57cec5SDimitry Andric return *this; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Arithmetic 940b57cec5SDimitry Andric AdaptedConstIterator 950b57cec5SDimitry Andric operator+(typename BackingIterator::difference_type offset) { 960b57cec5SDimitry Andric return AdaptedConstIterator(m_iter + offset); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric AdaptedConstIterator 1000b57cec5SDimitry Andric operator-(typename BackingIterator::difference_type offset) { 1010b57cec5SDimitry Andric return AdaptedConstIterator(m_iter - offset); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // Comparable 1050b57cec5SDimitry Andric bool operator<(AdaptedConstIterator &rhs) { return m_iter < rhs.m_iter; } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric bool operator<=(AdaptedConstIterator &rhs) { return m_iter <= rhs.m_iter; } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric bool operator>(AdaptedConstIterator &rhs) { return m_iter > rhs.m_iter; } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric bool operator>=(AdaptedConstIterator &rhs) { return m_iter >= rhs.m_iter; } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)> 1140b57cec5SDimitry Andric friend AdaptedConstIterator<C1, E1, A1> 1150b57cec5SDimitry Andric operator+(typename C1::const_iterator::difference_type, 1160b57cec5SDimitry Andric AdaptedConstIterator<C1, E1, A1> &); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)> 1190b57cec5SDimitry Andric friend typename C1::const_iterator::difference_type 1200b57cec5SDimitry Andric operator-(AdaptedConstIterator<C1, E1, A1> &, 1210b57cec5SDimitry Andric AdaptedConstIterator<C1, E1, A1> &); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)> 1240b57cec5SDimitry Andric friend void swap(AdaptedConstIterator<C1, E1, A1> &, 1250b57cec5SDimitry Andric AdaptedConstIterator<C1, E1, A1> &); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric private: 1280b57cec5SDimitry Andric BackingIterator m_iter; 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &)> 1320b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> operator+( 1330b57cec5SDimitry Andric typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type 1340b57cec5SDimitry Andric offset, 1350b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> &rhs) { 1360b57cec5SDimitry Andric return rhs.operator+(offset); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &)> 1400b57cec5SDimitry Andric typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type 1410b57cec5SDimitry Andric operator-(AdaptedConstIterator<C, E, A> &lhs, 1420b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> &rhs) { 1430b57cec5SDimitry Andric return (lhs.m_iter - rhs.m_iter); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &)> 1470b57cec5SDimitry Andric void swap(AdaptedConstIterator<C, E, A> &lhs, 1480b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> &rhs) { 1490b57cec5SDimitry Andric std::swap(lhs.m_iter, rhs.m_iter); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &)> 1530b57cec5SDimitry Andric class AdaptedIterable { 1540b57cec5SDimitry Andric private: 1550b57cec5SDimitry Andric const C &m_container; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric public: 1580b57cec5SDimitry Andric AdaptedIterable(const C &container) : m_container(container) {} 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> begin() { 1610b57cec5SDimitry Andric return AdaptedConstIterator<C, E, A>(m_container.begin()); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric AdaptedConstIterator<C, E, A> end() { 1650b57cec5SDimitry Andric return AdaptedConstIterator<C, E, A>(m_container.end()); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric }; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric template <typename C, typename E, E (*A)(typename C::const_iterator &), 1700b57cec5SDimitry Andric typename MutexType> 1710b57cec5SDimitry Andric class LockingAdaptedIterable : public AdaptedIterable<C, E, A> { 1720b57cec5SDimitry Andric public: 1730b57cec5SDimitry Andric LockingAdaptedIterable(C &container, MutexType &mutex) 1740b57cec5SDimitry Andric : AdaptedIterable<C, E, A>(container), m_mutex(&mutex) { 1750b57cec5SDimitry Andric m_mutex->lock(); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric LockingAdaptedIterable(LockingAdaptedIterable &&rhs) 1790b57cec5SDimitry Andric : AdaptedIterable<C, E, A>(rhs), m_mutex(rhs.m_mutex) { 1800b57cec5SDimitry Andric rhs.m_mutex = nullptr; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric ~LockingAdaptedIterable() { 1840b57cec5SDimitry Andric if (m_mutex) 1850b57cec5SDimitry Andric m_mutex->unlock(); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric private: 1890b57cec5SDimitry Andric MutexType *m_mutex = nullptr; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric LockingAdaptedIterable(const LockingAdaptedIterable &) = delete; 1920b57cec5SDimitry Andric LockingAdaptedIterable &operator=(const LockingAdaptedIterable &) = delete; 1930b57cec5SDimitry Andric }; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric } // namespace lldb_private 1960b57cec5SDimitry Andric 197*5ffd83dbSDimitry Andric #endif // LLDB_UTILITY_ITERABLE_H 198