Document the ARM_CC_FOR_TARGET testsuite variable
[binutils-gdb.git] / gdbsupport / range-chain.h
1 /* A range adapter that wraps multiple ranges
2 Copyright (C) 2022 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #ifndef GDBSUPPORT_RANGE_CHAIN_H
20 #define GDBSUPPORT_RANGE_CHAIN_H
21
22 /* A range adapter that presents a number of ranges as if it were a
23 single range. That is, iterating over a range_chain will iterate
24 over each sub-range in order. */
25 template<typename Range>
26 struct range_chain
27 {
28 /* The type of the iterator that is created by this range. */
29 class iterator
30 {
31 public:
32
33 iterator (const std::vector<Range> &ranges, size_t idx)
34 : m_index (idx),
35 m_ranges (ranges)
36 {
37 skip_empty ();
38 }
39
40 bool operator== (const iterator &other) const
41 {
42 if (m_index != other.m_index || &m_ranges != &other.m_ranges)
43 return false;
44 if (m_current.has_value () != other.m_current.has_value ())
45 return false;
46 if (m_current.has_value ())
47 return *m_current == *other.m_current;
48 return true;
49 }
50
51 bool operator!= (const iterator &other) const
52 {
53 return !(*this == other);
54 }
55
56 iterator &operator++ ()
57 {
58 ++*m_current;
59 if (*m_current == m_ranges[m_index].end ())
60 {
61 ++m_index;
62 skip_empty ();
63 }
64 return *this;
65 }
66
67 typename Range::iterator::value_type operator* () const
68 {
69 return **m_current;
70 }
71
72 private:
73 /* Skip empty sub-ranges. If this finds a valid sub-range,
74 m_current is updated to point to its start; otherwise,
75 m_current is reset. */
76 void skip_empty ()
77 {
78 for (; m_index < m_ranges.size (); ++m_index)
79 {
80 m_current = m_ranges[m_index].begin ();
81 if (*m_current != m_ranges[m_index].end ())
82 return;
83 }
84 m_current.reset ();
85 }
86
87 /* Index into the vector indicating where the current iterator
88 comes from. */
89 size_t m_index;
90 /* The current iterator into one of the vector ranges. If no
91 value then this (outer) iterator is at the end of the overall
92 range. */
93 gdb::optional<typename Range::iterator> m_current;
94 /* Vector of ranges. */
95 const std::vector<Range> &m_ranges;
96 };
97
98 /* Create a new range_chain. */
99 template<typename T>
100 range_chain (T &&ranges)
101 : m_ranges (std::forward<T> (ranges))
102 {
103 }
104
105 iterator begin () const
106 {
107 return iterator (m_ranges, 0);
108 }
109
110 iterator end () const
111 {
112 return iterator (m_ranges, m_ranges.size ());
113 }
114
115 private:
116
117 /* The sub-ranges. */
118 std::vector<Range> m_ranges;
119 };
120
121 #endif /* GDBSUPPORT_RANGE_CHAIN_H */