]> Git Repo - binutils.git/blob - gdbsupport/range-chain.h
Automatic date update in version.in
[binutils.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 */
This page took 0.028525 seconds and 4 git commands to generate.