1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 CERN
5  * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef __PNS_ITEMSET_H
23 #define __PNS_ITEMSET_H
24 
25 #include <vector>
26 #include <core/kicad_algo.h>
27 #include "pns_item.h"
28 
29 namespace PNS {
30 
31 /**
32  * Hold a list of board items, that can be filtered against net, kinds, layers, etc.
33  */
34 class LINE;
35 
36 class ITEM_SET
37 {
38 public:
39     struct ENTRY
40     {
41         ENTRY( ITEM* aItem, bool aOwned = false ) :
itemENTRY42             item( aItem ),
43             owned( aOwned )
44         {}
45 
ENTRYENTRY46         ENTRY( const ENTRY& aOther )
47         {
48             owned = aOther.owned;
49 
50             if( aOther.owned )
51                 item = aOther.item->Clone();
52             else
53                 item = aOther.item;
54         }
55 
~ENTRYENTRY56         ~ENTRY()
57         {
58             if( owned )
59                 delete item;
60         }
61 
62         bool operator==( const ENTRY& b ) const
63         {
64             return item == b.item;
65         }
66 
67         bool operator<( const ENTRY& b ) const
68         {
69             return item < b.item;
70         }
71 
72         ENTRY& operator=( const ENTRY& aOther )
73         {
74             owned = aOther.owned;
75 
76             if( aOther.owned )
77                 item = aOther.item->Clone();
78             else
79                 item = aOther.item;
80 
81             return *this;
82         }
83 
84         operator ITEM* () const
85         {
86             return item;
87         }
88 
89         ITEM *item;
90         bool owned;
91     };
92 
93     typedef std::vector<ENTRY> ENTRIES;
94 
95     ITEM_SET( ITEM* aInitialItem = nullptr, bool aBecomeOwner = false )
96     {
97         if( aInitialItem )
98             m_items.emplace_back( ENTRY( aInitialItem, aBecomeOwner ) );
99     }
100 
ITEM_SET(const ITEM_SET & aOther)101     ITEM_SET( const ITEM_SET& aOther )
102     {
103         m_items = aOther.m_items;
104     }
105 
106     ~ITEM_SET();
107 
108     ITEM_SET& operator=( const ITEM_SET& aOther )
109     {
110         m_items = aOther.m_items;
111         return *this;
112     }
113 
114     int Count( int aKindMask = -1 ) const
115     {
116         int n = 0;
117 
118         if( aKindMask == -1 || aKindMask == ITEM::ANY_T )
119             return static_cast<int>( m_items.size() );
120 
121         for( ITEM* item : m_items )
122         {
123             if( item->Kind() & aKindMask )
124                 n++;
125         }
126 
127         return n;
128     }
129 
Empty()130     bool Empty() const
131     {
132         return m_items.empty();
133     }
134 
Items()135     ENTRIES& Items() { return m_items; }
CItems()136     const ENTRIES& CItems() const { return m_items; }
137 
138     ITEM_SET& FilterLayers( int aStart, int aEnd = -1, bool aInvert = false );
139     ITEM_SET& FilterKinds( int aKindMask, bool aInvert = false );
140     ITEM_SET& FilterNet( int aNet, bool aInvert = false );
141     ITEM_SET& FilterMarker( int aMarker, bool aInvert = false );
142 
143     ITEM_SET& ExcludeLayers( int aStart, int aEnd = -1 )
144     {
145         return FilterLayers( aStart, aEnd, true );
146     }
147 
ExcludeKinds(int aKindMask)148     ITEM_SET& ExcludeKinds( int aKindMask )
149     {
150         return FilterKinds( aKindMask, true );
151     }
152 
ExcludeNet(int aNet)153     ITEM_SET& ExcludeNet( int aNet )
154     {
155         return FilterNet( aNet, true );
156     }
157 
158     ITEM_SET& ExcludeItem( const ITEM* aItem );
159 
Size()160     int Size() const
161     {
162         return static_cast<int>( m_items.size() );
163     }
164 
165     void Add( const LINE& aLine );
166     void Prepend( const LINE& aLine );
167 
168     ITEM* operator[]( size_t aIndex ) const
169     {
170         return m_items[aIndex].item;
171     }
172 
begin()173     ENTRIES::iterator begin() { return m_items.begin(); }
end()174     ENTRIES::iterator end() { return m_items.end(); }
cbegin()175     ENTRIES::const_iterator cbegin() const { return m_items.cbegin(); }
cend()176     ENTRIES::const_iterator cend() const { return m_items.cend(); }
177 
178     void Add( ITEM* aItem, bool aBecomeOwner = false )
179     {
180         m_items.emplace_back( ENTRY( aItem, aBecomeOwner ) );
181     }
182 
183     void Prepend( ITEM* aItem, bool aBecomeOwner = false )
184     {
185          m_items.emplace( m_items.begin(), ENTRY( aItem, aBecomeOwner ) );
186     }
187 
Clear()188     void Clear()
189     {
190         m_items.clear();
191     }
192 
Contains(ITEM * aItem)193     bool Contains( ITEM* aItem ) const
194     {
195         const ENTRY ent( aItem );
196         return alg::contains( m_items, ent );
197     }
198 
Erase(ITEM * aItem)199     void Erase( ITEM* aItem )
200     {
201         ENTRY ent( aItem );
202         ENTRIES::iterator f = std::find( m_items.begin(), m_items.end(), ent );
203 
204         if( f != m_items.end() )
205             m_items.erase( f );
206     }
207 
208     template<class T>
209     T* FindByKind( ITEM::PnsKind kind, int index = 0 )
210     {
211         int n = 0;
212 
213         for( const ITEM* item : m_items )
214         {
215             if( item->OfKind( kind ) )
216             {
217                 if( index == n )
218                     return static_cast<T*>( item );
219                 else
220                     n++;
221             }
222         }
223 
224         return nullptr;
225     }
226 
227 private:
228     ENTRIES m_items;
229 };
230 
231 }
232 
233 #endif
234