KiCad PCB EDA Suite
Loading...
Searching...
No Matches
conn_keys.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, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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 "conn_keys.h"
21
22#include <hashtables.h>
23#include <optional>
24#include <type_traits>
25
26namespace SCH_CONNECTIVITY
27{
29{
30 if( auto* name = std::get_if<NAME_KEY>( &aKey ) )
31 {
32 Name( name->text );
33
34 if( name->scope == SCOPE::GLOBAL )
35 name->inst = 0;
36 else
37 Instance( name->inst );
38
39 if( name->scope != SCOPE::PORT )
40 name->kind = KIND::SIGNAL;
41 }
42 else if( const auto* record = std::get_if<RECORD_NODE>( &aKey ) )
43 {
44 Instance( record->record.inst );
45 }
46 else
47 {
48 Instance( std::get<SLOT_KEY>( aKey ).bundleDriver.inst );
49 }
50
51 return m_nodes.Intern( aKey );
52}
53
55{
56 size_t hash = aKey.index();
57
58 if( const auto* record = std::get_if<RECORD_NODE>( &aKey ) )
59 {
60 hash = KiHashCombine( hash, record->record.inst );
61 hash = KiHashCombine( hash, std::hash<KIID>{}( record->record.anchor ) );
62 hash = KiHashCombine( hash, static_cast<size_t>( record->kind ) );
63 }
64 else if( const auto* name = std::get_if<NAME_KEY>( &aKey ) )
65 {
66 hash = KiHashCombine( hash, static_cast<size_t>( name->scope ) );
67 hash = KiHashCombine( hash, name->text );
68
69 if( name->scope != SCOPE::GLOBAL )
70 hash = KiHashCombine( hash, name->inst );
71
72 if( name->scope == SCOPE::PORT )
73 hash = KiHashCombine( hash, static_cast<size_t>( name->kind ) );
74 }
75 else
76 {
77 const auto& slot = std::get<SLOT_KEY>( aKey );
78 hash = KiHashCombine( hash, std::hash<KIID>{}( slot.bundleDriver.item ) );
79 hash = KiHashCombine( hash, slot.bundleDriver.inst );
80 hash = KiHashCombine( hash, slot.leaf );
81 }
82
83 return hash;
84}
85
86namespace
87{
88 // Default keys hold INVALID_ID, which no table resolves, so unset ids order first without a lookup.
89 std::optional<bool> unsetIdLess( uint32_t aLeft, uint32_t aRight )
90 {
91 if( aLeft != INVALID_ID && aRight != INVALID_ID )
92 return std::nullopt;
93
94 return aLeft == INVALID_ID && aRight != INVALID_ID;
95 }
96} // namespace
97
98bool SESSION_KEYS::Less( const ITEM_KEY& aLeft, const ITEM_KEY& aRight ) const
99{
100 if( aLeft.item != aRight.item )
101 return aLeft.item < aRight.item;
102
103 if( aLeft.inst == aRight.inst )
104 return false;
105
106 if( std::optional<bool> order = unsetIdLess( aLeft.inst, aRight.inst ) )
107 return *order;
108
109 return Instance( aLeft.inst ) < Instance( aRight.inst );
110}
111
112bool SESSION_KEYS::Less( const RECORD_KEY& aLeft, const RECORD_KEY& aRight ) const
113{
114 if( aLeft.inst == aRight.inst )
115 return aLeft.anchor < aRight.anchor;
116
117 if( std::optional<bool> order = unsetIdLess( aLeft.inst, aRight.inst ) )
118 return *order;
119
120 return Instance( aLeft.inst ) < Instance( aRight.inst );
121}
122
123bool SESSION_KEYS::Less( const RECORD_NODE& aLeft, const RECORD_NODE& aRight ) const
124{
125 return aLeft.record == aRight.record ? aLeft.kind < aRight.kind : Less( aLeft.record, aRight.record );
126}
127
128bool SESSION_KEYS::Less( const NAME_KEY& aLeft, const NAME_KEY& aRight ) const
129{
130 if( aLeft.scope != aRight.scope )
131 return aLeft.scope < aRight.scope;
132
133 if( aLeft.scope != SCOPE::GLOBAL && aLeft.inst != aRight.inst )
134 {
135 if( std::optional<bool> order = unsetIdLess( aLeft.inst, aRight.inst ) )
136 return *order;
137
138 return Instance( aLeft.inst ) < Instance( aRight.inst );
139 }
140
141 if( aLeft.text != aRight.text )
142 {
143 if( std::optional<bool> order = unsetIdLess( aLeft.text, aRight.text ) )
144 return *order;
145
146 return NameLess( aLeft.text, aRight.text );
147 }
148
149 return aLeft.scope == SCOPE::PORT && aLeft.kind < aRight.kind;
150}
151
152bool SESSION_KEYS::Less( const SLOT_KEY& aLeft, const SLOT_KEY& aRight ) const
153{
154 return aLeft.bundleDriver == aRight.bundleDriver ? aLeft.leaf < aRight.leaf
155 : Less( aLeft.bundleDriver, aRight.bundleDriver );
156}
157
158bool SESSION_KEYS::Less( const NODE_KEY& aLeft, const NODE_KEY& aRight ) const
159{
160 if( aLeft.index() != aRight.index() )
161 return aLeft.index() < aRight.index();
162
163 return std::visit(
164 [&]( const auto& left )
165 {
166 return Less( left, std::get<std::decay_t<decltype( left )>>( aRight ) );
167 },
168 aLeft );
169}
170} // namespace SCH_CONNECTIVITY
const char * name
const wxString & Name(NAME_ID aId) const
Definition conn_keys.h:163
const KIID_PATH & Instance(INST_ID aId) const
Definition conn_keys.h:162
INTERN_TABLE< NODE_KEY, std::unordered_map< NODE_KEY, uint32_t, NODE_HASH > > m_nodes
Definition conn_keys.h:241
bool Less(const ITEM_KEY &aLeft, const ITEM_KEY &aRight) const
Definition conn_keys.cpp:98
bool NameLess(NAME_ID aLeft, NAME_ID aRight) const
Definition conn_keys.h:166
NODE_ID InternNode(NODE_KEY aKey)
Definition conn_keys.cpp:28
std::size_t KiHashCombine(std::size_t aSeed, std::size_t aValue)
Fold aValue into the running hash aSeed using the well-known Boost hash_combine mixing step.
Definition hashtables.h:42
Value keys and the key session of the schematic connectivity engine.
std::variant< RECORD_NODE, NAME_KEY, SLOT_KEY > NODE_KEY
Any node of the union-find graph.
Definition conn_keys.h:136
uint32_t NODE_ID
Session handle of a NODE_KEY graph node.
Definition conn_keys.h:43
constexpr uint32_t INVALID_ID
Marks an unset handle.
Definition conn_keys.h:47
One item or pin in one sheet instance.
Definition conn_keys.h:77
KIID item
The item or pin KIID.
Definition conn_keys.h:78
INST_ID inst
The sheet instance that shows the item.
Definition conn_keys.h:79
The graph node of one name in one scope.
Definition conn_keys.h:110
KIND kind
The record kind. Only PORT compares it.
Definition conn_keys.h:114
INST_ID inst
The sheet instance, or the child instance of a sheet pin for PORT.
Definition conn_keys.h:112
NAME_ID text
The resolved name.
Definition conn_keys.h:113
One island in one sheet instance.
Definition conn_keys.h:87
INST_ID inst
The sheet instance of the record.
Definition conn_keys.h:88
KIID anchor
ISLAND::anchor, the smallest item KIID in the island.
Definition conn_keys.h:89
The graph node of one island record.
Definition conn_keys.h:97
KIND kind
The kind of the record, which selects its stratum.
Definition conn_keys.h:99
size_t operator()(const NODE_KEY &aKey) const
Definition conn_keys.cpp:54
One member position of a bus.
Definition conn_keys.h:127
ITEM_KEY bundleDriver
The source item of the claim that defines the leaf order.
Definition conn_keys.h:128
uint32_t leaf
The index into BUS_SCHEMA::leaves of that claim.
Definition conn_keys.h:129