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 bool isFirst = true;
138
139 for( const SIM_MODEL::PIN& pin : pins )
140 {
141 if( pin.symbolPinNumber != "" )
142 {
143 if( !isFirst )
144 result.append( " " );
145 else
146 isFirst = false;
147
148 result.append( fmt::format( "{}={}", pin.symbolPinNumber, pin.name ) );
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 pinName = node->children.at( 1 )->string();
279
280 m_model.SetPinSymbolPinNumber( pinName, 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:467
bool IsStoredInValue() const
Definition: sim_model.h:512
bool IsEnabled() const
Definition: sim_model.h:505
std::vector< std::reference_wrapper< const PIN > > GetPins() const
Definition: sim_model.cpp:739
virtual const PARAM & GetParam(unsigned aParamIndex) const
Definition: sim_model.cpp:779
int GetParamCount() const
Definition: sim_model.h:482
void SetPinSymbolPinNumber(int aPinIndex, const std::string &aSymbolPinNumber)
Definition: sim_model.cpp:749
DEVICE_INFO GetDeviceInfo() const
Definition: sim_model.h:461
INFO GetTypeInfo() const
Definition: sim_model.h:462
const PARAM & GetParamOverride(unsigned aParamIndex) const
Definition: sim_model.cpp:827
virtual bool HasAutofill() const
Definition: sim_model.h:501
void SetIsEnabled(bool aIsEnabled)
Definition: sim_model.h:504
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
Definition: sim_model.cpp:848
void SetIsStoredInValue(bool aIsStoredInValue)
Definition: sim_model.h:507
virtual bool HasPrimaryValue() const
Definition: sim_model.h:502
@ 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:396
std::string value
Definition: sim_model.h:401
const INFO & info
Definition: sim_model.h:402