xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/range-chain.h (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
14b169a6bSchristos /* A range adapter that wraps multiple ranges
2*5ba1f45fSchristos    Copyright (C) 2022-2024 Free Software Foundation, Inc.
34b169a6bSchristos 
44b169a6bSchristos    This file is part of GDB.
54b169a6bSchristos 
64b169a6bSchristos    This program is free software; you can redistribute it and/or modify
74b169a6bSchristos    it under the terms of the GNU General Public License as published by
84b169a6bSchristos    the Free Software Foundation; either version 3 of the License, or
94b169a6bSchristos    (at your option) any later version.
104b169a6bSchristos 
114b169a6bSchristos    This program is distributed in the hope that it will be useful,
124b169a6bSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
134b169a6bSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144b169a6bSchristos    GNU General Public License for more details.
154b169a6bSchristos 
164b169a6bSchristos    You should have received a copy of the GNU General Public License
174b169a6bSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
184b169a6bSchristos 
194b169a6bSchristos #ifndef GDBSUPPORT_RANGE_CHAIN_H
204b169a6bSchristos #define GDBSUPPORT_RANGE_CHAIN_H
214b169a6bSchristos 
224b169a6bSchristos /* A range adapter that presents a number of ranges as if it were a
234b169a6bSchristos    single range.  That is, iterating over a range_chain will iterate
244b169a6bSchristos    over each sub-range in order.  */
254b169a6bSchristos template<typename Range>
264b169a6bSchristos struct range_chain
274b169a6bSchristos {
284b169a6bSchristos   /* The type of the iterator that is created by this range.  */
294b169a6bSchristos   class iterator
304b169a6bSchristos   {
314b169a6bSchristos   public:
324b169a6bSchristos 
334b169a6bSchristos     iterator (const std::vector<Range> &ranges, size_t idx)
344b169a6bSchristos       : m_index (idx),
354b169a6bSchristos 	m_ranges (ranges)
364b169a6bSchristos     {
374b169a6bSchristos       skip_empty ();
384b169a6bSchristos     }
394b169a6bSchristos 
404b169a6bSchristos     bool operator== (const iterator &other) const
414b169a6bSchristos     {
424b169a6bSchristos       if (m_index != other.m_index || &m_ranges != &other.m_ranges)
434b169a6bSchristos 	return false;
444b169a6bSchristos       if (m_current.has_value () != other.m_current.has_value ())
454b169a6bSchristos 	return false;
464b169a6bSchristos       if (m_current.has_value ())
474b169a6bSchristos 	return *m_current == *other.m_current;
484b169a6bSchristos       return true;
494b169a6bSchristos     }
504b169a6bSchristos 
514b169a6bSchristos     bool operator!= (const iterator &other) const
524b169a6bSchristos     {
534b169a6bSchristos       return !(*this == other);
544b169a6bSchristos     }
554b169a6bSchristos 
564b169a6bSchristos     iterator &operator++ ()
574b169a6bSchristos     {
584b169a6bSchristos       ++*m_current;
594b169a6bSchristos       if (*m_current == m_ranges[m_index].end ())
604b169a6bSchristos 	{
614b169a6bSchristos 	  ++m_index;
624b169a6bSchristos 	  skip_empty ();
634b169a6bSchristos 	}
644b169a6bSchristos       return *this;
654b169a6bSchristos     }
664b169a6bSchristos 
674b169a6bSchristos     typename Range::iterator::value_type operator* () const
684b169a6bSchristos     {
694b169a6bSchristos       return **m_current;
704b169a6bSchristos     }
714b169a6bSchristos 
724b169a6bSchristos   private:
734b169a6bSchristos     /* Skip empty sub-ranges.  If this finds a valid sub-range,
744b169a6bSchristos        m_current is updated to point to its start; otherwise,
754b169a6bSchristos        m_current is reset.  */
764b169a6bSchristos     void skip_empty ()
774b169a6bSchristos     {
784b169a6bSchristos       for (; m_index < m_ranges.size (); ++m_index)
794b169a6bSchristos 	{
804b169a6bSchristos 	  m_current = m_ranges[m_index].begin ();
814b169a6bSchristos 	  if (*m_current != m_ranges[m_index].end ())
824b169a6bSchristos 	    return;
834b169a6bSchristos 	}
844b169a6bSchristos       m_current.reset ();
854b169a6bSchristos     }
864b169a6bSchristos 
874b169a6bSchristos     /* Index into the vector indicating where the current iterator
884b169a6bSchristos        comes from.  */
894b169a6bSchristos     size_t m_index;
904b169a6bSchristos     /* The current iterator into one of the vector ranges.  If no
914b169a6bSchristos        value then this (outer) iterator is at the end of the overall
924b169a6bSchristos        range.  */
93*5ba1f45fSchristos     std::optional<typename Range::iterator> m_current;
944b169a6bSchristos     /* Vector of ranges.  */
954b169a6bSchristos     const std::vector<Range> &m_ranges;
964b169a6bSchristos   };
974b169a6bSchristos 
984b169a6bSchristos   /* Create a new range_chain.  */
994b169a6bSchristos   template<typename T>
1004b169a6bSchristos   range_chain (T &&ranges)
1014b169a6bSchristos     : m_ranges (std::forward<T> (ranges))
1024b169a6bSchristos   {
1034b169a6bSchristos   }
1044b169a6bSchristos 
1054b169a6bSchristos   iterator begin () const
1064b169a6bSchristos   {
1074b169a6bSchristos     return iterator (m_ranges, 0);
1084b169a6bSchristos   }
1094b169a6bSchristos 
1104b169a6bSchristos   iterator end () const
1114b169a6bSchristos   {
1124b169a6bSchristos     return iterator (m_ranges, m_ranges.size ());
1134b169a6bSchristos   }
1144b169a6bSchristos 
1154b169a6bSchristos private:
1164b169a6bSchristos 
1174b169a6bSchristos   /* The sub-ranges.  */
1184b169a6bSchristos   std::vector<Range> m_ranges;
1194b169a6bSchristos };
1204b169a6bSchristos 
1214b169a6bSchristos #endif /* GDBSUPPORT_RANGE_CHAIN_H */
122