wxMaxima
CellIterators.h
Go to the documentation of this file.
1 // -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 //
3 // Copyright (C) 2020 Kuba Ober <kuba@bertec.com>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // SPDX-License-Identifier: GPL-2.0+
21 
27 #ifndef CELLITERATORS_H
28 #define CELLITERATORS_H
29 
30 #include <wx/debug.h>
31 #include <memory>
32 #include <type_traits>
33 
34 template <typename Cell> class CellListIterator final {
35  static_assert(std::is_class<Cell>::value, "The type argument must be a class");
36  Cell *m_ptr = {};
37 
38 public:
39  constexpr CellListIterator() = default;
40  constexpr explicit CellListIterator(const std::unique_ptr<Cell> &p)
41  : m_ptr(p.get()) {}
42  constexpr explicit CellListIterator(Cell *p) : m_ptr(p) {}
43  constexpr CellListIterator(const CellListIterator &o) = default;
44  constexpr CellListIterator &operator=(const CellListIterator &o) = default;
45  constexpr CellListIterator operator++(int) {
46  auto ret = *this;
47  return operator++(), ret;
48  }
49  // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
50  CellListIterator &operator++() {
51  if (m_ptr)
52  {
53  auto *const prev = m_ptr;
54  m_ptr = m_ptr->GetNext();
55  wxASSERT(prev != m_ptr);
56  }
57  return *this;
58  }
59  constexpr bool operator==(const CellListIterator &o) const {
60  return m_ptr == o.m_ptr;
61  }
62  constexpr bool operator!=(const CellListIterator &o) const {
63  return m_ptr != o.m_ptr;
64  }
65  constexpr operator bool() const { return m_ptr; }
66  constexpr operator Cell *() const { return m_ptr; }
67  constexpr Cell *operator->() const { return m_ptr; }
68 };
69 
70 template <typename Cell> class CellListAdapter final {
71  static_assert(std::is_class<Cell>::value, "The type argument must be a class");
72  Cell *m_cell = {};
75 
76 public:
77  explicit CellListAdapter(Cell *cell) : m_cell(cell) {}
78  constexpr iterator begin() const { return iterator(m_cell); }
79  constexpr iterator end() const { return {}; }
80  constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
81  constexpr const_iterator cend() const { return {}; }
82 };
83 
84 template <typename Cell>
85 class CellDrawListIterator final {
86  static_assert(std::is_class<Cell>::value, "The type argument must be a class");
87  Cell *m_ptr = {};
88 
89 public:
90  constexpr CellDrawListIterator() = default;
91  constexpr explicit CellDrawListIterator(const std::unique_ptr<Cell> &p) : m_ptr(p.get()) {}
92  constexpr explicit CellDrawListIterator(Cell *p) : m_ptr(p) {}
93  constexpr CellDrawListIterator(const CellDrawListIterator &o) = default;
94  constexpr CellDrawListIterator &operator=(const CellDrawListIterator &o) = default;
95  constexpr CellDrawListIterator operator++(int) {
96  auto ret = *this;
97  return operator++(), ret;
98  }
99  // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
100  CellDrawListIterator &operator++()
101  {
102  if (m_ptr)
103  {
104  auto *const prev = m_ptr;
105  m_ptr = m_ptr->GetNextToDraw();
106  wxASSERT(prev != m_ptr);
107  }
108  return *this;
109  }
110  constexpr bool operator==(const CellDrawListIterator &o) const
111  { return m_ptr == o.m_ptr; }
112  constexpr bool operator!=(const CellDrawListIterator &o) const
113  { return m_ptr != o.m_ptr; }
114  constexpr operator bool() const { return m_ptr; }
115  constexpr operator Cell*() const { return m_ptr; }
116  constexpr Cell *operator->() const { return m_ptr; }
117 };
118 
119 template <typename Cell> class CellDrawListAdapter final
120 {
121  static_assert(std::is_class<Cell>::value, "The type argument must be a class");
122  Cell *m_cell = {};
125 
126 public:
127  explicit CellDrawListAdapter(Cell *cell) : m_cell(cell) {}
128  constexpr iterator begin() const { return iterator(m_cell); }
129  constexpr iterator end() const { return {}; }
130  constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
131  constexpr const_iterator cend() const { return {}; }
132 };
133 
134 class Cell;
135 
138 {
139  enum class Advance { Always, OnlyIfNull };
140  const Cell *m_parentCell = {};
141  Cell *m_innerCell = {};
142  int16_t m_index = 0;
143  int16_t m_endIndex = 0;
144 
145  static int GetInnerCellCount(const Cell *cell);
146  static Cell *GetInnerCell(const Cell *cell, int index);
147 public:
148  InnerCellIterator() = default;
149  explicit InnerCellIterator(Cell *parentCell) :
150  m_parentCell(parentCell),
151  m_endIndex(parentCell ? GetInnerCellCount(parentCell) : 0)
152  {
153  FindFirstInnerCell();
154  }
155  InnerCellIterator(const InnerCellIterator &o) = default;
156  InnerCellIterator &operator=(const InnerCellIterator &o) = default;
157  InnerCellIterator operator++(int)
158  {
159  auto ret = *this;
160  return operator++(), ret;
161  }
162  InnerCellIterator &operator++()
163  {
164  if (m_parentCell)
165  AdvanceLoop(Advance::Always);
166  return *this;
167  }
168  bool operator==(const InnerCellIterator &o) const
169  { return m_innerCell == o.m_innerCell; }
170  bool operator!=(const InnerCellIterator &o) const
171  { return m_innerCell != o.m_innerCell; }
172  operator bool() const { return m_innerCell; }
173  operator Cell*() const { return m_innerCell; }
174  Cell *operator->() const { return m_innerCell; }
175 
176 private:
177  void FindFirstInnerCell();
178  void AdvanceLoop(Advance mode);
179 };
180 
181 inline void InnerCellIterator::FindFirstInnerCell()
182 {
183  if (m_endIndex)
184  {
185  m_innerCell = GetInnerCell(m_parentCell, 0);
186  AdvanceLoop(Advance::OnlyIfNull);
187  }
188 }
189 
190 inline void InnerCellIterator::AdvanceLoop(Advance mode)
191 {
192  Cell *prev = m_innerCell;
193  if (mode == Advance::OnlyIfNull && prev)
194  return;
195  for (;;)
196  {
197  ++ m_index;
198  if (m_index == m_endIndex)
199  {
200  m_innerCell = nullptr;
201  break;
202  }
203  m_innerCell = GetInnerCell(m_parentCell, m_index);
204  wxASSERT(!prev || prev != m_innerCell);
205  if (m_innerCell)
206  break;
207  }
208 }
209 
210 class InnerCellAdapter final {
211  using iterator = InnerCellIterator;
212  iterator const m_iter;
213 
214 public:
215  explicit InnerCellAdapter(const iterator &) = delete;
216  explicit InnerCellAdapter(Cell *cell) : m_iter(cell) {}
217  iterator begin() const { return m_iter; }
218  iterator end() const { return {}; }
219 };
220 
221 #endif
InnerCellIterator
Iterates the inner cells of a cell.
Definition: CellIterators.h:137
CellListAdapter
Definition: CellIterators.h:70
CellListIterator
Definition: CellIterators.h:34
Cell
Definition: Cell.h:139
Cell::GetNextToDraw
Cell * GetNextToDraw() const
Definition: Cell.h:631
Cell::GetNext
Cell * GetNext() const
Get the next cell in the list.
Definition: Cell.h:624
InnerCellAdapter
Definition: CellIterators.h:210
CellDrawListAdapter
Definition: CellIterators.h:119
CellDrawListIterator
Definition: CellIterators.h:85