safe-iterator.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* A safe iterator for GDB, the GNU debugger.
  2. Copyright (C) 2018-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #ifndef COMMON_SAFE_ITERATOR_H
  15. #define COMMON_SAFE_ITERATOR_H
  16. /* A forward iterator that wraps Iterator, such that when iterating
  17. with iterator IT, it is possible to delete *IT without invalidating
  18. IT. Suitably wrapped in a range type and used with range-for, this
  19. allow convenient patterns like this:
  20. // range_safe() returns a range type whose begin()/end() methods
  21. // return safe iterators.
  22. for (foo *f : range_safe ())
  23. {
  24. if (f->should_delete ())
  25. {
  26. // The ++it operation implicitly done by the range-for is
  27. // still OK after this.
  28. delete f;
  29. }
  30. }
  31. */
  32. template<typename Iterator>
  33. class basic_safe_iterator
  34. {
  35. public:
  36. typedef basic_safe_iterator self_type;
  37. typedef typename Iterator::value_type value_type;
  38. typedef typename Iterator::reference reference;
  39. typedef typename Iterator::pointer pointer;
  40. typedef typename Iterator::iterator_category iterator_category;
  41. typedef typename Iterator::difference_type difference_type;
  42. /* Construct the begin iterator using the given arguments; the end iterator is
  43. default constructed. */
  44. template<typename... Args>
  45. explicit basic_safe_iterator (Args &&...args)
  46. : m_it (std::forward<Args> (args)...),
  47. m_next (m_it)
  48. {
  49. if (m_it != m_end)
  50. ++m_next;
  51. }
  52. /* Construct the iterator using the first argument, and construct
  53. the end iterator using the second argument. */
  54. template<typename Arg>
  55. explicit basic_safe_iterator (Arg &&arg, Arg &&arg2)
  56. : m_it (std::forward<Arg> (arg)),
  57. m_next (m_it),
  58. m_end (std::forward<Arg> (arg2))
  59. {
  60. if (m_it != m_end)
  61. ++m_next;
  62. }
  63. /* Create a one-past-end iterator. */
  64. basic_safe_iterator ()
  65. {}
  66. value_type operator* () const { return *m_it; }
  67. self_type &operator++ ()
  68. {
  69. m_it = m_next;
  70. if (m_it != m_end)
  71. ++m_next;
  72. return *this;
  73. }
  74. bool operator== (const self_type &other) const
  75. { return m_it == other.m_it; }
  76. bool operator!= (const self_type &other) const
  77. { return m_it != other.m_it; }
  78. private:
  79. /* The current element. */
  80. Iterator m_it {};
  81. /* The next element. Always one element ahead of M_IT. */
  82. Iterator m_next {};
  83. /* A one-past-end iterator. */
  84. Iterator m_end {};
  85. };
  86. /* A range adapter that wraps another range, and then returns safe
  87. iterators wrapping the original range's iterators. */
  88. template<typename Range>
  89. class basic_safe_range
  90. {
  91. public:
  92. typedef basic_safe_iterator<typename Range::iterator> iterator;
  93. explicit basic_safe_range (Range range)
  94. : m_range (range)
  95. {
  96. }
  97. iterator begin ()
  98. {
  99. return iterator (m_range.begin (), m_range.end ());
  100. }
  101. iterator end ()
  102. {
  103. return iterator (m_range.end (), m_range.end ());
  104. }
  105. private:
  106. Range m_range;
  107. };
  108. #endif /* COMMON_SAFE_ITERATOR_H */