67 std::set<RECORD_KEY, KEY_LESS> removedInputs(
KEY_LESS{
m_keys } );
72 return a.
content == b.content && a == b;
77 const auto current = aCurrent.find( node );
79 if( current == aCurrent.end() || !sameComponent( component, current->second ) )
80 removedInputs.insert( component.content->records.begin(), component.content->records.end() );
83 for(
const auto& [node, component] : aCurrent )
87 connection.
kind = component.content->kind;
89 connection.
name = component.name;
90 connection.
netCode = component.netCode;
93 if( !component.content->netclasses.empty() )
98 old !=
m_netclasses.end() && *old->second == component.content->netclasses
100 : std::make_shared<const std::vector<NAME_ID>>( component.content->netclasses );
103 if( component.content->best )
105 connection.
driver = component.content->best->source;
111 component.nameSlot ? aSlots.at( *component.nameSlot )->localName : component.content->best->name;
114 if( component.name !=
INVALID_ID && !component.content->netclasses.empty() )
119 if( previous !=
m_components.end() && sameComponent( previous->second, component ) )
123 const auto& records = component.content->records;
124 std::vector<size_t> parents( records.size() );
125 std::vector<std::pair<size_t, const CLAIM*>> groups( records.size() );
126 std::iota( parents.begin(), parents.end(),
size_t( 0 ) );
128 const auto root = [&](
size_t aIndex )
130 while( parents[aIndex] != aIndex )
131 aIndex = parents[aIndex] = parents[parents[aIndex]];
138 std::map<std::pair<INST_ID, NAME_ID>,
size_t> names;
142 const auto* record = aRecords.
Find( records[
index] );
147 for(
const NAME_KEY& edge : record->value.edges )
149 if( edge.
scope != SCOPE::SHEET )
152 const auto [named, inserted] = names.try_emplace( { edge.
inst, edge.
text },
index );
155 parents[root(
index )] = root( named->second );
161 const auto* record = aRecords.
Find( records[
index] );
163 if( !record || record->value.claims.empty() )
166 auto& [count, best] = groups[root(
index )];
169 if( !best || less( *best, record->value.claims.front() ) )
170 best = &record->value.claims.front();
177 removedInputs.erase( key );
178 const auto* record = aRecords.
Find( key );
180 if( !record || record->value.kind != component.content->kind )
181 throw std::invalid_argument(
"Published component does not match its row records" );
185 const CLAIM* localClaim = component.content->best ? &*component.content->best :
nullptr;
187 if( !record->value.claims.empty() )
189 localClaim = &record->value.claims.front();
192 if( record->value.claims.front().priority ==
PRIORITY::PIN && component.content->best
196 localClaim = &*component.content->best;
203 if( !record->value.claims.empty() && localClaim == &record->value.claims.front() )
205 const auto& [count, winner] = groups[root(
index )];
207 if( count > 1 && winner->name != localClaim->
name )
215 && localClaim->
schema->shape == component.content->best->schema->shape
216 && localClaim->
name != component.content->best->name )
219 const auto previousSource = old !=
m_rowInputs.end() ? old->second->connection.busSource :
nullptr;
220 local.
busSource = previousSource && *previousSource == source
222 : std::make_shared<const ITEM_RESULT::BUS_SOURCE>( source );
228 else if( old !=
m_rowInputs.end() && old->second->version == record->version
229 && old->second->connection.localName == local.
localName
230 && old->second->connection.itemType == local.
itemType
231 &&
m_components.at( old->second->connection.component ).suffix == component.suffix )
236 localClaim ? localClaim->
schema.get() :
nullptr, component.suffix ) );
238 std::optional<std::pair<KIID, ITEM_RESULT>> driver;
246 if( component.suffix )
252 driver.emplace( localClaim->
source.
item, std::move( row ) );
255 if( old ==
m_rowInputs.end() || old->second->version != record->version
256 || old->second->connection != local || old->second->
driver != driver )
258 result.inputs.emplace( key, std::make_shared<const ROW_INPUT>(
ROW_INPUT{
259 record->version, local, record->value.items,
260 std::move( driver ) } ) );
266 const auto removePreviousItems = [&](
const RECORD_KEY& key )
272 for(
const KIID& item : old->second->items )
273 removed.insert( { item, key.inst } );
276 result.removedInputs.assign( removedInputs.begin(), removedInputs.end() );
279 removePreviousItems( key );
281 for(
const auto& [key, input] :
result.inputs )
282 removePreviousItems( key );
284 for(
const auto& [key, replacement] :
result.inputs )
294 removed.erase( item );
295 const auto old =
m_rows.find( item );
297 if( old ==
m_rows.end() || old->second != row )
304 result.upserts.emplace( item, row );
309 result.removed.assign( removed.begin(), removed.end() );
313 const auto old =
m_rows.find( item );
319 if( old->second.driver )
326 for(
const auto& [
name, classes] :
result.netclasses )
330 if( old ==
m_netclasses.end() || !SameValue( old->second, classes ) )
wxString result
Test unit parsing edge cases and error handling.