-
-
Notifications
You must be signed in to change notification settings - Fork 486
/
component_class_manager.cpp
210 lines (165 loc) · 6.61 KB
/
component_class_manager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utility>
#include <component_class_manager.h>
void COMPONENT_CLASS::AddConstituentClass( COMPONENT_CLASS* componentClass )
{
m_constituentClasses.push_back( componentClass );
}
bool COMPONENT_CLASS::ContainsClassName( const wxString& className ) const
{
if( m_constituentClasses.size() == 0 )
return false;
if( m_constituentClasses.size() == 1 )
return m_name == className;
return std::any_of( m_constituentClasses.begin(), m_constituentClasses.end(),
[&className]( const COMPONENT_CLASS* testClass )
{
return testClass->GetFullName() == className;
} );
}
wxString COMPONENT_CLASS::GetName() const
{
if( m_constituentClasses.size() == 0 )
return wxT( "<None>" );
if( m_constituentClasses.size() == 1 )
return m_name;
wxASSERT( m_constituentClasses.size() >= 2 );
wxString name;
if( m_constituentClasses.size() == 2 )
{
name.Printf( _( "%s and %s" ), m_constituentClasses[0]->GetName(),
m_constituentClasses[1]->GetName() );
}
else if( m_constituentClasses.size() == 3 )
{
name.Printf( _( "%s, %s and %s" ), m_constituentClasses[0]->GetName(),
m_constituentClasses[1]->GetName(), m_constituentClasses[2]->GetName() );
}
else if( m_constituentClasses.size() > 3 )
{
name.Printf( _( "%s, %s and %d more" ), m_constituentClasses[0]->GetName(),
m_constituentClasses[1]->GetName(),
static_cast<int>( m_constituentClasses.size() - 2 ) );
}
return name;
}
bool COMPONENT_CLASS::IsEmpty() const
{
return m_constituentClasses.size() == 0;
}
COMPONENT_CLASS_MANAGER::COMPONENT_CLASS_MANAGER()
{
m_noneClass = std::make_unique<COMPONENT_CLASS>( wxEmptyString );
}
COMPONENT_CLASS*
COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString>& classNames )
{
if( classNames.size() == 0 )
return m_noneClass.get();
// Lambda to handle finding constituent component classes. This first checks the cache,
// and if found moves the class to the primary classes map. If not found, it either returns
// an existing class in the primary list or creates a new class.
auto getOrCreateClass = [this]( const wxString& className )
{
if( m_classesCache.count( className ) )
{
auto existingClass = m_classesCache.extract( className );
m_classes.insert( std::move( existingClass ) );
}
else if( !m_classes.count( className ) )
{
std::unique_ptr<COMPONENT_CLASS> newClass =
std::make_unique<COMPONENT_CLASS>( className );
newClass->AddConstituentClass( newClass.get() );
m_classes[className] = std::move( newClass );
}
return m_classes[className].get();
};
// Handle single-assignment component classes
if( classNames.size() == 1 )
return getOrCreateClass( *classNames.begin() );
// Handle composite component classes
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
[]( const wxString& str1, const wxString& str2 )
{
return str1.Cmp( str2 ) < 0;
} );
wxString fullName = GetFullClassNameForConstituents( sortedClassNames );
if( m_effectiveClassesCache.count( fullName ) )
{
// The effective class was previously constructed - copy it across to the new live map
auto existingClass = m_effectiveClassesCache.extract( fullName );
COMPONENT_CLASS* effClass = existingClass.mapped().get();
m_effectiveClasses.insert( std::move( existingClass ) );
// Ensure that all constituent component classes are copied to the live map
for( COMPONENT_CLASS* constClass : effClass->GetConstituentClasses() )
{
if( m_classesCache.count( constClass->GetFullName() ) )
{
auto constClassNode = m_classesCache.extract( constClass->GetFullName() );
m_classes.insert( std::move( constClassNode ) );
}
}
}
else if( !m_effectiveClasses.count( fullName ) )
{
// The effective class was not previously constructed
std::unique_ptr<COMPONENT_CLASS> effClass = std::make_unique<COMPONENT_CLASS>( fullName );
for( const wxString& className : sortedClassNames )
effClass->AddConstituentClass( getOrCreateClass( className ) );
m_effectiveClasses[fullName] = std::move( effClass );
}
return m_effectiveClasses[fullName].get();
}
void COMPONENT_CLASS_MANAGER::InitNetlistUpdate()
{
m_classesCache = std::move( m_classes );
m_effectiveClassesCache = std::move( m_effectiveClasses );
}
void COMPONENT_CLASS_MANAGER::FinishNetlistUpdate()
{
m_classesCache.clear();
m_effectiveClassesCache.clear();
}
wxString
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( std::unordered_set<wxString>& classNames )
{
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
[]( const wxString& str1, const wxString& str2 )
{
return str1.Cmp( str2 ) < 0;
} );
return GetFullClassNameForConstituents( sortedClassNames );
}
wxString
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( std::vector<wxString>& classNames )
{
if( classNames.size() == 0 )
return wxEmptyString;
wxString fullName = classNames[0];
for( std::size_t i = 1; i < classNames.size(); ++i )
{
fullName += ",";
fullName += classNames[i];
}
return fullName;
}