diff options
Diffstat (limited to 'gdbsupport/safe-iterator.h')
-rw-r--r-- | gdbsupport/safe-iterator.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/gdbsupport/safe-iterator.h b/gdbsupport/safe-iterator.h new file mode 100644 index 0000000..04fe52a --- /dev/null +++ b/gdbsupport/safe-iterator.h @@ -0,0 +1,135 @@ +/* A safe iterator for GDB, the GNU debugger. + Copyright (C) 2018-2020 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef COMMON_SAFE_ITERATOR_H +#define COMMON_SAFE_ITERATOR_H + +/* A forward iterator that wraps Iterator, such that when iterating + with iterator IT, it is possible to delete *IT without invalidating + IT. Suitably wrapped in a range type and used with range-for, this + allow convenient patterns like this: + + // range_safe() returns a range type whose begin()/end() methods + // return safe iterators. + for (foo *f : range_safe ()) + { + if (f->should_delete ()) + { + // The ++it operation implicitly done by the range-for is + // still OK after this. + delete f; + } + } +*/ + +template<typename Iterator> +class basic_safe_iterator +{ +public: + typedef basic_safe_iterator self_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::reference reference; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::iterator_category iterator_category; + typedef typename Iterator::difference_type difference_type; + + /* Construct using the given argument; the end iterator is default + constructed. */ + template<typename Arg> + explicit basic_safe_iterator (Arg &&arg) + : m_it (std::forward<Arg> (arg)), + m_next (m_it) + { + if (m_it != m_end) + ++m_next; + } + + /* Construct the iterator using the first argument, and construct + the end iterator using the second argument. */ + template<typename Arg> + explicit basic_safe_iterator (Arg &&arg, Arg &&arg2) + : m_it (std::forward<Arg> (arg)), + m_next (m_it), + m_end (std::forward<Arg> (arg2)) + { + if (m_it != m_end) + ++m_next; + } + + /* Create a one-past-end iterator. */ + basic_safe_iterator () + {} + + value_type operator* () const { return *m_it; } + + self_type &operator++ () + { + m_it = m_next; + if (m_it != m_end) + ++m_next; + return *this; + } + + bool operator== (const self_type &other) const + { return m_it == other.m_it; } + + bool operator!= (const self_type &other) const + { return m_it != other.m_it; } + +private: + /* The current element. */ + Iterator m_it {}; + + /* The next element. Always one element ahead of M_IT. */ + Iterator m_next {}; + + /* A one-past-end iterator. */ + Iterator m_end {}; +}; + +/* A range adapter that wraps another range, and then returns safe + iterators wrapping the original range's iterators. */ + +template<typename Range> +class basic_safe_range +{ +public: + + typedef basic_safe_iterator<typename Range::iterator> iterator; + + explicit basic_safe_range (Range range) + : m_range (range) + { + } + + iterator begin () + { + return iterator (m_range.begin (), m_range.end ()); + } + + iterator end () + { + return iterator (m_range.end (), m_range.end ()); + } + +private: + + Range m_range; +}; + +#endif /* COMMON_SAFE_ITERATOR_H */ |