18dffb485Schristos /* A safe iterator for GDB, the GNU debugger. 2*5ba1f45fSchristos Copyright (C) 2018-2024 Free Software Foundation, Inc. 38dffb485Schristos 48dffb485Schristos This file is part of GDB. 58dffb485Schristos 68dffb485Schristos This program is free software; you can redistribute it and/or modify 78dffb485Schristos it under the terms of the GNU General Public License as published by 88dffb485Schristos the Free Software Foundation; either version 3 of the License, or 98dffb485Schristos (at your option) any later version. 108dffb485Schristos 118dffb485Schristos This program is distributed in the hope that it will be useful, 128dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 138dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 148dffb485Schristos GNU General Public License for more details. 158dffb485Schristos 168dffb485Schristos You should have received a copy of the GNU General Public License 178dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 188dffb485Schristos 198dffb485Schristos #ifndef COMMON_SAFE_ITERATOR_H 208dffb485Schristos #define COMMON_SAFE_ITERATOR_H 218dffb485Schristos 22*5ba1f45fSchristos #include <type_traits> 23*5ba1f45fSchristos 248dffb485Schristos /* A forward iterator that wraps Iterator, such that when iterating 258dffb485Schristos with iterator IT, it is possible to delete *IT without invalidating 268dffb485Schristos IT. Suitably wrapped in a range type and used with range-for, this 278dffb485Schristos allow convenient patterns like this: 288dffb485Schristos 298dffb485Schristos // range_safe() returns a range type whose begin()/end() methods 308dffb485Schristos // return safe iterators. 318dffb485Schristos for (foo *f : range_safe ()) 328dffb485Schristos { 338dffb485Schristos if (f->should_delete ()) 348dffb485Schristos { 358dffb485Schristos // The ++it operation implicitly done by the range-for is 368dffb485Schristos // still OK after this. 378dffb485Schristos delete f; 388dffb485Schristos } 398dffb485Schristos } 408dffb485Schristos */ 418dffb485Schristos 428dffb485Schristos template<typename Iterator> 438dffb485Schristos class basic_safe_iterator 448dffb485Schristos { 458dffb485Schristos public: 468dffb485Schristos typedef basic_safe_iterator self_type; 478dffb485Schristos typedef typename Iterator::value_type value_type; 488dffb485Schristos typedef typename Iterator::reference reference; 498dffb485Schristos typedef typename Iterator::pointer pointer; 508dffb485Schristos typedef typename Iterator::iterator_category iterator_category; 518dffb485Schristos typedef typename Iterator::difference_type difference_type; 528dffb485Schristos 534b169a6bSchristos /* Construct the begin iterator using the given arguments; the end iterator is 544b169a6bSchristos default constructed. */ 554b169a6bSchristos template<typename... Args> 564b169a6bSchristos explicit basic_safe_iterator (Args &&...args) 574b169a6bSchristos : m_it (std::forward<Args> (args)...), 588dffb485Schristos m_next (m_it) 598dffb485Schristos { 608dffb485Schristos if (m_it != m_end) 618dffb485Schristos ++m_next; 628dffb485Schristos } 638dffb485Schristos 648dffb485Schristos /* Construct the iterator using the first argument, and construct 658dffb485Schristos the end iterator using the second argument. */ 668dffb485Schristos template<typename Arg> 678dffb485Schristos explicit basic_safe_iterator (Arg &&arg, Arg &&arg2) 688dffb485Schristos : m_it (std::forward<Arg> (arg)), 698dffb485Schristos m_next (m_it), 708dffb485Schristos m_end (std::forward<Arg> (arg2)) 718dffb485Schristos { 728dffb485Schristos if (m_it != m_end) 738dffb485Schristos ++m_next; 748dffb485Schristos } 758dffb485Schristos 768dffb485Schristos /* Create a one-past-end iterator. */ 778dffb485Schristos basic_safe_iterator () 788dffb485Schristos {} 798dffb485Schristos 80*5ba1f45fSchristos typename std::invoke_result<decltype(&Iterator::operator*), Iterator>::type 81*5ba1f45fSchristos operator* () const 82*5ba1f45fSchristos { return *m_it; } 838dffb485Schristos 848dffb485Schristos self_type &operator++ () 858dffb485Schristos { 868dffb485Schristos m_it = m_next; 878dffb485Schristos if (m_it != m_end) 888dffb485Schristos ++m_next; 898dffb485Schristos return *this; 908dffb485Schristos } 918dffb485Schristos 928dffb485Schristos bool operator== (const self_type &other) const 938dffb485Schristos { return m_it == other.m_it; } 948dffb485Schristos 958dffb485Schristos bool operator!= (const self_type &other) const 968dffb485Schristos { return m_it != other.m_it; } 978dffb485Schristos 988dffb485Schristos private: 998dffb485Schristos /* The current element. */ 1008dffb485Schristos Iterator m_it {}; 1018dffb485Schristos 1028dffb485Schristos /* The next element. Always one element ahead of M_IT. */ 1038dffb485Schristos Iterator m_next {}; 1048dffb485Schristos 1058dffb485Schristos /* A one-past-end iterator. */ 1068dffb485Schristos Iterator m_end {}; 1078dffb485Schristos }; 1088dffb485Schristos 1098dffb485Schristos /* A range adapter that wraps another range, and then returns safe 1108dffb485Schristos iterators wrapping the original range's iterators. */ 1118dffb485Schristos 1128dffb485Schristos template<typename Range> 1138dffb485Schristos class basic_safe_range 1148dffb485Schristos { 1158dffb485Schristos public: 1168dffb485Schristos 1178dffb485Schristos typedef basic_safe_iterator<typename Range::iterator> iterator; 1188dffb485Schristos 1198dffb485Schristos explicit basic_safe_range (Range range) 1208dffb485Schristos : m_range (range) 1218dffb485Schristos { 1228dffb485Schristos } 1238dffb485Schristos 1248dffb485Schristos iterator begin () 1258dffb485Schristos { 1268dffb485Schristos return iterator (m_range.begin (), m_range.end ()); 1278dffb485Schristos } 1288dffb485Schristos 1298dffb485Schristos iterator end () 1308dffb485Schristos { 1318dffb485Schristos return iterator (m_range.end (), m_range.end ()); 1328dffb485Schristos } 1338dffb485Schristos 1348dffb485Schristos private: 1358dffb485Schristos 1368dffb485Schristos Range m_range; 1378dffb485Schristos }; 1388dffb485Schristos 1398dffb485Schristos #endif /* COMMON_SAFE_ITERATOR_H */ 140