wxMaxima
Loading...
Searching...
No Matches
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#include <iterator>
34
35template <typename Cell> class CellListIterator final {
36 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
37 Cell *m_ptr = {};
38
39public:
40 using iterator_category = std::forward_iterator_tag;
41 using value_type = Cell;
42 using difference_type = std::ptrdiff_t;
43 using pointer = Cell *;
44 using reference = Cell &;
45
46 constexpr CellListIterator() = default;
47 constexpr explicit CellListIterator(const std::unique_ptr<Cell> &p)
48 : m_ptr(p.get()) {}
49 constexpr explicit CellListIterator(Cell *p) : m_ptr(p) {}
50 constexpr CellListIterator(const CellListIterator &o) = default;
51 constexpr CellListIterator &operator=(const CellListIterator &o) = default;
52 constexpr CellListIterator operator++(int) {
53 auto ret = *this;
54 return operator++(), ret;
55 }
56 // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
57 CellListIterator &operator++() {
58 if (m_ptr)
59 {
60 const auto *const prev = m_ptr;
61 m_ptr = m_ptr->GetNext();
62 wxASSERT(prev != m_ptr);
63 }
64 return *this;
65 }
66 constexpr bool operator==(const CellListIterator &o) const {
67 return m_ptr == o.m_ptr;
68 }
69 constexpr bool operator!=(const CellListIterator &o) const {
70 return m_ptr != o.m_ptr;
71 }
72 constexpr operator bool() const { return m_ptr; }
73 constexpr operator Cell *() const { return m_ptr; }
74 constexpr Cell *operator->() const { return m_ptr; }
75};
76
77template <typename Cell> class CellListAdapter final {
78 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
79 Cell *m_cell = {};
82
83public:
84 explicit CellListAdapter(Cell *cell) : m_cell(cell) {}
85 constexpr iterator begin() const { return iterator(m_cell); }
86 static constexpr iterator end() { return {}; }
87 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
88 static constexpr const_iterator cend() { return {}; }
89};
90
91template <typename Cell>
93 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
94 Cell *m_ptr = {};
95
96public:
97 using iterator_category = std::forward_iterator_tag;
98 using value_type = Cell;
99 using difference_type = std::ptrdiff_t;
100 using pointer = Cell *;
101 using reference = Cell &;
102
103 constexpr CellDrawListIterator() = default;
104 constexpr explicit CellDrawListIterator(const std::unique_ptr<Cell> &p) : m_ptr(p.get()) {}
105 constexpr explicit CellDrawListIterator(Cell *p) : m_ptr(p) {}
106 constexpr CellDrawListIterator(const CellDrawListIterator &o) = default;
107 constexpr CellDrawListIterator &operator=(const CellDrawListIterator &o) = default;
108 constexpr CellDrawListIterator operator++(int) {
109 auto ret = *this;
110 return operator++(), ret;
111 }
112 // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
113 CellDrawListIterator &operator++()
114 {
115 if (m_ptr)
116 {
117 const auto *const prev = m_ptr;
118 m_ptr = m_ptr->GetNextToDraw();
119 wxASSERT(prev != m_ptr);
120 }
121 return *this;
122 }
123 constexpr bool operator==(const CellDrawListIterator &o) const
124 { return m_ptr == o.m_ptr; }
125 constexpr bool operator!=(const CellDrawListIterator &o) const
126 { return m_ptr != o.m_ptr; }
127 constexpr operator bool() const { return m_ptr; }
128 constexpr operator Cell*() const { return m_ptr; }
129 constexpr Cell *operator->() const { return m_ptr; }
130};
131
132template <typename Cell> class CellDrawListAdapter final
133{
134 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
135 Cell *m_cell = {};
138
139public:
140 explicit CellDrawListAdapter(Cell *cell) : m_cell(cell) {}
141 constexpr iterator begin() const { return iterator(m_cell); }
142 static constexpr iterator end() { return {}; }
143 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
144 static constexpr const_iterator cend() { return {}; }
145};
146
147class Cell;
148
151{
152 enum class Advance { Always, OnlyIfNull };
153 const Cell *m_parentCell = {};
154 Cell *m_innerCell = {};
155 size_t m_index = 0;
156 size_t m_endIndex = 0;
157
158 static size_t GetInnerCellCount(const Cell *cell);
159 static Cell *GetInnerCell(const Cell *cell, size_t index);
160public:
161 using iterator_category = std::forward_iterator_tag;
162 using value_type = Cell;
163 using difference_type = std::ptrdiff_t;
164 using pointer = Cell *;
165 using reference = Cell &;
166
167 InnerCellIterator() = default;
168 explicit InnerCellIterator(Cell *parentCell) :
169 m_parentCell(parentCell),
170 m_endIndex(parentCell ? GetInnerCellCount(parentCell) : 0)
171 {
172 FindFirstInnerCell();
173 }
174 InnerCellIterator(const InnerCellIterator &o) = default;
175 InnerCellIterator &operator=(const InnerCellIterator &o) = default;
176 InnerCellIterator operator++(int)
177 {
178 auto ret = *this;
179 return operator++(), ret;
180 }
181 InnerCellIterator &operator++()
182 {
183 if (m_parentCell)
184 AdvanceLoop(Advance::Always);
185 return *this;
186 }
187 bool operator==(const InnerCellIterator &o) const
188 { return m_innerCell == o.m_innerCell; }
189 bool operator!=(const InnerCellIterator &o) const
190 { return m_innerCell != o.m_innerCell; }
191 operator bool() const { return m_innerCell; }
192 operator Cell*() const { return m_innerCell; }
193 Cell *operator->() const { return m_innerCell; }
194
195private:
196 void FindFirstInnerCell();
197 void AdvanceLoop(Advance mode);
198};
199
200inline void InnerCellIterator::FindFirstInnerCell()
201{
202 if (m_endIndex)
203 {
204 m_innerCell = GetInnerCell(m_parentCell, 0);
205 AdvanceLoop(Advance::OnlyIfNull);
206 }
207}
208
209inline void InnerCellIterator::AdvanceLoop(Advance mode)
210{
211 const Cell *prev = m_innerCell;
212 if (mode == Advance::OnlyIfNull && prev)
213 return;
214 for (;;)
215 {
216 ++m_index;
217 if (m_index == m_endIndex)
218 {
219 m_innerCell = nullptr;
220 break;
221 }
222 m_innerCell = GetInnerCell(m_parentCell, m_index);
223 wxASSERT(!prev || prev != m_innerCell);
224 if (m_innerCell)
225 break;
226 }
227}
228
229class InnerCellAdapter final {
231 iterator const m_iter;
232
233public:
234 explicit InnerCellAdapter(const iterator &) = delete;
235 explicit InnerCellAdapter(Cell *cell) : m_iter(cell) {}
236 iterator begin() const { return m_iter; }
237 static iterator end() { return {}; }
238};
239
240#endif
Definition: CellIterators.h:133
Definition: CellIterators.h:92
Definition: CellIterators.h:77
Definition: CellIterators.h:35
The base class all cell types the worksheet can consist of are derived from.
Definition: Cell.h:142
Cell * GetNextToDraw() const
Get the next cell that needs to be drawn.
Definition: Cell.h:741
Cell * GetNext() const
Get the next cell in the list.
Definition: Cell.h:734
Definition: CellIterators.h:229
Iterates the inner cells of a cell.
Definition: CellIterators.h:151