Update HOWTO document after creating the 2.42 branch
[binutils-gdb.git] / gdbsupport / range-chain.h
blobb6b711b428125e388a8c8ed8b6e8ed3219fe87a8
1 /* A range adapter that wraps multiple ranges
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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/>. */
19 #ifndef GDBSUPPORT_RANGE_CHAIN_H
20 #define GDBSUPPORT_RANGE_CHAIN_H
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
28 /* The type of the iterator that is created by this range. */
29 class iterator
31 public:
33 iterator (const std::vector<Range> &ranges, size_t idx)
34 : m_index (idx),
35 m_ranges (ranges)
37 skip_empty ();
40 bool operator== (const iterator &other) const
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;
51 bool operator!= (const iterator &other) const
53 return !(*this == other);
56 iterator &operator++ ()
58 ++*m_current;
59 if (*m_current == m_ranges[m_index].end ())
61 ++m_index;
62 skip_empty ();
64 return *this;
67 typename Range::iterator::value_type operator* () const
69 return **m_current;
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 ()
78 for (; m_index < m_ranges.size (); ++m_index)
80 m_current = m_ranges[m_index].begin ();
81 if (*m_current != m_ranges[m_index].end ())
82 return;
84 m_current.reset ();
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 std::optional<typename Range::iterator> m_current;
94 /* Vector of ranges. */
95 const std::vector<Range> &m_ranges;
98 /* Create a new range_chain. */
99 template<typename T>
100 range_chain (T &&ranges)
101 : m_ranges (std::forward<T> (ranges))
105 iterator begin () const
107 return iterator (m_ranges, 0);
110 iterator end () const
112 return iterator (m_ranges, m_ranges.size ());
115 private:
117 /* The sub-ranges. */
118 std::vector<Range> m_ranges;
121 #endif /* GDBSUPPORT_RANGE_CHAIN_H */