KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_item_index.cpp
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 The KiCad Developers.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "board_item_index.h"
21
22#include <functional>
23
24#include <wx/log.h>
25
26#include <board.h>
27#include <board_item.h>
28
29
31{
32 auto it = m_itemsById.find( aId );
33
34 if( it == m_itemsById.end() )
35 return nullptr;
36
37 BOARD_ITEM* item = it->second;
38
39 if( item && item->m_Uuid == aId )
40 return item;
41
42 Unbind( aId );
43 return nullptr;
44}
45
46
48{
49 if( m_owner.IsFootprintHolder() )
50 return;
51
52 // Hand the item to this index. A stale index cannot evict it.
53 if( aItem.m_owningIndex && aItem.m_owningIndex != this )
54 aItem.m_owningIndex->UnbindItem( aItem );
55
56 // Called once per item on load, so probe and insert in one lookup per map and pay for the
57 // aliasing fixups only when a key was already taken
58 auto [idIt, idInserted] = m_itemsById.try_emplace( aItem.m_Uuid, &aItem );
59 auto [itemIt, itemInserted] = m_idsByItem.try_emplace( &aItem, aItem.m_Uuid );
60
61 if( !itemInserted && itemIt->second != aItem.m_Uuid )
62 {
63 // The item was indexed under an older UUID; drop that forward alias
64 auto prevIt = m_itemsById.find( itemIt->second );
65
66 if( prevIt != m_itemsById.end() && prevIt->second == &aItem )
67 m_itemsById.erase( prevIt );
68
69 itemIt->second = aItem.m_Uuid;
70 }
71
72 if( !idInserted && idIt->second != &aItem )
73 {
74 // Another item already claims this UUID; evict it
75 if( auto prev = m_idsByItem.find( idIt->second );
76 prev != m_idsByItem.end() && prev->second == aItem.m_Uuid )
77 {
78 idIt->second->m_owningIndex = nullptr;
79 m_idsByItem.erase( prev );
80 }
81
82 idIt->second = &aItem;
83 }
84
85 // Set the owning index last, a half-done update then reads as not indexed
86 aItem.m_owningIndex = this;
87}
88
89
91{
92 auto it = m_itemsById.find( aId );
93
94 if( it == m_itemsById.end() )
95 return;
96
97 const BOARD_ITEM* item = it->second;
98
99 m_itemsById.erase( it );
100
101 if( auto cached = m_idsByItem.find( item );
102 cached != m_idsByItem.end() && cached->second == aId )
103 {
104 item->m_owningIndex = nullptr;
105 m_idsByItem.erase( cached );
106 }
107}
108
109
111{
112 // Clear the link first, the item no longer points to this index
113 aItem.m_owningIndex = nullptr;
114
115 if( auto cached = m_idsByItem.find( &aItem ); cached != m_idsByItem.end() )
116 {
117 auto it = m_itemsById.find( cached->second );
118
119 if( it != m_itemsById.end() && it->second == &aItem )
120 m_itemsById.erase( it );
121
122 m_idsByItem.erase( cached );
123 return;
124 }
125
126 std::erase_if( m_itemsById,
127 [&aItem]( const auto& entry )
128 {
129 return entry.second == &aItem;
130 } );
131}
132
133
135{
136 for( const auto& [item, id] : m_idsByItem )
137 item->m_owningIndex = nullptr;
138
139 m_itemsById.clear();
140 m_idsByItem.clear();
141}
142
143
144void BOARD_ITEM_INDEX::Rebind( BOARD_ITEM& aItem, const KIID& aNewId )
145{
146 if( m_owner.IsFootprintHolder() )
147 return;
148
149 if( aItem.m_Uuid == aNewId )
150 {
151 BindItem( aItem );
152 return;
153 }
154
155 if( BOARD_ITEM* existing = Find( aNewId ); existing && existing != &aItem )
156 {
157 wxFAIL_MSG( wxString::Format( "BOARD_ITEM_INDEX::Rebind() duplicate target UUID: %s", aNewId.AsString() ) );
158 return;
159 }
160
161 UnbindItem( aItem );
162 aItem.SetUuidDirect( aNewId );
163 BindItem( aItem );
164}
165
166
168{
169 BindItem( aItem );
170
171 aItem.RunOnChildren(
172 [this]( BOARD_ITEM* aChild )
173 {
174 BindSubtree( *aChild );
175 },
177}
178
180{
181 aParent.RunOnChildren(
182 [this]( BOARD_ITEM* aChild )
183 {
184 BindSubtree( *aChild );
185 },
187}
188
189
191{
192 // Pointer-keyed eviction: never remove an entry that belongs to a
193 // different live item with the same UUID (e.g. a temporary copy).
194 UnbindItem( aItem );
195
196 aItem.RunOnChildren(
197 [this]( BOARD_ITEM* aChild )
198 {
199 UnbindSubtree( *aChild );
200 },
202}
203
204
206{
207 aParent.RunOnChildren(
208 [this]( BOARD_ITEM* aChild )
209 {
210 UnbindSubtree( *aChild );
211 },
213}
std::unordered_map< KIID, BOARD_ITEM * > m_itemsById
Forward map from KIIDs to board items.
BOARD_ITEM * Find(const KIID &aId)
Return a cached item for aId if the entry is still self-consistent.
void UnbindSubtree(const BOARD_ITEM &aItem)
void UnbindItem(const BOARD_ITEM &aItem)
Drop aItem itself.
void Clear()
Drop every entry, clearing each item's link back to the board.
void BindSubtree(BOARD_ITEM &aItem)
void Unbind(const KIID &aId)
Remove an item from the item-by-id cache.
void BindChildren(const BOARD_ITEM &aParent)
void BindItem(BOARD_ITEM &aItem)
Index aItem, replacing any previous entry for its UUID or address.
std::unordered_map< const BOARD_ITEM *, KIID > m_idsByItem
Reverse map from board items to their KIIDs.
void UnbindChildren(const BOARD_ITEM &aParent)
void Rebind(BOARD_ITEM &aItem, const KIID &aNewId)
Move aItem to aNewId, keeping the index in step with the item.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
Definition board_item.h:265
BOARD_ITEM_INDEX * m_owningIndex
Board index that indexes this item, or nullptr.
Definition board_item.h:608
const KIID m_Uuid
Definition eda_item.h:599
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
@ NO_RECURSE
Definition eda_item.h:52