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