KiCad PCB EDA Suite
Loading...
Searching...
No Matches
net_settings.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 (C) 2020 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Jon Evans <[email protected]>
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#include <algorithm>
23#include <limits>
24
25#include <json_common.h>
26
29#include <settings/parameters.h>
31#include <string_utils.h>
32#include <base_units.h>
33#include <unordered_set>
34
35
36// const int netSettingsSchemaVersion = 0;
37// const int netSettingsSchemaVersion = 1; // new overbar syntax
38// const int netSettingsSchemaVersion = 2; // exclude buses from netclass members
39// const int netSettingsSchemaVersion = 3; // netclass assignment patterns
40// const int netSettingsSchemaVersion = 4; // netclass ordering
41const int netSettingsSchemaVersion = 5; // Tuning profile names
42
43
44static std::optional<int> getInPcbUnits( const nlohmann::json& aObj, const std::string& aKey,
45 std::optional<int> aDefault = std::optional<int>() )
46{
47 if( aObj.contains( aKey ) && aObj[aKey].is_number() )
48 return pcbIUScale.mmToIU( aObj[aKey].get<double>() );
49 else
50 return aDefault;
51};
52
53
54static std::optional<int> getInSchUnits( const nlohmann::json& aObj, const std::string& aKey,
55 std::optional<int> aDefault = std::optional<int>() )
56{
57 if( aObj.contains( aKey ) && aObj[aKey].is_number() )
58 return schIUScale.MilsToIU( aObj[aKey].get<double>() );
59 else
60 return aDefault;
61};
62
63
64NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
65 NESTED_SETTINGS( "net_settings", netSettingsSchemaVersion, aParent, aPath, false )
66{
67 m_defaultNetClass = std::make_shared<NETCLASS>( NETCLASS::Default, true );
68 m_defaultNetClass->SetDescription( _( "This is the default net class." ) );
69 m_defaultNetClass->SetPriority( std::numeric_limits<int>::max() );
70
71 auto saveNetclass =
72 []( nlohmann::json& json_array, const std::shared_ptr<NETCLASS>& nc )
73 {
74 // Note: we're in common/, but we do happen to know which of these
75 // fields are used in which units system.
76 nlohmann::json nc_json = { { "name", nc->GetName().ToUTF8() },
77 { "priority", nc->GetPriority() },
78 { "schematic_color", nc->GetSchematicColor( true ) },
79 { "pcb_color", nc->GetPcbColor( true ) },
80 { "tuning_profile", nc->GetTuningProfile() } };
81
82 auto saveInPcbUnits =
83 []( nlohmann::json& json, const std::string& aKey, int aValue )
84 {
85 json.push_back( { aKey, pcbIUScale.IUTomm( aValue ) } );
86 };
87
88 if( nc->HasWireWidth() )
89 nc_json.push_back(
90 { "wire_width", schIUScale.IUToMils( nc->GetWireWidth() ) } );
91
92 if( nc->HasBusWidth() )
93 nc_json.push_back( { "bus_width", schIUScale.IUToMils( nc->GetBusWidth() ) } );
94
95 if( nc->HasLineStyle() )
96 nc_json.push_back( { "line_style", nc->GetLineStyle() } );
97
98 if( nc->HasClearance() )
99 saveInPcbUnits( nc_json, "clearance", nc->GetClearance() );
100
101 if( nc->HasTrackWidth() )
102 saveInPcbUnits( nc_json, "track_width", nc->GetTrackWidth() );
103
104 if( nc->HasViaDiameter() )
105 saveInPcbUnits( nc_json, "via_diameter", nc->GetViaDiameter() );
106
107 if( nc->HasViaDrill() )
108 saveInPcbUnits( nc_json, "via_drill", nc->GetViaDrill() );
109
110 if( nc->HasuViaDiameter() )
111 saveInPcbUnits( nc_json, "microvia_diameter", nc->GetuViaDiameter() );
112
113 if( nc->HasuViaDrill() )
114 saveInPcbUnits( nc_json, "microvia_drill", nc->GetuViaDrill() );
115
116 if( nc->HasDiffPairWidth() )
117 saveInPcbUnits( nc_json, "diff_pair_width", nc->GetDiffPairWidth() );
118
119 if( nc->HasDiffPairGap() )
120 saveInPcbUnits( nc_json, "diff_pair_gap", nc->GetDiffPairGap() );
121
122 if( nc->HasDiffPairViaGap() )
123 saveInPcbUnits( nc_json, "diff_pair_via_gap", nc->GetDiffPairViaGap() );
124
125 json_array.push_back( nc_json );
126 };
127
128 auto readNetClass =
129 []( const nlohmann::json& entry )
130 {
131 wxString name = entry["name"];
132
133 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( name, false );
134
135 if( entry.contains( "priority" ) && entry["priority"].is_number() )
136 nc->SetPriority( entry["priority"].get<int>() );
137
138 if( entry.contains( "tuning_profile" ) && entry["tuning_profile"].is_string() )
139 nc->SetTuningProfile( entry["tuning_profile"].get<wxString>() );
140
141 if( auto value = getInPcbUnits( entry, "clearance" ) )
142 nc->SetClearance( *value );
143
144 if( auto value = getInPcbUnits( entry, "track_width" ) )
145 nc->SetTrackWidth( *value );
146
147 if( auto value = getInPcbUnits( entry, "via_diameter" ) )
148 nc->SetViaDiameter( *value );
149
150 if( auto value = getInPcbUnits( entry, "via_drill" ) )
151 nc->SetViaDrill( *value );
152
153 if( auto value = getInPcbUnits( entry, "microvia_diameter" ) )
154 nc->SetuViaDiameter( *value );
155
156 if( auto value = getInPcbUnits( entry, "microvia_drill" ) )
157 nc->SetuViaDrill( *value );
158
159 if( auto value = getInPcbUnits( entry, "diff_pair_width" ) )
160 nc->SetDiffPairWidth( *value );
161
162 if( auto value = getInPcbUnits( entry, "diff_pair_gap" ) )
163 nc->SetDiffPairGap( *value );
164
165 if( auto value = getInPcbUnits( entry, "diff_pair_via_gap" ) )
166 nc->SetDiffPairViaGap( *value );
167
168 if( auto value = getInSchUnits( entry, "wire_width" ) )
169 nc->SetWireWidth( *value );
170
171 if( auto value = getInSchUnits( entry, "bus_width" ) )
172 nc->SetBusWidth( *value );
173
174 if( entry.contains( "line_style" ) && entry["line_style"].is_number() )
175 nc->SetLineStyle( entry["line_style"].get<int>() );
176
177 if( entry.contains( "pcb_color" ) && entry["pcb_color"].is_string() )
178 nc->SetPcbColor( entry["pcb_color"].get<KIGFX::COLOR4D>() );
179
180 if( entry.contains( "schematic_color" )
181 && entry["schematic_color"].is_string() )
182 {
183 nc->SetSchematicColor( entry["schematic_color"].get<KIGFX::COLOR4D>() );
184 }
185
186 return nc;
187 };
188
189 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "classes",
190 [&]() -> nlohmann::json
191 {
192 nlohmann::json ret = nlohmann::json::array();
193
195 saveNetclass( ret, m_defaultNetClass );
196
197 for( const auto& [name, netclass] : m_netClasses )
198 saveNetclass( ret, netclass );
199
200 return ret;
201 },
202 [&]( const nlohmann::json& aJson )
203 {
204 if( !aJson.is_array() )
205 return;
206
207 m_netClasses.clear();
208
209 for( const nlohmann::json& entry : aJson )
210 {
211 if( !entry.is_object() || !entry.contains( "name" ) )
212 continue;
213
214 std::shared_ptr<NETCLASS> nc = readNetClass( entry );
215
216 if( nc->IsDefault() )
218 else
219 m_netClasses[nc->GetName()] = nc;
220 }
221 },
222 {} ) );
223
224 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "net_colors",
225 [&]() -> nlohmann::json
226 {
227 nlohmann::json ret = {};
228
229 for( const auto& [netname, color] : m_netColorAssignments )
230 {
231 std::string key( netname.ToUTF8() );
232 ret[ std::move( key ) ] = color;
233 }
234
235 return ret;
236 },
237 [&]( const nlohmann::json& aJson )
238 {
239 if( !aJson.is_object() )
240 return;
241
242 m_netColorAssignments.clear();
243
244 for( const auto& pair : aJson.items() )
245 {
246 wxString key( pair.key().c_str(), wxConvUTF8 );
247 m_netColorAssignments[std::move( key )] = pair.value().get<KIGFX::COLOR4D>();
248 }
249 },
250 {} ) );
251
252 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "netclass_assignments",
253 [&]() -> nlohmann::json
254 {
255 nlohmann::json ret = {};
256
257 for( const auto& [netname, netclassNames] : m_netClassLabelAssignments )
258 {
259 nlohmann::json netclassesJson = nlohmann::json::array();
260
261 for( const auto& netclass : netclassNames )
262 {
263 std::string netclassStr( netclass.ToUTF8() );
264 netclassesJson.push_back( std::move( netclassStr ) );
265 }
266
267 std::string key( netname.ToUTF8() );
268 ret[std::move( key )] = netclassesJson;
269 }
270
271 return ret;
272 },
273 [&]( const nlohmann::json& aJson )
274 {
275 if( !aJson.is_object() )
276 return;
277
279
280 for( const auto& pair : aJson.items() )
281 {
282 wxString key( pair.key().c_str(), wxConvUTF8 );
283
284 for( const auto& netclassName : pair.value() )
285 m_netClassLabelAssignments[key].insert( netclassName.get<wxString>() );
286 }
287 },
288 {} ) );
289
290 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "netclass_patterns",
291 [&]() -> nlohmann::json
292 {
293 nlohmann::json ret = nlohmann::json::array();
294
295 for( const auto& [matcher, netclassName] : m_netClassPatternAssignments )
296 {
297 nlohmann::json pattern_json = {
298 { "pattern", matcher->GetPattern().ToUTF8() },
299 { "netclass", netclassName.ToUTF8() }
300 };
301
302 ret.push_back( std::move( pattern_json ) );
303 }
304
305 return ret;
306 },
307 [&]( const nlohmann::json& aJson )
308 {
309 if( !aJson.is_array() )
310 return;
311
313
314 for( const nlohmann::json& entry : aJson )
315 {
316 if( !entry.is_object() )
317 continue;
318
319 if( entry.contains( "pattern" ) && entry["pattern"].is_string()
320 && entry.contains( "netclass" ) && entry["netclass"].is_string() )
321 {
322 wxString pattern = entry["pattern"].get<wxString>();
323 wxString netclass = entry["netclass"].get<wxString>();
324
325 // Expand bus patterns so individual bus member nets can be matched
326 ForEachBusMember( pattern,
327 [&]( const wxString& memberPattern )
328 {
329 addSinglePatternAssignment( memberPattern, netclass );
330 } );
331 }
332 }
333 },
334 {} ) );
335
336 registerMigration( 0, 1, std::bind( &NET_SETTINGS::migrateSchema0to1, this ) );
337 registerMigration( 1, 2, std::bind( &NET_SETTINGS::migrateSchema1to2, this ) );
338 registerMigration( 2, 3, std::bind( &NET_SETTINGS::migrateSchema2to3, this ) );
339 registerMigration( 3, 4, std::bind( &NET_SETTINGS::migrateSchema3to4, this ) );
340 registerMigration( 4, 5, std::bind( &NET_SETTINGS::migrateSchema4to5, this ) );
341}
342
343
345{
346 // Release early before destroying members
347 if( m_parent )
348 {
349 m_parent->ReleaseNestedSettings( this );
350 m_parent = nullptr;
351 }
352}
353
354
355bool NET_SETTINGS::operator==( const NET_SETTINGS& aOther ) const
356{
357 if( !std::equal( std::begin( m_netClasses ), std::end( m_netClasses ),
358 std::begin( aOther.m_netClasses ) ) )
359 return false;
360
361 if( !std::equal( std::begin( m_netClassPatternAssignments ),
363 std::begin( aOther.m_netClassPatternAssignments ) ) )
364 return false;
365
366 if( !std::equal( std::begin( m_netClassLabelAssignments ),
367 std::end( m_netClassLabelAssignments ),
368 std::begin( aOther.m_netClassLabelAssignments ) ) )
369 return false;
370
371
372 if( !std::equal( std::begin( m_netColorAssignments ), std::end( m_netColorAssignments ),
373 std::begin( aOther.m_netColorAssignments ) ) )
374 return false;
375
376 return true;
377}
378
379
381{
382 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
383 {
384 for( auto& netClass : m_internals->At( "classes" ).items() )
385 {
386 if( netClass.value().contains( "nets" ) && netClass.value()["nets"].is_array() )
387 {
388 nlohmann::json migrated = nlohmann::json::array();
389
390 for( auto& net : netClass.value()["nets"].items() )
391 migrated.push_back( ConvertToNewOverbarNotation( net.value().get<wxString>() ) );
392
393 netClass.value()["nets"] = migrated;
394 }
395 }
396 }
397
398 return true;
399}
400
401
403{
404 return true;
405}
406
407
409{
410 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
411 {
412 nlohmann::json patterns = nlohmann::json::array();
413
414 for( auto& netClass : m_internals->At( "classes" ).items() )
415 {
416 if( netClass.value().contains( "name" )
417 && netClass.value().contains( "nets" )
418 && netClass.value()["nets"].is_array() )
419 {
420 wxString netClassName = netClass.value()["name"].get<wxString>();
421
422 for( auto& net : netClass.value()["nets"].items() )
423 {
424 nlohmann::json pattern_json = {
425 { "pattern", net.value().get<wxString>() },
426 { "netclass", netClassName }
427 };
428
429 patterns.push_back( pattern_json );
430 }
431 }
432 }
433
434 m_internals->SetFromString( "netclass_patterns", patterns );
435 }
436
437 return true;
438}
439
440
442{
443 // Add priority field to netclasses
444 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
445 {
446 int priority = 0;
447
448 for( auto& netClass : m_internals->At( "classes" ).items() )
449 {
450 if( netClass.value()["name"].get<wxString>() == NETCLASS::Default )
451 netClass.value()["priority"] = std::numeric_limits<int>::max();
452 else
453 netClass.value()["priority"] = priority++;
454 }
455 }
456
457 // Move netclass assignments to a list
458 if( m_internals->contains( "netclass_assignments" )
459 && m_internals->At( "netclass_assignments" ).is_object() )
460 {
461 nlohmann::json migrated = {};
462
463 for( const auto& pair : m_internals->At( "netclass_assignments" ).items() )
464 {
465 nlohmann::json netclassesJson = nlohmann::json::array();
466
467 if( pair.value().get<wxString>() != wxEmptyString )
468 netclassesJson.push_back( pair.value() );
469
470 migrated[pair.key()] = netclassesJson;
471 }
472
473 m_internals->SetFromString( "netclass_assignments", migrated );
474 }
475
476 return true;
477}
478
479
481{
482 // Add tuning profile name field to netclasses
483 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
484 {
485 const wxString emptyStr = "";
486
487 for( auto& netClass : m_internals->At( "classes" ).items() )
488 netClass.value()["tuning_profile"] = emptyStr.ToUTF8();
489 }
490
491 return true;
492}
493
494
495void NET_SETTINGS::SetDefaultNetclass( std::shared_ptr<NETCLASS> netclass )
496{
497 m_defaultNetClass = netclass;
498}
499
500
501std::shared_ptr<NETCLASS> NET_SETTINGS::GetDefaultNetclass()
502{
503 return m_defaultNetClass;
504}
505
506
507bool NET_SETTINGS::HasNetclass( const wxString& netclassName ) const
508{
509 return m_netClasses.find( netclassName ) != m_netClasses.end();
510}
511
512
513void NET_SETTINGS::SetNetclass( const wxString& netclassName, std::shared_ptr<NETCLASS>& netclass )
514{
515 m_netClasses[netclassName] = netclass;
516}
517
518
519void NET_SETTINGS::SetNetclasses( const std::map<wxString, std::shared_ptr<NETCLASS>>& netclasses )
520{
521 m_netClasses = netclasses;
523}
524
525
526const std::map<wxString, std::shared_ptr<NETCLASS>>& NET_SETTINGS::GetNetclasses() const
527{
528 return m_netClasses;
529}
530
531
532const std::map<wxString, std::shared_ptr<NETCLASS>>& NET_SETTINGS::GetCompositeNetclasses() const
533{
535}
536
537
539{
540 m_netClasses.clear();
541 m_impicitNetClasses.clear();
543}
544
545
546const std::map<wxString, std::set<wxString>>& NET_SETTINGS::GetNetclassLabelAssignments() const
547{
549}
550
551
556
557
558void NET_SETTINGS::ClearNetclassLabelAssignment( const wxString& netName )
559{
560 m_netClassLabelAssignments.erase( netName );
561}
562
563
564void NET_SETTINGS::SetNetclassLabelAssignment( const wxString& netName,
565 const std::set<wxString>& netclasses )
566{
567 m_netClassLabelAssignments[netName] = netclasses;
568}
569
570
572 const std::set<wxString>& netclasses )
573{
574 m_netClassLabelAssignments[netName].insert( netclasses.begin(), netclasses.end() );
575}
576
577
578bool NET_SETTINGS::HasNetclassLabelAssignment( const wxString& netName ) const
579{
580 return m_netClassLabelAssignments.find( netName ) != m_netClassLabelAssignments.end();
581}
582
583
584void NET_SETTINGS::SetNetclassPatternAssignment( const wxString& pattern, const wxString& netclass )
585{
586 // Expand bus patterns (vector buses and bus groups) to individual member patterns.
587 // This is necessary because the regex/wildcard matchers interpret brackets and braces
588 // as special characters, not as bus notation.
589 ForEachBusMember( pattern,
590 [&]( const wxString& memberPattern )
591 {
592 addSinglePatternAssignment( memberPattern, netclass );
593 } );
594
596}
597
598
599void NET_SETTINGS::addSinglePatternAssignment( const wxString& pattern, const wxString& netclass )
600{
601 // Avoid exact duplicates - these shouldn't cause problems, due to later de-duplication
602 // but they are unnecessary.
603 for( auto& assignment : m_netClassPatternAssignments )
604 {
605 if( assignment.first->GetPattern() == pattern && assignment.second == netclass )
606 return;
607 }
608
609 // No assignment, add a new one
611 { std::make_unique<EDA_COMBINED_MATCHER>( pattern, CTX_NETCLASS ), netclass } );
612}
613
614
616 std::vector<std::pair<std::unique_ptr<EDA_COMBINED_MATCHER>, wxString>>&& netclassPatterns )
617{
618 m_netClassPatternAssignments = std::move( netclassPatterns );
620}
621
622
623std::vector<std::pair<std::unique_ptr<EDA_COMBINED_MATCHER>, wxString>>&
628
629
634
635
636void NET_SETTINGS::ClearCacheForNet( const wxString& netName )
637{
638 if( m_effectiveNetclassCache.count( netName ) )
639 {
640 wxString compositeNetclassName = m_effectiveNetclassCache[netName]->GetName();
641 m_compositeNetClasses.erase( compositeNetclassName );
642 m_effectiveNetclassCache.erase( netName );
643 }
644}
645
646
652
653
654void NET_SETTINGS::SetNetColorAssignment( const wxString& netName, const KIGFX::COLOR4D& color )
655{
656 m_netColorAssignments[netName] = color;
657}
658
659
660const std::map<wxString, KIGFX::COLOR4D>& NET_SETTINGS::GetNetColorAssignments() const
661{
663}
664
665
670
671
672bool NET_SETTINGS::HasEffectiveNetClass( const wxString& aNetName ) const
673{
674 return m_effectiveNetclassCache.count( aNetName ) > 0;
675}
676
677
678std::shared_ptr<NETCLASS> NET_SETTINGS::GetCachedEffectiveNetClass( const wxString& aNetName ) const
679{
680 return m_effectiveNetclassCache.at( aNetName );
681}
682
683
684std::shared_ptr<NETCLASS> NET_SETTINGS::GetEffectiveNetClass( const wxString& aNetName )
685{
686 // Lambda to fetch an explicit netclass. Returns a nullptr if not found
687 auto getExplicitNetclass =
688 [this]( const wxString& netclass ) -> std::shared_ptr<NETCLASS>
689 {
690 if( netclass == NETCLASS::Default )
691 return m_defaultNetClass;
692
693 auto ii = m_netClasses.find( netclass );
694
695 if( ii == m_netClasses.end() )
696 return {};
697 else
698 return ii->second;
699 };
700
701 // Lambda to fetch or create an implicit netclass (defined with a label, but not configured)
702 // These are needed as while they do not provide any netclass parameters, they do now appear in
703 // DRC matching strings as an assigned netclass.
704 auto getOrAddImplicitNetcless =
705 [this]( const wxString& netclass ) -> std::shared_ptr<NETCLASS>
706 {
707 auto ii = m_impicitNetClasses.find( netclass );
708
709 if( ii == m_impicitNetClasses.end() )
710 {
711 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( netclass, false );
712 nc->SetPriority( std::numeric_limits<int>::max() - 1 ); // Priority > default netclass
713 m_impicitNetClasses[netclass] = nc;
714 return nc;
715 }
716 else
717 {
718 return ii->second;
719 }
720 };
721
722 // <no net> is forced to be part of the default netclass.
723 if( aNetName.IsEmpty() )
724 return m_defaultNetClass;
725
726 // First check if we have a cached resolved netclass
727 auto cacheItr = m_effectiveNetclassCache.find( aNetName );
728
729 if( cacheItr != m_effectiveNetclassCache.end() )
730 return cacheItr->second;
731
732 // No cache found - build a vector of all netclasses assigned to or matching this net
733 std::unordered_set<std::shared_ptr<NETCLASS>> resolvedNetclasses;
734
735 // First find explicit netclass assignments
736 auto it = m_netClassLabelAssignments.find( aNetName );
737
738 if( it != m_netClassLabelAssignments.end() && it->second.size() > 0 )
739 {
740 for( const wxString& netclassName : it->second )
741 {
742 std::shared_ptr<NETCLASS> netclass = getExplicitNetclass( netclassName );
743
744 if( netclass )
745 {
746 resolvedNetclasses.insert( std::move( netclass ) );
747 }
748 else
749 {
750 resolvedNetclasses.insert( getOrAddImplicitNetcless( netclassName ) );
751 }
752 }
753 }
754
755 // Now find any pattern-matched netclass assignments
756 for( const auto& [matcher, netclassName] : m_netClassPatternAssignments )
757 {
758 if( matcher->StartsWith( aNetName ) )
759 {
760 std::shared_ptr<NETCLASS> netclass = getExplicitNetclass( netclassName );
761
762 if( netclass )
763 {
764 resolvedNetclasses.insert( std::move( netclass ) );
765 }
766 else
767 {
768 resolvedNetclasses.insert( getOrAddImplicitNetcless( netclassName ) );
769 }
770 }
771 }
772
773 // Handle zero resolved netclasses
774 if( resolvedNetclasses.size() == 0 )
775 {
776 // For bus patterns, check if all members share the same netclass.
777 // If they do, the bus inherits that netclass for coloring purposes.
778 std::shared_ptr<NETCLASS> sharedNetclass;
779 bool allSameNetclass = true;
780 bool isBusPattern = false;
781
782 ForEachBusMember( aNetName,
783 [&]( const wxString& member )
784 {
785 // If ForEachBusMember gives us back the same name, it's not a bus.
786 // Skip to avoid infinite recursion.
787 if( member == aNetName )
788 return;
789
790 isBusPattern = true;
791
792 if( !allSameNetclass )
793 return;
794
795 std::shared_ptr<NETCLASS> memberNc = GetEffectiveNetClass( member );
796
797 if( !sharedNetclass )
798 {
799 sharedNetclass = memberNc;
800 }
801 else if( memberNc->GetName() != sharedNetclass->GetName() )
802 {
803 allSameNetclass = false;
804 }
805 } );
806
807 if( isBusPattern && allSameNetclass && sharedNetclass
808 && sharedNetclass->GetName() != NETCLASS::Default )
809 {
810 m_effectiveNetclassCache[aNetName] = sharedNetclass;
811 return sharedNetclass;
812 }
813
815
816 return m_defaultNetClass;
817 }
818
819 // Make and cache the effective netclass. Note that makeEffectiveNetclass will add the default
820 // netclass to resolvedNetclasses if it is needed to complete the netclass paramters set. It
821 // will also sort resolvedNetclasses by priority order.
822 std::vector<NETCLASS*> netclassPtrs;
823
824 for( const std::shared_ptr<NETCLASS>& nc : resolvedNetclasses )
825 netclassPtrs.push_back( nc.get() );
826
827 wxString name;
828 name.Printf( "Effective for net: %s", aNetName );
829 std::shared_ptr<NETCLASS> effectiveNetclass = std::make_shared<NETCLASS>( name, false );
830 makeEffectiveNetclass( effectiveNetclass, netclassPtrs );
831
832 if( netclassPtrs.size() == 1 )
833 {
834 // No defaults were added - just return the primary netclass
835 m_effectiveNetclassCache[aNetName] = *resolvedNetclasses.begin();
836 return *resolvedNetclasses.begin();
837 }
838 else
839 {
840 effectiveNetclass->SetConstituentNetclasses( std::move( netclassPtrs ) );
841
842 m_compositeNetClasses[effectiveNetclass->GetName()] = effectiveNetclass;
843 m_effectiveNetclassCache[aNetName] = effectiveNetclass;
844
845 return effectiveNetclass;
846 }
847}
848
849
851{
852 for( auto& [ncName, nc] : m_compositeNetClasses )
853 {
854 // Note this needs to be a copy in case we now need to add the default netclass
855 std::vector<NETCLASS*> constituents = nc->GetConstituentNetclasses();
856
857 wxASSERT( constituents.size() > 0 );
858
859 // If the last netclass is Default, remove it (it will be re-added if still needed)
860 if( ( *constituents.rbegin() )->GetName() == NETCLASS::Default )
861 {
862 constituents.pop_back();
863 }
864
865 // Remake the netclass from original constituents
866 nc->ResetParameters();
867 makeEffectiveNetclass( nc, constituents );
868 nc->SetConstituentNetclasses( std::move( constituents ) );
869 }
870}
871
872
873void NET_SETTINGS::makeEffectiveNetclass( std::shared_ptr<NETCLASS>& effectiveNetclass,
874 std::vector<NETCLASS*>& constituentNetclasses ) const
875{
876 // Sort the resolved netclasses by priority (highest first), with same-priority netclasses
877 // ordered alphabetically
878 std::sort( constituentNetclasses.begin(), constituentNetclasses.end(),
879 []( NETCLASS* nc1, NETCLASS* nc2 )
880 {
881 int p1 = nc1->GetPriority();
882 int p2 = nc2->GetPriority();
883
884 if( p1 < p2 )
885 return true;
886
887 if (p1 == p2)
888 return nc1->GetName().Cmp( nc2->GetName() ) < 0;
889
890 return false;
891 } );
892
893 // Iterate from lowest priority netclass and fill effective netclass parameters
894 for( auto itr = constituentNetclasses.rbegin(); itr != constituentNetclasses.rend(); ++itr )
895 {
896 NETCLASS* nc = *itr;
897
898 if( nc->HasClearance() )
899 {
900 effectiveNetclass->SetClearance( nc->GetClearance() );
901 effectiveNetclass->SetClearanceParent( nc );
902 }
903
904 if( nc->HasTrackWidth() )
905 {
906 effectiveNetclass->SetTrackWidth( nc->GetTrackWidth() );
907 effectiveNetclass->SetTrackWidthParent( nc );
908 }
909
910 if( nc->HasViaDiameter() )
911 {
912 effectiveNetclass->SetViaDiameter( nc->GetViaDiameter() );
913 effectiveNetclass->SetViaDiameterParent( nc );
914 }
915
916 if( nc->HasViaDrill() )
917 {
918 effectiveNetclass->SetViaDrill( nc->GetViaDrill() );
919 effectiveNetclass->SetViaDrillParent( nc );
920 }
921
922 if( nc->HasuViaDiameter() )
923 {
924 effectiveNetclass->SetuViaDiameter( nc->GetuViaDiameter() );
925 effectiveNetclass->SetuViaDiameterParent( nc );
926 }
927
928 if( nc->HasuViaDrill() )
929 {
930 effectiveNetclass->SetuViaDrill( nc->GetuViaDrill() );
931 effectiveNetclass->SetuViaDrillParent( nc );
932 }
933
934 if( nc->HasDiffPairWidth() )
935 {
936 effectiveNetclass->SetDiffPairWidth( nc->GetDiffPairWidth() );
937 effectiveNetclass->SetDiffPairWidthParent( nc );
938 }
939
940 if( nc->HasDiffPairGap() )
941 {
942 effectiveNetclass->SetDiffPairGap( nc->GetDiffPairGap() );
943 effectiveNetclass->SetDiffPairGapParent( nc );
944 }
945
946 if( nc->HasDiffPairViaGap() )
947 {
948 effectiveNetclass->SetDiffPairViaGap( nc->GetDiffPairViaGap() );
949 effectiveNetclass->SetDiffPairViaGapParent( nc );
950 }
951
952 if( nc->HasWireWidth() )
953 {
954 effectiveNetclass->SetWireWidth( nc->GetWireWidth() );
955 effectiveNetclass->SetWireWidthParent( nc );
956 }
957
958 if( nc->HasBusWidth() )
959 {
960 effectiveNetclass->SetBusWidth( nc->GetBusWidth() );
961 effectiveNetclass->SetBusWidthParent( nc );
962 }
963
964 if( nc->HasLineStyle() )
965 {
966 effectiveNetclass->SetLineStyle( nc->GetLineStyle() );
967 effectiveNetclass->SetLineStyleParent( nc );
968 }
969
970 COLOR4D pcbColor = nc->GetPcbColor();
971
972 if( pcbColor != COLOR4D::UNSPECIFIED )
973 {
974 effectiveNetclass->SetPcbColor( pcbColor );
975 effectiveNetclass->SetPcbColorParent( nc );
976 }
977
978 COLOR4D schColor = nc->GetSchematicColor();
979
980 if( schColor != COLOR4D::UNSPECIFIED )
981 {
982 effectiveNetclass->SetSchematicColor( schColor );
983 effectiveNetclass->SetSchematicColorParent( nc );
984 }
985
986 if( nc->HasTuningProfile() )
987 {
988 effectiveNetclass->SetTuningProfile( nc->GetTuningProfile() );
989 effectiveNetclass->SetTuningProfileParent( nc );
990 }
991 }
992
993 // Fill in any required defaults
994 if( addMissingDefaults( effectiveNetclass.get() ) )
995 constituentNetclasses.push_back( m_defaultNetClass.get() );
996}
997
998
1000{
1001 bool addedDefault = false;
1002
1003 if( !nc->HasClearance() )
1004 {
1005 addedDefault = true;
1006 nc->SetClearance( m_defaultNetClass->GetClearance() );
1008 }
1009
1010 if( !nc->HasTrackWidth() )
1011 {
1012 addedDefault = true;
1013 nc->SetTrackWidth( m_defaultNetClass->GetTrackWidth() );
1015 }
1016
1017 if( !nc->HasViaDiameter() )
1018 {
1019 addedDefault = true;
1020 nc->SetViaDiameter( m_defaultNetClass->GetViaDiameter() );
1022 }
1023
1024 if( !nc->HasViaDrill() )
1025 {
1026 addedDefault = true;
1027 nc->SetViaDrill( m_defaultNetClass->GetViaDrill() );
1029 }
1030
1031 if( !nc->HasuViaDiameter() )
1032 {
1033 addedDefault = true;
1034 nc->SetuViaDiameter( m_defaultNetClass->GetuViaDiameter() );
1036 }
1037
1038 if( !nc->HasuViaDrill() )
1039 {
1040 addedDefault = true;
1041 nc->SetuViaDrill( m_defaultNetClass->GetuViaDrill() );
1043 }
1044
1045 if( !nc->HasDiffPairWidth() )
1046 {
1047 addedDefault = true;
1048 nc->SetDiffPairWidth( m_defaultNetClass->GetDiffPairWidth() );
1050 }
1051
1052 if( !nc->HasDiffPairGap() )
1053 {
1054 addedDefault = true;
1055 nc->SetDiffPairGap( m_defaultNetClass->GetDiffPairGap() );
1057 }
1058
1059 // Currently this is only on the default netclass, and not editable in the setup panel
1060 // if( !nc->HasDiffPairViaGap() )
1061 // {
1062 // addedDefault = true;
1063 // nc->SetDiffPairViaGap( m_defaultNetClass->GetDiffPairViaGap() );
1064 // nc->SetDiffPairViaGapParent( m_defaultNetClass.get() );
1065 // }
1066
1067 if( !nc->HasWireWidth() )
1068 {
1069 addedDefault = true;
1070 nc->SetWireWidth( m_defaultNetClass->GetWireWidth() );
1072 }
1073
1074 if( !nc->HasBusWidth() )
1075 {
1076 addedDefault = true;
1077 nc->SetBusWidth( m_defaultNetClass->GetBusWidth() );
1079 }
1080
1081 // The tuning profile can be empty - only fill if a default tuning profile is set
1082 if( !nc->HasTuningProfile() && m_defaultNetClass->HasTuningProfile() )
1083 {
1084 addedDefault = true;
1085 nc->SetTuningProfile( m_defaultNetClass->GetTuningProfile() );
1087 }
1088
1089 return addedDefault;
1090}
1091
1092
1093std::shared_ptr<NETCLASS> NET_SETTINGS::GetNetClassByName( const wxString& aNetClassName ) const
1094{
1095 auto ii = m_netClasses.find( aNetClassName );
1096
1097 if( ii == m_netClasses.end() )
1098 return m_defaultNetClass;
1099 else
1100 return ii->second;
1101}
1102
1103
1104static bool isSuperSubOverbar( wxChar c )
1105{
1106 return c == '_' || c == '^' || c == '~';
1107}
1108
1109
1117static bool isEscaped( const wxString& aStr, size_t aPos )
1118{
1119 if( aPos == 0 )
1120 return false;
1121
1122 // Count consecutive backslashes before this position
1123 int backslashCount = 0;
1124 size_t pos = aPos;
1125
1126 while( pos > 0 && aStr[pos - 1] == '\\' )
1127 {
1128 backslashCount++;
1129 pos--;
1130 }
1131
1132 // If odd number of backslashes, the character is escaped
1133 return ( backslashCount % 2 ) == 1;
1134}
1135
1136
1137bool NET_SETTINGS::ParseBusVector( const wxString& aBus, wxString* aName,
1138 std::vector<wxString>* aMemberList )
1139{
1140 auto isDigit =
1141 []( wxChar c )
1142 {
1143 static wxString digits( wxT( "0123456789" ) );
1144 return digits.Contains( c );
1145 };
1146
1147 size_t busLen = aBus.length();
1148 size_t i = 0;
1149 wxString prefix;
1150 wxString suffix;
1151 wxString tmp;
1152 long begin = 0;
1153 long end = 0;
1154 int braceNesting = 0;
1155 bool fmtWrapsName = false;
1156 bool inQuotes = false;
1157
1158 prefix.reserve( busLen );
1159
1160 // Parse prefix
1161 //
1162 // Formatting markers (^{}, _{}, ~{}) can appear either as part of the prefix name
1163 // (e.g. I^{2}C[0..7]) or wrapping the range specifier (e.g. D_{[1..2]}).
1164 // We preserve formatting in the prefix and only strip it when the range bracket
1165 // appears inside formatting braces, indicating the formatting wraps the range.
1166 //
1167 for( ; i < busLen; ++i )
1168 {
1169 // Handle quoted strings (allows spaces inside)
1170 if( aBus[i] == '"' && !isEscaped( aBus, i ) )
1171 {
1172 inQuotes = !inQuotes;
1173 continue;
1174 }
1175
1176 if( inQuotes )
1177 {
1178 // Inside quotes, add characters directly (including spaces)
1179 if( aBus[i] == '\\' && i + 1 < busLen )
1180 {
1181 // Handle escaped characters inside quotes
1182 prefix += aBus[++i];
1183 }
1184 else
1185 {
1186 prefix += aBus[i];
1187 }
1188
1189 continue;
1190 }
1191
1192 if( aBus[i] == '{' )
1193 {
1194 if( i > 0 && isSuperSubOverbar( aBus[i-1] ) )
1195 {
1196 braceNesting++;
1197 prefix += wxT( '{' );
1198 continue;
1199 }
1200 else
1201 return false;
1202 }
1203 else if( aBus[i] == '}' )
1204 {
1205 braceNesting--;
1206 prefix += wxT( '}' );
1207 continue;
1208 }
1209
1210 // Handle backslash-escaped spaces
1211 if( aBus[i] == '\\' && i + 1 < busLen && aBus[i + 1] == ' ' )
1212 {
1213 prefix += aBus[++i];
1214 continue;
1215 }
1216
1217 // Unescaped space or ] in bus vector prefix is not allowed
1218 if( aBus[i] == ' ' || aBus[i] == ']' )
1219 return false;
1220
1221 if( aBus[i] == '[' )
1222 {
1223 if( braceNesting > 0 )
1224 {
1225 size_t fmtStart = prefix.rfind( wxT( '{' ) );
1226
1227 if( fmtStart != wxString::npos && fmtStart > 0
1228 && isSuperSubOverbar( prefix[fmtStart - 1] ) )
1229 {
1230 if( fmtStart == prefix.length() - 1 )
1231 {
1232 // '{' immediately precedes '[' (e.g. D_{[1..2]}).
1233 // The formatting decorates the range indices, not the
1234 // name itself.
1235 prefix.erase( fmtStart - 1 );
1236 }
1237 else
1238 {
1239 // Name characters exist between '{' and '[' (e.g.
1240 // ~{BE[0..3]}). The formatting wraps the signal name,
1241 // not the range.
1242 fmtWrapsName = true;
1243 }
1244 }
1245 }
1246
1247 break;
1248 }
1249
1250 prefix += aBus[i];
1251 }
1252
1253 // Parse start number
1254 //
1255 i++; // '[' character
1256
1257 if( i >= busLen )
1258 return false;
1259
1260 for( ; i < busLen; ++i )
1261 {
1262 if( aBus[i] == '.' && i + 1 < busLen && aBus[i+1] == '.' )
1263 {
1264 tmp.ToLong( &begin );
1265 i += 2;
1266 break;
1267 }
1268
1269 if( !isDigit( aBus[i] ) )
1270 return false;
1271
1272 tmp += aBus[i];
1273 }
1274
1275 // Parse end number
1276 //
1277 tmp = wxEmptyString;
1278
1279 if( i >= busLen )
1280 return false;
1281
1282 for( ; i < busLen; ++i )
1283 {
1284 if( aBus[i] == ']' )
1285 {
1286 tmp.ToLong( &end );
1287 ++i;
1288 break;
1289 }
1290
1291 if( !isDigit( aBus[i] ) )
1292 return false;
1293
1294 tmp += aBus[i];
1295 }
1296
1297 // Parse suffix
1298 //
1299 for( ; i < busLen; ++i )
1300 {
1301 if( aBus[i] == '}' )
1302 {
1303 braceNesting--;
1304
1305 if( fmtWrapsName )
1306 suffix += aBus[i];
1307 }
1308 else if( aBus[i] == '+' || aBus[i] == '-' || aBus[i] == 'P' || aBus[i] == 'N' )
1309 {
1310 suffix += aBus[i];
1311 }
1312 else
1313 {
1314 return false;
1315 }
1316 }
1317
1318 if( braceNesting != 0 )
1319 return false;
1320
1321 if( begin == end )
1322 return false;
1323 else if( begin > end )
1324 std::swap( begin, end );
1325
1326 if( aName )
1327 *aName = prefix;
1328
1329 if( aMemberList )
1330 {
1331 for( long idx = begin; idx <= end; ++idx )
1332 {
1333 wxString str = prefix;
1334 str << idx;
1335 str << suffix;
1336
1337 aMemberList->emplace_back( str );
1338 }
1339 }
1340
1341 return true;
1342}
1343
1344
1345bool NET_SETTINGS::ParseBusGroup( const wxString& aGroup, wxString* aName,
1346 std::vector<wxString>* aMemberList )
1347{
1348 size_t groupLen = aGroup.length();
1349 size_t i = 0;
1350 wxString prefix;
1351 wxString tmp;
1352 int braceNesting = 0;
1353 bool inQuotes = false;
1354
1355 prefix.reserve( groupLen );
1356
1357 // Escape spaces in member names so recursive parsing by ForEachBusMember works correctly.
1358 // Both quoted strings and backslash-escaped spaces collapse to bare spaces during parsing,
1359 // so we must re-escape them for subsequent ParseBusVector/ParseBusGroup calls.
1360 auto escapeSpacesForBus =
1361 []( const wxString& aMember ) -> wxString
1362 {
1363 wxString escaped;
1364 escaped.reserve( aMember.length() * 2 );
1365
1366 for( wxUniChar c : aMember )
1367 {
1368 if( c == ' ' )
1369 escaped += wxT( "\\ " );
1370 else
1371 escaped += c;
1372 }
1373
1374 return escaped;
1375 };
1376
1377 // Parse prefix
1378 //
1379 // Formatting markers (^{}, _{}, ~{}) in the prefix are part of the group name
1380 // and must be preserved. The member-list opening brace is distinguished by NOT
1381 // being preceded by a formatting character.
1382 //
1383 for( ; i < groupLen; ++i )
1384 {
1385 // Handle quoted strings (allows spaces inside)
1386 if( aGroup[i] == '"' && !isEscaped( aGroup, i ) )
1387 {
1388 inQuotes = !inQuotes;
1389 continue;
1390 }
1391
1392 if( inQuotes )
1393 {
1394 // Inside quotes, add characters directly (including spaces)
1395 if( aGroup[i] == '\\' && i + 1 < groupLen )
1396 {
1397 // Handle escaped characters inside quotes
1398 prefix += aGroup[++i];
1399 }
1400 else
1401 {
1402 prefix += aGroup[i];
1403 }
1404
1405 continue;
1406 }
1407
1408 if( aGroup[i] == '{' )
1409 {
1410 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1411 {
1412 braceNesting++;
1413 prefix += wxT( '{' );
1414 continue;
1415 }
1416 else
1417 break;
1418 }
1419 else if( aGroup[i] == '}' )
1420 {
1421 braceNesting--;
1422 prefix += wxT( '}' );
1423 continue;
1424 }
1425
1426 // Handle backslash-escaped spaces
1427 if( aGroup[i] == '\\' && i + 1 < groupLen && aGroup[i + 1] == ' ' )
1428 {
1429 prefix += aGroup[++i];
1430 continue;
1431 }
1432
1433 // Unescaped space, [, or ] in bus group prefix is not allowed
1434 if( aGroup[i] == ' ' || aGroup[i] == '[' || aGroup[i] == ']' )
1435 return false;
1436
1437 prefix += aGroup[i];
1438 }
1439
1440 if( braceNesting != 0 )
1441 return false;
1442
1443 if( aName )
1444 *aName = prefix;
1445
1446 // Parse members
1447 //
1448 i++; // '{' character
1449
1450 if( i >= groupLen )
1451 return false;
1452
1453 inQuotes = false;
1454
1455 for( ; i < groupLen; ++i )
1456 {
1457 // Handle quoted strings (allows spaces inside member names)
1458 if( aGroup[i] == '"' && !isEscaped( aGroup, i ) )
1459 {
1460 inQuotes = !inQuotes;
1461 continue;
1462 }
1463
1464 if( inQuotes )
1465 {
1466 // Inside quotes, add characters directly (including spaces)
1467 if( aGroup[i] == '\\' && i + 1 < groupLen )
1468 {
1469 // Handle escaped characters inside quotes
1470 tmp += aGroup[++i];
1471 }
1472 else
1473 {
1474 tmp += aGroup[i];
1475 }
1476
1477 continue;
1478 }
1479
1480 if( aGroup[i] == '{' )
1481 {
1482 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1483 {
1484 braceNesting++;
1485
1486 // Keep the full formatting notation (e.g. ~{CAS}) in the member name.
1487 // A net named ~{CAS} is distinct from CAS, and stripping the marker
1488 // would lose that identity. Vector bus members like D_{[1..2]} also
1489 // preserve their subscript so recursive ForEachBusMember can parse them.
1490 tmp += wxT( '{' );
1491 continue;
1492 }
1493 else
1494 return false;
1495 }
1496 else if( aGroup[i] == '}' )
1497 {
1498 if( braceNesting )
1499 {
1500 braceNesting--;
1501 tmp += wxT( '}' );
1502 continue;
1503 }
1504 else
1505 {
1506 if( aMemberList && !tmp.IsEmpty() )
1507 aMemberList->push_back( EscapeString( escapeSpacesForBus( tmp ), CTX_NETNAME ) );
1508
1509 return true;
1510 }
1511 }
1512
1513 // Handle backslash-escaped spaces in member names
1514 if( aGroup[i] == '\\' && i + 1 < groupLen && aGroup[i + 1] == ' ' )
1515 {
1516 tmp += aGroup[++i];
1517 continue;
1518 }
1519
1520 // Unescaped space or comma separates members
1521 if( aGroup[i] == ' ' || aGroup[i] == ',' )
1522 {
1523 if( aMemberList && !tmp.IsEmpty() )
1524 aMemberList->push_back( EscapeString( escapeSpacesForBus( tmp ), CTX_NETNAME ) );
1525
1526 tmp.Clear();
1527 continue;
1528 }
1529
1530 tmp += aGroup[i];
1531 }
1532
1533 return false;
1534}
1535
1536
1537void NET_SETTINGS::ForEachBusMember( const wxString& aBusPattern,
1538 const std::function<void( const wxString& )>& aFunction )
1539{
1540 std::vector<wxString> members;
1541
1542 if( ParseBusVector( aBusPattern, nullptr, &members ) )
1543 {
1544 // Vector bus: call function for each expanded member
1545 for( const wxString& member : members )
1546 aFunction( member );
1547 }
1548 else if( ParseBusGroup( aBusPattern, nullptr, &members ) )
1549 {
1550 // Bus group: recursively expand each member (which may itself be a vector or group)
1551 for( const wxString& member : members )
1552 ForEachBusMember( member, aFunction );
1553 }
1554 else
1555 {
1556 // Not a bus pattern: call function with the original pattern
1557 aFunction( aBusPattern );
1558 }
1559}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:127
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
NESTED_SETTINGS(const std::string &aName, int aSchemaVersion, JSON_SETTINGS *aParent, const std::string &aPath, bool aLoadFromFile=true)
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:42
void SetViaDiameter(int aDia)
Definition netclass.h:132
void SetViaDrill(int aSize)
Definition netclass.h:140
bool HasLineStyle() const
Definition netclass.h:230
int GetViaDiameter() const
Definition netclass.h:130
int GetViaDrill() const
Definition netclass.h:138
void SetWireWidthParent(NETCLASS *parent)
Definition netclass.h:205
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:44
void SetuViaDrillParent(NETCLASS *parent)
Definition netclass.h:158
bool HasBusWidth() const
Definition netclass.h:208
bool HasuViaDrill() const
Definition netclass.h:153
void SetDiffPairWidthParent(NETCLASS *parent)
Definition netclass.h:166
void SetuViaDiameter(int aSize)
Definition netclass.h:148
void SetDiffPairWidth(int aSize)
Definition netclass.h:164
int HasViaDrill() const
Definition netclass.h:137
int GetDiffPairViaGap() const
Definition netclass.h:178
void SetViaDrillParent(NETCLASS *parent)
Definition netclass.h:142
wxString GetTuningProfile() const
Definition netclass.h:243
void SetDiffPairGapParent(NETCLASS *parent)
Definition netclass.h:174
void SetTuningProfileParent(NETCLASS *aParent)
Definition netclass.h:244
int GetDiffPairGap() const
Definition netclass.h:170
int GetuViaDrill() const
Definition netclass.h:154
bool HasViaDiameter() const
Definition netclass.h:129
int GetLineStyle() const
Definition netclass.h:231
bool HasDiffPairWidth() const
Definition netclass.h:161
bool HasuViaDiameter() const
Definition netclass.h:145
void SetTrackWidthParent(NETCLASS *parent)
Definition netclass.h:126
int GetuViaDiameter() const
Definition netclass.h:146
bool HasTrackWidth() const
Definition netclass.h:121
void SetViaDiameterParent(NETCLASS *parent)
Definition netclass.h:134
int GetDiffPairWidth() const
Definition netclass.h:162
void SetuViaDrill(int aSize)
Definition netclass.h:156
int GetWireWidth() const
Definition netclass.h:201
void SetDiffPairGap(int aSize)
Definition netclass.h:172
void SetBusWidthParent(NETCLASS *parent)
Definition netclass.h:213
void SetClearance(int aClearance)
Definition netclass.h:116
COLOR4D GetPcbColor(bool aIsForSave=false) const
Definition netclass.h:186
bool HasDiffPairGap() const
Definition netclass.h:169
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:216
void SetBusWidth(int aWidth)
Definition netclass.h:211
void SetClearanceParent(NETCLASS *parent)
Definition netclass.h:118
int GetTrackWidth() const
Definition netclass.h:122
void SetWireWidth(int aWidth)
Definition netclass.h:203
void SetTuningProfile(const wxString &aTuningProfile)
Definition netclass.h:242
bool HasTuningProfile() const
Definition netclass.h:241
bool HasWireWidth() const
Definition netclass.h:200
int GetClearance() const
Definition netclass.h:114
void SetuViaDiameterParent(NETCLASS *parent)
Definition netclass.h:150
void SetTrackWidth(int aWidth)
Definition netclass.h:124
bool HasDiffPairViaGap() const
Definition netclass.h:177
int GetBusWidth() const
Definition netclass.h:209
bool HasClearance() const
Definition netclass.h:113
void ClearAllCaches()
Clears the effective netclass cache for all nets.
std::map< wxString, std::shared_ptr< NETCLASS > > m_compositeNetClasses
Map of netclass names to netclass definitions for.
bool addMissingDefaults(NETCLASS *nc) const
Adds any missing fields to the given netclass from the default netclass.
void ClearNetColorAssignments()
Clears all net name to color assignments Calling user is responsible for resetting the effective netc...
bool operator==(const NET_SETTINGS &aOther) const
void ClearCacheForNet(const wxString &netName)
Clears effective netclass cache for the given net.
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const wxString &aNetName)
Fetches the effective (may be aggregate) netclass for the given net name.
bool HasEffectiveNetClass(const wxString &aNetName) const
Determines if an effective netclass for the given net name has been cached.
void addSinglePatternAssignment(const wxString &pattern, const wxString &netclass)
Adds a single pattern assignment without bus expansion (internal helper)
void ClearNetclassLabelAssignments()
Clears all net name to netclasses assignments Calling user is responsible for resetting the effective...
void ClearNetclassLabelAssignment(const wxString &netName)
Clears a specific net name to netclass assignment Calling user is responsible for resetting the effec...
void ClearNetclassPatternAssignments()
Clears all netclass pattern assignments.
std::map< wxString, KIGFX::COLOR4D > m_netColorAssignments
A map of fully-qualified net names to colors used in the board context.
void SetNetclasses(const std::map< wxString, std::shared_ptr< NETCLASS > > &netclasses)
Sets all netclass Calling this method will reset the effective netclass calculation caches.
bool HasNetclassLabelAssignment(const wxString &netName) const
Determines if a given net name has netclasses assigned.
void SetNetclassLabelAssignment(const wxString &netName, const std::set< wxString > &netclasses)
Sets a net name to netclasses assignment Calling user is responsible for resetting the effective netc...
std::shared_ptr< NETCLASS > m_defaultNetClass
The default netclass.
virtual ~NET_SETTINGS()
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
void ClearNetclasses()
Clears all netclasses Calling this method will reset the effective netclass calculation caches.
std::map< wxString, std::shared_ptr< NETCLASS > > m_impicitNetClasses
Map of netclass names to netclass definitions for implicit netclasses.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > m_netClassPatternAssignments
List of net class pattern assignments.
bool migrateSchema3to4()
bool migrateSchema0to1()
std::map< wxString, std::shared_ptr< NETCLASS > > m_effectiveNetclassCache
Cache of nets to pattern-matched netclasses.
void SetNetclassPatternAssignments(std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > &&netclassPatterns)
Sets all netclass pattern assignments Calling user is responsible for resetting the effective netclas...
void SetNetclassPatternAssignment(const wxString &pattern, const wxString &netclass)
Sets a netclass pattern assignment Calling this method will reset the effective netclass calculation ...
bool migrateSchema2to3()
std::map< wxString, std::shared_ptr< NETCLASS > > m_netClasses
Map of netclass names to netclass definitions.
const std::map< wxString, std::set< wxString > > & GetNetclassLabelAssignments() const
Gets all current net name to netclasses assignments.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
const std::map< wxString, KIGFX::COLOR4D > & GetNetColorAssignments() const
Gets all net name to color assignments.
bool migrateSchema1to2()
std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > & GetNetclassPatternAssignments()
Gets the netclass pattern assignments.
void RecomputeEffectiveNetclasses()
Recomputes the internal values of all aggregate effective netclasses Called when a value of a user-de...
std::shared_ptr< NETCLASS > GetCachedEffectiveNetClass(const wxString &aNetName) const
Returns an already cached effective netclass for the given net name.
bool migrateSchema4to5()
std::map< wxString, std::set< wxString > > m_netClassLabelAssignments
Map of net names to resolved netclasses.
void SetNetclass(const wxString &netclassName, std::shared_ptr< NETCLASS > &netclass)
Sets the given netclass Calling user is responsible for resetting the effective netclass calculation ...
void makeEffectiveNetclass(std::shared_ptr< NETCLASS > &effectiveNetclass, std::vector< NETCLASS * > &netclasses) const
Creates an effective aggregate netclass from the given constituent netclasses.
void AppendNetclassLabelAssignment(const wxString &netName, const std::set< wxString > &netclasses)
Apppends to a net name to netclasses assignment Calling user is responsible for resetting the effecti...
void SetDefaultNetclass(std::shared_ptr< NETCLASS > netclass)
Sets the default netclass for the project Calling user is responsible for resetting the effective net...
static void ForEachBusMember(const wxString &aBusPattern, const std::function< void(const wxString &)> &aFunction)
Call a function for each member of an expanded bus pattern.
std::shared_ptr< NETCLASS > GetNetClassByName(const wxString &aNetName) const
Get a NETCLASS object from a given Netclass name string.
void SetNetColorAssignment(const wxString &netName, const KIGFX::COLOR4D &color)
Sets a net to color assignment Calling user is responsible for resetting the effective netclass calcu...
NET_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
bool HasNetclass(const wxString &netclassName) const
Determines if the given netclass exists.
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:297
bool isDigit(char cc)
Definition dsnlexer.cpp:469
#define _(s)
@ CTX_NETCLASS
nlohmann::json json
Definition gerbview.cpp:53
static bool isSuperSubOverbar(wxChar c)
const int netSettingsSchemaVersion
static bool isEscaped(const wxString &aStr, size_t aPos)
Check if a character at the given position is escaped by a backslash.
static std::optional< int > getInSchUnits(const nlohmann::json &aObj, const std::string &aKey, std::optional< int > aDefault=std::optional< int >())
static std::optional< int > getInPcbUnits(const nlohmann::json &aObj, const std::string &aKey, std::optional< int > aDefault=std::optional< int >())
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
VECTOR2I end