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
27#include <ki_exception.h>
28#include <fmt/core.h>
29#include <pegtl.hpp>
30#include <pegtl/contrib/parse_tree.hpp>
31#include <boost/algorithm/string/replace.hpp>
32#include <boost/algorithm/string/case_conv.hpp>
33#include <boost/algorithm/string/predicate.hpp>
34#include <string_utils.h>
35
36
38{
39 using namespace SIM_MODEL_SERIALIZER_GRAMMAR;
40
41 template <typename Rule> struct fieldParamValuePairsSelector : std::false_type {};
42 template <> struct fieldParamValuePairsSelector<param> : std::true_type {};
43 template <> struct fieldParamValuePairsSelector<flagParam> : std::true_type {};
44 template <> struct fieldParamValuePairsSelector<quotedStringContent> : std::true_type {};
45 template <> struct fieldParamValuePairsSelector<unquotedString> : std::true_type {};
46
47
48 template <typename Rule> struct pinSequenceSelector : std::false_type {};
49 template <> struct pinSequenceSelector<pinAssignment> : std::true_type {};
50 template <> struct pinSequenceSelector<pinSymbolPinNumber> : std::true_type {};
51 template <> struct pinSequenceSelector<pinName> : std::true_type {};
52
53 template <typename Rule> struct fieldInferValueSelector : std::false_type {};
54 template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {};
55}
56
57
59{
60 return m_model.GetDeviceInfo().fieldValue;
61}
62
63
65{
66 return m_model.GetTypeInfo().fieldValue;
67}
68
69
71{
73 std::string result = param.value;
74
75 if( result == "" )
76 result = m_model.GetDeviceInfo().fieldValue;
77
78 return result;
79}
80
81
83{
84 std::string result;
85 bool isFirst = true;
86
87 for( int i = 0; i < m_model.GetParamCount(); ++i )
88 {
89 if( i == 0 && m_model.IsStoredInValue() )
90 continue;
91
93
94 if( param.value == ""
95 && !( i == 0 && m_model.HasPrimaryValue() && !m_model.IsStoredInValue() ) )
96 {
97 continue;
98 }
99
100 if( m_model.GetBaseModel() && m_model.GetBaseModel()->GetParam( i ).value == param.value )
101 continue;
102
103 // If the parameter is an enum and the value is default, don't write anything.
104 if( param.info.enumValues.size() >= 1 && param.value == param.info.defaultValue )
105 continue;
106
107 std::string paramValuePair = generateParamValuePair( param );
108
109 if( paramValuePair == "" )
110 continue; // Prevent adding empty spaces.
111
112 if( isFirst ) // Don't add a space at the beginning.
113 isFirst = false;
114 else
115 result.append( " " );
116
117 result.append( paramValuePair );
118 }
119
120 return result;
121}
122
123
125{
126 std::string result;
127
128 std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> pins = m_model.GetPins();
129
130 // m_model.GetPins() returns pins in the order they appear in the model, but the keys in the
131 // key=value pairs we create here are symbol pin numbers, so we sort the pins so that they are
132 // ordered by the latter instead.
133 std::sort( pins.begin(), pins.end(),
134 []( const SIM_MODEL_PIN& lhs, const SIM_MODEL_PIN& rhs )
135 {
136 return StrNumCmp( lhs.symbolPinNumber, rhs.symbolPinNumber, true ) < 0;
137 } );
138
139 for( const SIM_MODEL_PIN& pin : pins )
140 {
141 std::string symbolPinNumber( pin.symbolPinNumber.ToUTF8() );
142
143 if( symbolPinNumber != "" )
144 {
145 if( !result.empty() )
146 result.append( " " );
147
148 result.append( fmt::format( "{}={}", symbolPinNumber, pin.modelPinName ) );
149 }
150 }
151
152 return result;
153}
154
155
157{
158 return m_model.IsEnabled() ? "" : "0";
159}
160
161
162void SIM_MODEL_SERIALIZER::ParseValue( const std::string& aValue )
163{
164 try
165 {
166 tao::pegtl::string_input<> in( aValue, "Value field" );
167 auto root =
168 tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::fieldInferValueGrammar,
170 tao::pegtl::nothing,
172 ( in );
173
174 for( const auto& node : root->children )
175 {
177 SIM_VALUE::NOTATION::SI>>()
178 && node->string() != "" )
179 {
180 m_model.SetParamValue( 0, node->string() );
181 }
182 }
183 }
184 catch( const tao::pegtl::parse_error& e )
185 {
186 THROW_IO_ERROR( e.what() );
187 }
188
190}
191
192
193bool SIM_MODEL_SERIALIZER::ParseParams( const std::string& aParams )
194{
195 tao::pegtl::string_input<> in( aParams, "Sim.Params field" );
196 std::unique_ptr<tao::pegtl::parse_tree::node> root;
197
198 try
199 {
200 // Using parse tree instead of actions because we don't care about performance that much,
201 // and having a tree greatly simplifies things.
202 root = tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::fieldParamValuePairsGrammar,
204 tao::pegtl::nothing,
206 ( in );
207 }
208 catch( const tao::pegtl::parse_error& e )
209 {
210 THROW_IO_ERROR( e.what() );
211 }
212
213 std::string paramName;
214 bool isPrimaryValueSet = false;
215
216 for( const auto& node : root->children )
217 {
218 if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::param>() )
219 {
220 paramName = node->string();
221 }
222 // TODO: Do something with number<SIM_VALUE::TYPE_INT, ...>.
223 // It doesn't seem too useful?
226 {
227 wxASSERT( paramName != "" );
228
229 m_model.SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI );
230
231 if( m_model.GetParam( 0 ).Matches( paramName ) )
232 isPrimaryValueSet = true;
233 }
234 else if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::quotedString>() )
235 {
236 std::string str = node->string();
237
238 // Unescape quotes.
239 boost::replace_all( str, "\\\"", "\"" );
240
242 }
243 else if( node->is_type<SIM_MODEL_SERIALIZER_PARSER::flagParam>() )
244 {
245 std::string token = node->string();
246
248 }
249 else
250 {
251 wxFAIL;
252 }
253 }
254
255 return !m_model.HasPrimaryValue() || m_model.HasAutofill() || isPrimaryValueSet;
256}
257
258
259void SIM_MODEL_SERIALIZER::ParsePins( const std::string& aPins )
260{
261 if( aPins == "" )
262 return;
263
264 tao::pegtl::string_input<> in( aPins, "Sim.Pins field" );
265 std::unique_ptr<tao::pegtl::parse_tree::node> root;
266
267 try
268 {
269 root = tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::pinSequenceGrammar,
271 tao::pegtl::nothing,
273 ( in );
274
275 for( const auto& node : root->children )
276 {
277 std::string symbolPinNumber = node->children.at( 0 )->string();
278 std::string modelPinName = node->children.at( 1 )->string();
279
280 m_model.AssignSymbolPinNumberToModelPin( modelPinName, symbolPinNumber );
281 }
282 }
283 catch( const tao::pegtl::parse_error& e )
284 {
285 THROW_IO_ERROR( e.what() );
286 }
287}
288
289
290void SIM_MODEL_SERIALIZER::ParseEnable( const std::string& aEnable )
291{
292 if( aEnable == "" )
293 return;
294
295 char c = boost::to_lower_copy( aEnable )[0];
296
297 if( c == 'n' || c == 'f' || c == '0' )
298 m_model.SetIsEnabled( false );
299}
300
301
303{
304 std::string name = aParam.info.name;
305
306 // Because of collisions with instance parameters, we append some model parameters with "_".
307 if( boost::ends_with( name, "_" ) )
308 name = name.substr( 0, aParam.info.name.length() - 1 );
309
310 std::string value = aParam.value;
311
313 return value == "1" ? name : "";
314
315 if( value == "" || value.find( ' ' ) != std::string::npos )
316 value = fmt::format( "\"{}\"", value );
317
318 return fmt::format( "{}={}", name, value );
319}
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:509
bool IsEnabled() const
Definition: sim_model.h:502
virtual const PARAM & GetParam(unsigned aParamIndex) const
Definition: sim_model.cpp:789
int GetParamCount() const
Definition: sim_model.h:481
void AssignSymbolPinNumberToModelPin(int aPinIndex, const wxString &aSymbolPinNumber)
Definition: sim_model.cpp:758
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:824
virtual bool HasAutofill() const
Definition: sim_model.h:498
void SetIsEnabled(bool aIsEnabled)
Definition: sim_model.h:501
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
Definition: sim_model.cpp:845
void SetIsStoredInValue(bool aIsStoredInValue)
Definition: sim_model.h:504
virtual bool HasPrimaryValue() const
Definition: sim_model.h:499
std::vector< std::reference_wrapper< const SIM_MODEL_PIN > > GetPins() const
Definition: sim_model.cpp:748
@ 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