xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/safe-iterator.h (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
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