KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sim_model_serializer.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) 2022 Mikolaj Wielgus
5 * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * https://www.gnu.org/licenses/gpl-3.0.html
20 * or you may search the http://www.gnu.org website for the version 3 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26#include <fmt/core.h>
27#include <pegtl.hpp>
28#include <pegtl/contrib/parse_tree.hpp>
29#include <boost/algorithm/string/replace.hpp>
30#include <boost/algorithm/string/case_conv.hpp>
31#include <boost/algorithm/string/predicate.hpp>
32#include <string_utils.h>
33
34
36{
37 using namespace SIM_MODEL_SERIALIZER_GRAMMAR;
38
39 template <typename Rule> struct fieldParamValuePairsSelector : std::false_type {};
40 template <> struct fieldParamValuePairsSelector<param> : std::true_type {};
41 template <> struct fieldParamValuePairsSelector<flagParam> : std::true_type {};
42 template <> struct fieldParamValuePairsSelector<quotedStringContent> : std::true_type {};
43 template <> struct fieldParamValuePairsSelector<unquotedString> : std::true_type {};
44
45
46 template <typename Rule> struct pinSequenceSelector : std::false_type {};
47 template <> struct pinSequenceSelector<pinAssignment> : std::true_type {};
48 template <> struct pinSequenceSelector<pinSymbolPinNumber> : std::true_type {};
49 template <> struct pinSequenceSelector<pinName> : std::true_type {};
50
51 template <typename Rule> struct fieldInferValueSelector : std::false_type {};
52 template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {};
53}
54
55
57{
58 return m_model.GetDeviceInfo().fieldValue;
59}
60
61
63{
64 return m_model.GetTypeInfo().fieldValue;
65}
66
67
69{
71 std::string result = param.value;
72
73 if( result == "" )
74 result = m_model.GetDeviceInfo().fieldValue;
75
76 return result;
77}
78
79
81{
82 std::string result;
83 bool isFirst = true;
84
85 for( int i = 0; i < m_model.GetParamCount(); ++i )
86 {
87 if( i == 0 && m_model.IsStoredInValue() )
88 continue;
89
91
92 if( param.value == ""
93 && !( i == 0 && m_model.HasPrimaryValue() && !m_model.IsStoredInValue() ) )
94 {
95 continue;
96 }
97
98 if( m_model.GetBaseModel() && m_model.GetBaseModel()->GetParam( i ).value == param.value )
99 continue;
100
101 // If the parameter is an enum and the value is default, don't write anything.
102 if( param.info.enumValues.size() >= 1 && param.value == param.info.defaultValue )
103 continue;
104
105 std::string paramValuePair = generateParamValuePair( param );
106
107 if( paramValuePair == "" )
108 continue; // Prevent adding empty spaces.
109
110 if( isFirst ) // Don't add a space at the beginning.
111 isFirst = false;
112 else
113 result.append( " " );
114
115 result.append( paramValuePair );
116 }
117
118 return result;
119}
120
121
123{
124 std::string result;
125
126 std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> pins = m_model.GetPins();
127
128 // m_model.GetPins() returns pins in the order they appear in the model, but the keys in the
129 // key=value pairs we create here are symbol pin numbers, so we sort the pins so that they are
130 // ordered by the latter instead.
131 std::sort( pins.begin(), pins.end(),
132 []( const SIM_MODEL_PIN& lhs, const SIM_MODEL_PIN& rhs )
133 {
134 return StrNumCmp( lhs.symbolPinNumber, rhs.symbolPinNumber, true ) < 0;
135 } );
136
137 for( const SIM_MODEL_PIN& pin : pins )
138 {
139 std::string symbolPinNumber( pin.symbolPinNumber.ToUTF8() );
140
141 if( symbolPinNumber != "" )
142 {
143 if( !result.empty() )
144 result.append( " " );
145
146 result.append( fmt::format( "{}={}", symbolPinNumber, pin.modelPinName ) );
147 }
148 }
149
150 return result;
151}
152
153
155{
156 return m_model.IsEnabled() ? "" : "0";
157}
158
159
160void SIM_MODEL_SERIALIZER::ParseValue( const std::string& aValue )
161{
162 try
163 {
164 tao::pegtl::string_input<> in( aValue, "Value field" );
165 auto root =
166 tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::fieldInferValueGrammar,
168 tao::pegtl::nothing,
170 ( in );
171
172 for( const auto& node : root->children )
173 {
175 SIM_VALUE::NOTATION::SI>>()
176 && node->string() != "" )
177 {
178 m_model.SetParamValue( 0, node->string() );
179 }
180 }
181 }
182 catch( const tao::pegtl::parse_error& e )
183 {
184 THROW_IO_ERROR( e.what() );
185 }
186
188}
189
190
191bool SIM_MODEL_SERIALIZER::ParseParams( const std::string& aParams )
192{
193 tao::pegtl::string_input<> in( aParams, "Sim.Params field" );
194 std::unique_ptr<tao::pegtl::parse_tree::node> root;
195
196 try
197 {
198 // Using parse tree instead of actions because we don't care about performance that much,
199 // and having a tree greatly simplifies things.
200 root = tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::fieldParamValuePairsGrammar,
202 tao::pegtl::nothing,
204 ( in );
205 }
206 catch( const tao::pegtl::parse_error& e )
207 {
208 THROW_IO_ERROR( e.what() );
209 }
210
211 std::string paramName;
212 bool isPrimaryValueSet = false;
213
214 for( const auto& node : root->children )
215 {
216 if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::param>() )
217 {
218 paramName = node->string();
219 }
220 // TODO: Do something with number<SIM_VALUE::TYPE_INT, ...>.
221 // It doesn't seem too useful?
224 {
225 wxASSERT( paramName != "" );
226
227 m_model.SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI );
228
229 if( m_model.GetParam( 0 ).Matches( paramName ) )
230 isPrimaryValueSet = true;
231 }
232 else if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::quotedString>() )
233 {
234 std::string str = node->string();
235
236 // Unescape quotes.
237 boost::replace_all( str, "\\\"", "\"" );
238
240 }
241 else if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::flagParam>() )
242 {
243 std::string token = node->string();
244
246 }
247 else
248 {
249 wxFAIL;
250 }
251 }
252
253 return !m_model.HasPrimaryValue() || m_model.HasAutofill() || isPrimaryValueSet;
254}
255
256
257void SIM_MODEL_SERIALIZER::ParsePins( const std::string& aPins )
258{
259 if( aPins == "" )
260 return;
261
262 tao::pegtl::string_input<> in( aPins, "Sim.Pins field" );
263 std::unique_ptr<tao::pegtl::parse_tree::node> root;
264
265 try
266 {
267 root = tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::pinSequenceGrammar,
269 tao::pegtl::nothing,
271 ( in );
272
273 for( const auto& node : root->children )
274 {
275 std::string symbolPinNumber = node->children.at( 0 )->string();
276 std::string modelPinName = node->children.at( 1 )->string();
277
278 m_model.AssignSymbolPinNumberToModelPin( modelPinName, symbolPinNumber );
279 }
280 }
281 catch( const tao::pegtl::parse_error& e )
282 {
283 THROW_IO_ERROR( e.what() );
284 }
285}
286
287
288void SIM_MODEL_SERIALIZER::ParseEnable( const std::string& aEnable )
289{
290 if( aEnable == "" )
291 return;
292
293 char c = boost::to_lower_copy( aEnable )[0];
294
295 if( c == 'n' || c == 'f' || c == '0' )
296 m_model.SetIsEnabled( false );
297}
298
299
301{
302 std::string name = aParam.info.name;
303
304 // Because of collisions with instance parameters, we append some model parameters with "_".
305 if( boost::ends_with( name, "_" ) )
306 name = name.substr( 0, aParam.info.name.length() - 1 );
307
308 std::string value = aParam.value;
309
311 return value == "1" ? name : "";
312
313 if( value == "" || value.find( ' ' ) != std::string::npos )
314 value = fmt::format( "\"{}\"", value );
315
316 return fmt::format( "{}={}", name, value );
317}
const char * name
Definition: DXF_plotter.cpp:57
std::string GeneratePins() const
void ParsePins(const std::string &aPins)
std::string generateParamValuePair(const SIM_MODEL::PARAM &aParam) const
std::string GenerateParams() const
std::string GenerateValue() const
void ParseValue(const std::string &aValue)
void ParseEnable(const std::string &aEnable)
std::string GenerateEnable() const
std::string GenerateDevice() const
bool ParseParams(const std::string &aParams)
std::string GenerateDeviceSubtype() const
const SIM_MODEL * GetBaseModel() const
Definition: sim_model.h:466
bool IsStoredInValue() const
Definition: sim_model.h:511
bool IsEnabled() const
Definition: sim_model.h:504
virtual const PARAM & GetParam(unsigned aParamIndex) const
Definition: sim_model.cpp:780
int GetParamCount() const
Definition: sim_model.h:481
void AssignSymbolPinNumberToModelPin(int aPinIndex, const wxString &aSymbolPinNumber)
Definition: sim_model.cpp:749
DEVICE_INFO GetDeviceInfo() const
Definition: sim_model.h:460
INFO GetTypeInfo() const
Definition: sim_model.h:461
const PARAM & GetParamOverride(unsigned aParamIndex) const
Definition: sim_model.cpp:828
virtual bool HasAutofill() const
Definition: sim_model.h:500
void SetIsEnabled(bool aIsEnabled)
Definition: sim_model.h:503
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
Definition: sim_model.cpp:849
void SetIsStoredInValue(bool aIsStoredInValue)
Definition: sim_model.h:506
virtual bool HasPrimaryValue() const
Definition: sim_model.h:501
std::vector< std::reference_wrapper< const SIM_MODEL_PIN > > GetPins() const
Definition: sim_model.cpp:739
@ TYPE_FLOAT
Definition: sim_value.h:69
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
must_if< error >::control< Rule > control
bool Matches(const std::string &aName) const
Definition: sim_model.h:395
std::string value
Definition: sim_model.h:400
const INFO & info
Definition: sim_model.h:401