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