1 /* A safe iterator for GDB, the GNU debugger. 2 Copyright (C) 2018-2023 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 COMMON_SAFE_ITERATOR_H 20 #define COMMON_SAFE_ITERATOR_H 21 22 /* A forward iterator that wraps Iterator, such that when iterating 23 with iterator IT, it is possible to delete *IT without invalidating 24 IT. Suitably wrapped in a range type and used with range-for, this 25 allow convenient patterns like this: 26 27 // range_safe() returns a range type whose begin()/end() methods 28 // return safe iterators. 29 for (foo *f : range_safe ()) 30 { 31 if (f->should_delete ()) 32 { 33 // The ++it operation implicitly done by the range-for is 34 // still OK after this. 35 delete f; 36 } 37 } 38 */ 39 40 template<typename Iterator> 41 class basic_safe_iterator 42 { 43 public: 44 typedef basic_safe_iterator self_type; 45 typedef typename Iterator::value_type value_type; 46 typedef typename Iterator::reference reference; 47 typedef typename Iterator::pointer pointer; 48 typedef typename Iterator::iterator_category iterator_category; 49 typedef typename Iterator::difference_type difference_type; 50 51 /* Construct the begin iterator using the given arguments; the end iterator is 52 default constructed. */ 53 template<typename... Args> 54 explicit basic_safe_iterator (Args &&...args) 55 : m_it (std::forward<Args> (args)...), 56 m_next (m_it) 57 { 58 if (m_it != m_end) 59 ++m_next; 60 } 61 62 /* Construct the iterator using the first argument, and construct 63 the end iterator using the second argument. */ 64 template<typename Arg> 65 explicit basic_safe_iterator (Arg &&arg, Arg &&arg2) 66 : m_it (std::forward<Arg> (arg)), 67 m_next (m_it), 68 m_end (std::forward<Arg> (arg2)) 69 { 70 if (m_it != m_end) 71 ++m_next; 72 } 73 74 /* Create a one-past-end iterator. */ 75 basic_safe_iterator () 76 {} 77 78 value_type operator* () const { return *m_it; } 79 80 self_type &operator++ () 81 { 82 m_it = m_next; 83 if (m_it != m_end) 84 ++m_next; 85 return *this; 86 } 87 88 bool operator== (const self_type &other) const 89 { return m_it == other.m_it; } 90 91 bool operator!= (const self_type &other) const 92 { return m_it != other.m_it; } 93 94 private: 95 /* The current element. */ 96 Iterator m_it {}; 97 98 /* The next element. Always one element ahead of M_IT. */ 99 Iterator m_next {}; 100 101 /* A one-past-end iterator. */ 102 Iterator m_end {}; 103 }; 104 105 /* A range adapter that wraps another range, and then returns safe 106 iterators wrapping the original range's iterators. */ 107 108 template<typename Range> 109 class basic_safe_range 110 { 111 public: 112 113 typedef basic_safe_iterator<typename Range::iterator> iterator; 114 115 explicit basic_safe_range (Range range) 116 : m_range (range) 117 { 118 } 119 120 iterator begin () 121 { 122 return iterator (m_range.begin (), m_range.end ()); 123 } 124 125 iterator end () 126 { 127 return iterator (m_range.end (), m_range.end ()); 128 } 129 130 private: 131 132 Range m_range; 133 }; 134 135 #endif /* COMMON_SAFE_ITERATOR_H */ 136