1258882Semaste//===-- Iterable.h ----------------------------------------------*- C++ -*-===//
2258882Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6258882Semaste//
7258882Semaste//===----------------------------------------------------------------------===//
8258882Semaste
9258882Semaste#ifndef liblldb_Iterable_h_
10258882Semaste#define liblldb_Iterable_h_
11258882Semaste
12296417Sdim#include <utility>
13296417Sdim
14258882Semaste
15314564Sdimnamespace lldb_private {
16314564Sdim
17314564Sdimtemplate <typename I, typename E> E map_adapter(I &iter) {
18314564Sdim  return iter->second;
19258882Semaste}
20314564Sdim
21314564Sdimtemplate <typename I, typename E> E vector_adapter(I &iter) { return *iter; }
22314564Sdim
23314564Sdimtemplate <typename I, typename E> E list_adapter(I &iter) { return *iter; }
24314564Sdim
25314564Sdimtemplate <typename C, typename E, E (*A)(typename C::const_iterator &)>
26314564Sdimclass AdaptedConstIterator {
27258882Semastepublic:
28314564Sdim  typedef typename C::const_iterator BackingIterator;
29296417Sdim
30314564Sdim  // Wrapping constructor
31314564Sdim  AdaptedConstIterator(BackingIterator backing_iterator)
32314564Sdim      : m_iter(backing_iterator) {}
33262528Semaste
34314564Sdim  // Default-constructible
35314564Sdim  AdaptedConstIterator() : m_iter() {}
36262528Semaste
37314564Sdim  // Copy-constructible
38314564Sdim  AdaptedConstIterator(const AdaptedConstIterator &rhs) : m_iter(rhs.m_iter) {}
39296417Sdim
40314564Sdim  // Copy-assignable
41314564Sdim  AdaptedConstIterator &operator=(const AdaptedConstIterator &rhs) {
42314564Sdim    m_iter = rhs.m_iter;
43314564Sdim    return *this;
44314564Sdim  }
45314564Sdim
46314564Sdim  // Destructible
47314564Sdim  ~AdaptedConstIterator() = default;
48314564Sdim
49314564Sdim  // Comparable
50314564Sdim  bool operator==(const AdaptedConstIterator &rhs) {
51314564Sdim    return m_iter == rhs.m_iter;
52314564Sdim  }
53314564Sdim
54314564Sdim  bool operator!=(const AdaptedConstIterator &rhs) {
55314564Sdim    return m_iter != rhs.m_iter;
56314564Sdim  }
57314564Sdim
58314564Sdim  // Rvalue dereferenceable
59314564Sdim  E operator*() { return (*A)(m_iter); }
60314564Sdim
61314564Sdim  E operator->() { return (*A)(m_iter); }
62314564Sdim
63314564Sdim  // Offset dereferenceable
64314564Sdim  E operator[](typename BackingIterator::difference_type offset) {
65314564Sdim    return AdaptedConstIterator(m_iter + offset);
66314564Sdim  }
67314564Sdim
68314564Sdim  // Incrementable
69314564Sdim  AdaptedConstIterator &operator++() {
70314564Sdim    m_iter++;
71314564Sdim    return *this;
72314564Sdim  }
73314564Sdim
74314564Sdim  // Decrementable
75314564Sdim  AdaptedConstIterator &operator--() {
76314564Sdim    m_iter--;
77314564Sdim    return *this;
78314564Sdim  }
79314564Sdim
80314564Sdim  // Compound assignment
81314564Sdim  AdaptedConstIterator &
82314564Sdim  operator+=(typename BackingIterator::difference_type offset) {
83314564Sdim    m_iter += offset;
84314564Sdim    return *this;
85314564Sdim  }
86314564Sdim
87314564Sdim  AdaptedConstIterator &
88314564Sdim  operator-=(typename BackingIterator::difference_type offset) {
89314564Sdim    m_iter -= offset;
90314564Sdim    return *this;
91314564Sdim  }
92314564Sdim
93314564Sdim  // Arithmetic
94314564Sdim  AdaptedConstIterator
95314564Sdim  operator+(typename BackingIterator::difference_type offset) {
96314564Sdim    return AdaptedConstIterator(m_iter + offset);
97314564Sdim  }
98314564Sdim
99314564Sdim  AdaptedConstIterator
100314564Sdim  operator-(typename BackingIterator::difference_type offset) {
101314564Sdim    return AdaptedConstIterator(m_iter - offset);
102314564Sdim  }
103314564Sdim
104314564Sdim  // Comparable
105314564Sdim  bool operator<(AdaptedConstIterator &rhs) { return m_iter < rhs.m_iter; }
106314564Sdim
107314564Sdim  bool operator<=(AdaptedConstIterator &rhs) { return m_iter <= rhs.m_iter; }
108314564Sdim
109314564Sdim  bool operator>(AdaptedConstIterator &rhs) { return m_iter > rhs.m_iter; }
110314564Sdim
111314564Sdim  bool operator>=(AdaptedConstIterator &rhs) { return m_iter >= rhs.m_iter; }
112314564Sdim
113314564Sdim  template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
114314564Sdim  friend AdaptedConstIterator<C1, E1, A1>
115314564Sdim  operator+(typename C1::const_iterator::difference_type,
116314564Sdim            AdaptedConstIterator<C1, E1, A1> &);
117314564Sdim
118314564Sdim  template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
119314564Sdim  friend typename C1::const_iterator::difference_type
120314564Sdim  operator-(AdaptedConstIterator<C1, E1, A1> &,
121314564Sdim            AdaptedConstIterator<C1, E1, A1> &);
122314564Sdim
123314564Sdim  template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
124314564Sdim  friend void swap(AdaptedConstIterator<C1, E1, A1> &,
125314564Sdim                   AdaptedConstIterator<C1, E1, A1> &);
126314564Sdim
127296417Sdimprivate:
128314564Sdim  BackingIterator m_iter;
129258882Semaste};
130314564Sdim
131258882Semastetemplate <typename C, typename E, E (*A)(typename C::const_iterator &)>
132314564SdimAdaptedConstIterator<C, E, A> operator+(
133314564Sdim    typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type
134314564Sdim        offset,
135314564Sdim    AdaptedConstIterator<C, E, A> &rhs) {
136314564Sdim  return rhs.operator+(offset);
137258882Semaste}
138258882Semaste
139258882Semastetemplate <typename C, typename E, E (*A)(typename C::const_iterator &)>
140314564Sdimtypename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type
141314564Sdimoperator-(AdaptedConstIterator<C, E, A> &lhs,
142314564Sdim          AdaptedConstIterator<C, E, A> &rhs) {
143314564Sdim  return (lhs.m_iter - rhs.m_iter);
144258882Semaste}
145258882Semaste
146258882Semastetemplate <typename C, typename E, E (*A)(typename C::const_iterator &)>
147314564Sdimvoid swap(AdaptedConstIterator<C, E, A> &lhs,
148314564Sdim          AdaptedConstIterator<C, E, A> &rhs) {
149314564Sdim  std::swap(lhs.m_iter, rhs.m_iter);
150258882Semaste}
151314564Sdim
152314564Sdimtemplate <typename C, typename E, E (*A)(typename C::const_iterator &)>
153314564Sdimclass AdaptedIterable {
154258882Semasteprivate:
155314564Sdim  const C &m_container;
156314564Sdim
157258882Semastepublic:
158314564Sdim  AdaptedIterable(const C &container) : m_container(container) {}
159314564Sdim
160314564Sdim  AdaptedConstIterator<C, E, A> begin() {
161314564Sdim    return AdaptedConstIterator<C, E, A>(m_container.begin());
162314564Sdim  }
163314564Sdim
164314564Sdim  AdaptedConstIterator<C, E, A> end() {
165314564Sdim    return AdaptedConstIterator<C, E, A>(m_container.end());
166314564Sdim  }
167258882Semaste};
168309124Sdim
169314564Sdimtemplate <typename C, typename E, E (*A)(typename C::const_iterator &),
170314564Sdim          typename MutexType>
171314564Sdimclass LockingAdaptedIterable : public AdaptedIterable<C, E, A> {
172258882Semastepublic:
173314564Sdim  LockingAdaptedIterable(C &container, MutexType &mutex)
174314564Sdim      : AdaptedIterable<C, E, A>(container), m_mutex(&mutex) {
175314564Sdim    m_mutex->lock();
176314564Sdim  }
177309124Sdim
178314564Sdim  LockingAdaptedIterable(LockingAdaptedIterable &&rhs)
179314564Sdim      : AdaptedIterable<C, E, A>(rhs), m_mutex(rhs.m_mutex) {
180314564Sdim    rhs.m_mutex = nullptr;
181314564Sdim  }
182309124Sdim
183314564Sdim  ~LockingAdaptedIterable() {
184314564Sdim    if (m_mutex)
185314564Sdim      m_mutex->unlock();
186314564Sdim  }
187309124Sdim
188258882Semasteprivate:
189314564Sdim  MutexType *m_mutex = nullptr;
190296417Sdim
191314564Sdim  LockingAdaptedIterable(const LockingAdaptedIterable &) = delete;
192314564Sdim  LockingAdaptedIterable &operator=(const LockingAdaptedIterable &) = delete;
193258882Semaste};
194309124Sdim
195296417Sdim} // namespace lldb_private
196258882Semaste
197296417Sdim#endif // liblldb_Iterable_h_
198