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