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 inQuotes = false;
1156
1157 prefix.reserve( busLen );
1158
1159 // Parse prefix
1160 //
1161 // Formatting markers (^{}, _{}, ~{}) can appear either as part of the prefix name
1162 // (e.g. I^{2}C[0..7]) or wrapping the range specifier (e.g. D_{[1..2]}).
1163 // We preserve formatting in the prefix and only strip it when the range bracket
1164 // appears inside formatting braces, indicating the formatting wraps the range.
1165 //
1166 for( ; i < busLen; ++i )
1167 {
1168 // Handle quoted strings (allows spaces inside)
1169 if( aBus[i] == '"' && !isEscaped( aBus, i ) )
1170 {
1171 inQuotes = !inQuotes;
1172 continue;
1173 }
1174
1175 if( inQuotes )
1176 {
1177 // Inside quotes, add characters directly (including spaces)
1178 if( aBus[i] == '\\' && i + 1 < busLen )
1179 {
1180 // Handle escaped characters inside quotes
1181 prefix += aBus[++i];
1182 }
1183 else
1184 {
1185 prefix += aBus[i];
1186 }
1187
1188 continue;
1189 }
1190
1191 if( aBus[i] == '{' )
1192 {
1193 if( i > 0 && isSuperSubOverbar( aBus[i-1] ) )
1194 {
1195 braceNesting++;
1196 prefix += wxT( '{' );
1197 continue;
1198 }
1199 else
1200 return false;
1201 }
1202 else if( aBus[i] == '}' )
1203 {
1204 braceNesting--;
1205 prefix += wxT( '}' );
1206 continue;
1207 }
1208
1209 // Handle backslash-escaped spaces
1210 if( aBus[i] == '\\' && i + 1 < busLen && aBus[i + 1] == ' ' )
1211 {
1212 prefix += aBus[++i];
1213 continue;
1214 }
1215
1216 // Unescaped space or ] in bus vector prefix is not allowed
1217 if( aBus[i] == ' ' || aBus[i] == ']' )
1218 return false;
1219
1220 if( aBus[i] == '[' )
1221 {
1222 if( braceNesting > 0 )
1223 {
1224 // The range bracket is inside formatting braces (e.g. D_{[1..2]}).
1225 // Strip the formatting wrapper from the prefix since it decorates the
1226 // range indices, not the name itself.
1227 size_t fmtStart = prefix.rfind( wxT( '{' ) );
1228
1229 if( fmtStart != wxString::npos && fmtStart > 0
1230 && isSuperSubOverbar( prefix[fmtStart - 1] ) )
1231 {
1232 prefix.erase( fmtStart - 1 );
1233 }
1234 }
1235
1236 break;
1237 }
1238
1239 prefix += aBus[i];
1240 }
1241
1242 // Parse start number
1243 //
1244 i++; // '[' character
1245
1246 if( i >= busLen )
1247 return false;
1248
1249 for( ; i < busLen; ++i )
1250 {
1251 if( aBus[i] == '.' && i + 1 < busLen && aBus[i+1] == '.' )
1252 {
1253 tmp.ToLong( &begin );
1254 i += 2;
1255 break;
1256 }
1257
1258 if( !isDigit( aBus[i] ) )
1259 return false;
1260
1261 tmp += aBus[i];
1262 }
1263
1264 // Parse end number
1265 //
1266 tmp = wxEmptyString;
1267
1268 if( i >= busLen )
1269 return false;
1270
1271 for( ; i < busLen; ++i )
1272 {
1273 if( aBus[i] == ']' )
1274 {
1275 tmp.ToLong( &end );
1276 ++i;
1277 break;
1278 }
1279
1280 if( !isDigit( aBus[i] ) )
1281 return false;
1282
1283 tmp += aBus[i];
1284 }
1285
1286 // Parse suffix
1287 //
1288 for( ; i < busLen; ++i )
1289 {
1290 if( aBus[i] == '}' )
1291 {
1292 braceNesting--;
1293 }
1294 else if( aBus[i] == '+' || aBus[i] == '-' || aBus[i] == 'P' || aBus[i] == 'N' )
1295 {
1296 suffix += aBus[i];
1297 }
1298 else
1299 {
1300 return false;
1301 }
1302 }
1303
1304 if( braceNesting != 0 )
1305 return false;
1306
1307 if( begin == end )
1308 return false;
1309 else if( begin > end )
1310 std::swap( begin, end );
1311
1312 if( aName )
1313 *aName = prefix;
1314
1315 if( aMemberList )
1316 {
1317 for( long idx = begin; idx <= end; ++idx )
1318 {
1319 wxString str = prefix;
1320 str << idx;
1321 str << suffix;
1322
1323 aMemberList->emplace_back( str );
1324 }
1325 }
1326
1327 return true;
1328}
1329
1330
1331bool NET_SETTINGS::ParseBusGroup( const wxString& aGroup, wxString* aName,
1332 std::vector<wxString>* aMemberList )
1333{
1334 size_t groupLen = aGroup.length();
1335 size_t i = 0;
1336 wxString prefix;
1337 wxString tmp;
1338 int braceNesting = 0;
1339 bool inQuotes = false;
1340
1341 prefix.reserve( groupLen );
1342
1343 // Escape spaces in member names so recursive parsing by ForEachBusMember works correctly.
1344 // Both quoted strings and backslash-escaped spaces collapse to bare spaces during parsing,
1345 // so we must re-escape them for subsequent ParseBusVector/ParseBusGroup calls.
1346 auto escapeSpacesForBus =
1347 []( const wxString& aMember ) -> wxString
1348 {
1349 wxString escaped;
1350 escaped.reserve( aMember.length() * 2 );
1351
1352 for( wxUniChar c : aMember )
1353 {
1354 if( c == ' ' )
1355 escaped += wxT( "\\ " );
1356 else
1357 escaped += c;
1358 }
1359
1360 return escaped;
1361 };
1362
1363 // Parse prefix
1364 //
1365 // Formatting markers (^{}, _{}, ~{}) in the prefix are part of the group name
1366 // and must be preserved. The member-list opening brace is distinguished by NOT
1367 // being preceded by a formatting character.
1368 //
1369 for( ; i < groupLen; ++i )
1370 {
1371 // Handle quoted strings (allows spaces inside)
1372 if( aGroup[i] == '"' && !isEscaped( aGroup, i ) )
1373 {
1374 inQuotes = !inQuotes;
1375 continue;
1376 }
1377
1378 if( inQuotes )
1379 {
1380 // Inside quotes, add characters directly (including spaces)
1381 if( aGroup[i] == '\\' && i + 1 < groupLen )
1382 {
1383 // Handle escaped characters inside quotes
1384 prefix += aGroup[++i];
1385 }
1386 else
1387 {
1388 prefix += aGroup[i];
1389 }
1390
1391 continue;
1392 }
1393
1394 if( aGroup[i] == '{' )
1395 {
1396 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1397 {
1398 braceNesting++;
1399 prefix += wxT( '{' );
1400 continue;
1401 }
1402 else
1403 break;
1404 }
1405 else if( aGroup[i] == '}' )
1406 {
1407 braceNesting--;
1408 prefix += wxT( '}' );
1409 continue;
1410 }
1411
1412 // Handle backslash-escaped spaces
1413 if( aGroup[i] == '\\' && i + 1 < groupLen && aGroup[i + 1] == ' ' )
1414 {
1415 prefix += aGroup[++i];
1416 continue;
1417 }
1418
1419 // Unescaped space, [, or ] in bus group prefix is not allowed
1420 if( aGroup[i] == ' ' || aGroup[i] == '[' || aGroup[i] == ']' )
1421 return false;
1422
1423 prefix += aGroup[i];
1424 }
1425
1426 if( braceNesting != 0 )
1427 return false;
1428
1429 if( aName )
1430 *aName = prefix;
1431
1432 // Parse members
1433 //
1434 i++; // '{' character
1435
1436 if( i >= groupLen )
1437 return false;
1438
1439 inQuotes = false;
1440
1441 for( ; i < groupLen; ++i )
1442 {
1443 // Handle quoted strings (allows spaces inside member names)
1444 if( aGroup[i] == '"' && !isEscaped( aGroup, i ) )
1445 {
1446 inQuotes = !inQuotes;
1447 continue;
1448 }
1449
1450 if( inQuotes )
1451 {
1452 // Inside quotes, add characters directly (including spaces)
1453 if( aGroup[i] == '\\' && i + 1 < groupLen )
1454 {
1455 // Handle escaped characters inside quotes
1456 tmp += aGroup[++i];
1457 }
1458 else
1459 {
1460 tmp += aGroup[i];
1461 }
1462
1463 continue;
1464 }
1465
1466 if( aGroup[i] == '{' )
1467 {
1468 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1469 {
1470 braceNesting++;
1471
1472 // Keep the full formatting notation (e.g. ~{CAS}) in the member name.
1473 // A net named ~{CAS} is distinct from CAS, and stripping the marker
1474 // would lose that identity. Vector bus members like D_{[1..2]} also
1475 // preserve their subscript so recursive ForEachBusMember can parse them.
1476 tmp += wxT( '{' );
1477 continue;
1478 }
1479 else
1480 return false;
1481 }
1482 else if( aGroup[i] == '}' )
1483 {
1484 if( braceNesting )
1485 {
1486 braceNesting--;
1487 tmp += wxT( '}' );
1488 continue;
1489 }
1490 else
1491 {
1492 if( aMemberList && !tmp.IsEmpty() )
1493 aMemberList->push_back( EscapeString( escapeSpacesForBus( tmp ), CTX_NETNAME ) );
1494
1495 return true;
1496 }
1497 }
1498
1499 // Handle backslash-escaped spaces in member names
1500 if( aGroup[i] == '\\' && i + 1 < groupLen && aGroup[i + 1] == ' ' )
1501 {
1502 tmp += aGroup[++i];
1503 continue;
1504 }
1505
1506 // Unescaped space or comma separates members
1507 if( aGroup[i] == ' ' || aGroup[i] == ',' )
1508 {
1509 if( aMemberList && !tmp.IsEmpty() )
1510 aMemberList->push_back( EscapeString( escapeSpacesForBus( tmp ), CTX_NETNAME ) );
1511
1512 tmp.Clear();
1513 continue;
1514 }
1515
1516 tmp += aGroup[i];
1517 }
1518
1519 return false;
1520}
1521
1522
1523void NET_SETTINGS::ForEachBusMember( const wxString& aBusPattern,
1524 const std::function<void( const wxString& )>& aFunction )
1525{
1526 std::vector<wxString> members;
1527
1528 if( ParseBusVector( aBusPattern, nullptr, &members ) )
1529 {
1530 // Vector bus: call function for each expanded member
1531 for( const wxString& member : members )
1532 aFunction( member );
1533 }
1534 else if( ParseBusGroup( aBusPattern, nullptr, &members ) )
1535 {
1536 // Bus group: recursively expand each member (which may itself be a vector or group)
1537 for( const wxString& member : members )
1538 ForEachBusMember( member, aFunction );
1539 }
1540 else
1541 {
1542 // Not a bus pattern: call function with the original pattern
1543 aFunction( aBusPattern );
1544 }
1545}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
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:50
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