KiCad PCB EDA Suite
Loading...
Searching...
No Matches
multivector.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright 2017 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Maciej Suminski <[email protected]>
8 * @author Bernhard Stegmaier <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#ifndef MULTIVECTOR_H
25#define MULTIVECTOR_H
26
27#include <wx/debug.h>
28#include <boost/ptr_container/ptr_vector.hpp>
29#include <stdexcept>
30
41template<typename T, int FIRST_TYPE_VAL, int LAST_TYPE_VAL>
43{
44public:
49 static constexpr int UNDEFINED_TYPE = 0;
50 static_assert( FIRST_TYPE_VAL > UNDEFINED_TYPE,
51 "FIRST_TYPE_VAL must be greater than UNDEFINED_TYPE" );
52 static_assert( FIRST_TYPE_VAL < LAST_TYPE_VAL,
53 "FIRST_TYPE_VAL must be greater than LAST_TYPE_VAL" );
54
61 typedef boost::ptr_vector<T> ITEM_PTR_VECTOR;
62
66 template<typename ITEM_TYPE, typename ITEM_CONTAINER, typename ITEM_CONTAINER_IT>
68 {
69 public:
70 ITEM_TYPE& operator*()
71 {
72 return *m_it;
73 }
74
75 ITEM_TYPE* operator->()
76 {
77 return &( *m_it );
78 }
79
81 {
82 if( m_it != (*m_parent)[ m_curType ].end() )
83 ++m_it;
84
85 validate();
86
87 return *this;
88 }
89
90 bool operator!=( const ITERATOR_BASE& aOther ) const
91 {
92 if( aOther.m_parent != m_parent )
93 return true;
94
95 if( aOther.m_filter != m_filter )
96 return true;
97
98 if( aOther.m_curType != m_curType )
99 return true;
100
101 return aOther.m_it != m_it;
102 }
103
104 protected:
113 ITERATOR_BASE( ITEM_CONTAINER* aItems, ITEM_CONTAINER_IT aIt,
114 int aBucket, int aType = UNDEFINED_TYPE )
115 : m_parent( aItems ), m_it( aIt ), m_curType( aBucket )
116 {
117 m_filter = ( aType != UNDEFINED_TYPE );
118 }
119
121 void validate()
122 {
123 // for all-items iterators (unfiltered): check if this is the end of the
124 // current type container, if so switch to the next non-empty container
125 if( !m_filter && m_it == (*m_parent)[ m_curType ].end() )
126 {
127 // switch to the next type (look for a not empty container)
128 int nextType = m_curType;
129
130 do
131 ++nextType;
132 while( ( nextType <= LAST_TYPE ) && (*m_parent)[ nextType ].empty() );
133
134 // there is another not empty container, so make the iterator point to it,
135 // otherwise it means the iterator points to the last item
136 if( nextType <= LAST_TYPE )
137 {
138 m_curType = nextType;
139 m_it = (*m_parent)[ m_curType ].begin();
140 }
141 }
142 }
143
145 ITEM_CONTAINER* m_parent;
146
148 ITEM_CONTAINER_IT m_it;
149
152
155
156 friend class MULTIVECTOR;
157 };
158
161 typename ITEM_PTR_VECTOR::iterator> ITERATOR;
163 typedef ITERATOR_BASE<const T, const MULTIVECTOR<T, FIRST_TYPE_VAL, LAST_TYPE_VAL>,
164 typename ITEM_PTR_VECTOR::const_iterator> CONST_ITERATOR;
165
166
168 {
169 }
170
171 void push_back( T* aItem )
172 {
173 operator[]( aItem->Type() ).push_back( aItem );
174 }
175
176 ITERATOR erase( const ITERATOR& aIterator )
177 {
178 ITERATOR it( aIterator );
179 it.m_it = (*aIterator.m_parent)[ aIterator.m_curType ].erase( aIterator.m_it );
180 it.validate();
181
182 return it;
183 }
184
186 {
187 int bucket = ( aType != UNDEFINED_TYPE ) ? aType : first();
188 return ITERATOR( this, operator[]( bucket ).begin(), bucket, aType );
189 }
190
192 {
193 int bucket = ( aType != UNDEFINED_TYPE ) ? aType : last();
194 return ITERATOR( this, operator[]( bucket ).end(), bucket, aType );
195 }
196
198 {
199 int bucket = ( aType != UNDEFINED_TYPE ) ? aType : first();
200 return CONST_ITERATOR( this, operator[]( bucket ).begin(), bucket, aType );
201 }
202
203 CONST_ITERATOR end( int aType = UNDEFINED_TYPE ) const
204 {
205 int bucket = ( aType != UNDEFINED_TYPE ) ? aType : last();
206 return CONST_ITERATOR( this, operator[]( bucket ).end(), bucket, aType );
207 }
208
209 void clear( int aType = UNDEFINED_TYPE )
210 {
211 if( aType != UNDEFINED_TYPE )
212 {
213 operator[]( aType ).clear();
214 }
215 else
216 {
217 for( int i = 0; i < TYPES_COUNT; ++i)
218 m_data[ i ].clear();
219 }
220 }
221
222 size_t size( int aType = UNDEFINED_TYPE ) const
223 {
224 if( aType != UNDEFINED_TYPE )
225 {
226 return operator[]( aType ).size();
227 }
228 else
229 {
230 size_t cnt = 0;
231
232 for( int i = 0; i < TYPES_COUNT; ++i)
233 cnt += m_data[ i ].size();
234
235 return cnt;
236 }
237 }
238
239 bool empty( int aType = UNDEFINED_TYPE ) const
240 {
241 return ( size( aType ) == 0 );
242 }
243
244 void sort()
245 {
246 for( int i = 0; i < TYPES_COUNT; ++i )
247 m_data[ i ].sort();
248 }
249
253 void unique()
254 {
255 for( int i = 0; i < TYPES_COUNT; ++i )
256 {
257 if( m_data[ i ].size() > 1 )
258 m_data[ i ].unique();
259 }
260 }
261
263 {
264 if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) )
265 {
266 wxFAIL_MSG( wxT( "Attempted access to type not within MULTIVECTOR" ) );
267
268 // return type is a reference so we have to return something...
269 aType = FIRST_TYPE;
270 }
271
272 return m_data[ aType - FIRST_TYPE ];
273 }
274
275 const ITEM_PTR_VECTOR& operator[]( int aType ) const
276 {
277 if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) )
278 {
279 wxFAIL_MSG( wxT( "Attempted access to type not within MULTIVECTOR" ) );
280
281 // return type is a reference so we have to return something...
282 aType = FIRST_TYPE;
283 }
284
285 return m_data[ aType - FIRST_TYPE ];
286 }
287
288 // Range of valid types handled by the iterator
289 static constexpr int FIRST_TYPE = FIRST_TYPE_VAL;
290 static constexpr int LAST_TYPE = LAST_TYPE_VAL;
291 static constexpr int TYPES_COUNT = LAST_TYPE - FIRST_TYPE + 1;
292
293private:
295 int first() const
296 {
297 int i = 0;
298
299 while( ( i < TYPES_COUNT ) && ( m_data[ i ].empty() ) )
300 ++i;
301
302 return ( i == TYPES_COUNT ) ? FIRST_TYPE : FIRST_TYPE + i;
303 }
304
306 int last() const
307 {
308 int i = TYPES_COUNT - 1;
309
310 while( ( i >= 0 ) && ( m_data[ i ].empty() ) )
311 --i;
312
313 return ( i < 0 ) ? FIRST_TYPE : FIRST_TYPE + i;
314 }
315
318};
319
320#endif /* MULTIVECTOR_H */
Generic implementation of a flat const/non-const iterator over contained items.The non-const iterator...
Definition multivector.h:68
ITERATOR_BASE(ITEM_CONTAINER *aItems, ITEM_CONTAINER_IT aIt, int aBucket, int aType=UNDEFINED_TYPE)
Assures the iterator is in a valid state.
void validate()
Wrapped container.
bool m_filter
Type of the currently iterated items.
bool operator!=(const ITERATOR_BASE &aOther) const
Definition multivector.h:90
ITERATOR_BASE & operator++()
Definition multivector.h:80
size_t size(int aType=UNDEFINED_TYPE) const
CONST_ITERATOR begin(int aType=UNDEFINED_TYPE) const
bool empty(int aType=UNDEFINED_TYPE) const
ITERATOR_BASE< const SCH_ITEM, const MULTIVECTOR< SCH_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::const_iterator > CONST_ITERATOR
ITEM_PTR_VECTOR & operator[](int aType)
const ITEM_PTR_VECTOR & operator[](int aType) const
CONST_ITERATOR end(int aType=UNDEFINED_TYPE) const
void unique()
Remove duplicate elements in list.
void push_back(T *aItem)
ITERATOR_BASE< SCH_ITEM, MULTIVECTOR< SCH_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
ITERATOR end(int aType=UNDEFINED_TYPE)
int last() const
Contained items by type.
int first() const
< Get first non-empty type or first type if all are empty.
void clear(int aType=UNDEFINED_TYPE)
static constexpr int LAST_TYPE
ITERATOR erase(const ITERATOR &aIterator)
boost::ptr_vector< SCH_ITEM > ITEM_PTR_VECTOR
Definition multivector.h:61
ITERATOR begin(int aType=UNDEFINED_TYPE)
netlist clear()
VECTOR2I end