KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sexpr.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 Mark Roszko <[email protected]>
3 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "sexpr/sexpr.h"
20#include <cctype>
21#include <iterator>
22#include <stdexcept>
23#include <iomanip>
24#include <sstream>
25#include <wx/debug.h>
26#include <fmt/core.h>
27
28namespace SEXPR
29{
30 SEXPR::SEXPR( SEXPR_TYPE aType, size_t aLineNumber ) :
31 m_type( aType ), m_lineNumber( aLineNumber )
32 {
33 }
34
36 m_type( aType ), m_lineNumber( 1 )
37 {
38 }
39
41 {
43 {
44 throw INVALID_TYPE_EXCEPTION("SEXPR is not a list type!");
45 }
46
47 return &static_cast< SEXPR_LIST const * >(this)->m_children;
48 }
49
50 SEXPR* SEXPR::GetChild( size_t aIndex ) const
51 {
53 {
54 throw INVALID_TYPE_EXCEPTION("SEXPR is not a list type!");
55 }
56
57 return static_cast< SEXPR_LIST const * >(this)->m_children[aIndex];
58 }
59
60 void SEXPR::AddChild( SEXPR* aChild )
61 {
63 {
64 throw INVALID_TYPE_EXCEPTION("SEXPR is not a list type!");
65 }
66
67 SEXPR_LIST* list = static_cast< SEXPR_LIST * >( this );
68
69 list->m_children.push_back( aChild );
70 }
71
73 {
75 {
76 throw INVALID_TYPE_EXCEPTION("SEXPR is not a list type!");
77 }
78
79 return static_cast< SEXPR_LIST const * >(this)->m_children.size();
80 }
81
82 std::string const & SEXPR::GetString() const
83 {
85 {
86 throw INVALID_TYPE_EXCEPTION("SEXPR is not a string type!");
87 }
88
89 return static_cast< SEXPR_STRING const * >(this)->m_value;
90 }
91
92 int32_t SEXPR::GetInteger() const
93 {
94 return static_cast< int >( GetLongInteger() );
95 }
96
97 int64_t SEXPR::GetLongInteger() const
98 {
100 {
101 throw INVALID_TYPE_EXCEPTION("SEXPR is not a integer type!");
102 }
103
104 return static_cast< SEXPR_INTEGER const * >(this)->m_value;
105 }
106
107 double SEXPR::GetDouble() const
108 {
109 // we may end up parsing "intended" floats/doubles as ints
110 // so here we allow silent casting back to doubles
112 {
113 return static_cast< SEXPR_DOUBLE const * >(this)->m_value;
114 }
116 {
117 return static_cast< SEXPR_INTEGER const * >(this)->m_value;
118 }
119 else
120 {
121 throw INVALID_TYPE_EXCEPTION("SEXPR is not a double type!");
122 }
123 }
124
125 float SEXPR::GetFloat() const
126 {
127 return static_cast< float >( GetDouble() );
128 }
129
130 std::string const & SEXPR::GetSymbol() const
131 {
133 {
134 std::string err_msg( "GetSymbol(): SEXPR is not a symbol type! error line ");
135 err_msg += std::to_string( GetLineNumber() );
136 throw INVALID_TYPE_EXCEPTION( err_msg );
137 }
138
139 return static_cast< SEXPR_SYMBOL const * >(this)->m_value;
140 }
141
142
144 {
146 {
147 throw INVALID_TYPE_EXCEPTION("SEXPR is not a list type!");
148 }
149
150 return static_cast< SEXPR_LIST* >(this);
151 }
152
153 std::string SEXPR::AsString( size_t aLevel ) const
154 {
155 std::string result;
156
157 if( IsList() )
158 {
159 if( aLevel != 0 )
160 {
161 result = "\n";
162 }
163
164 result.append( aLevel * 2, ' ' );
165 aLevel++;
166 result += "(";
167
168 SEXPR_VECTOR const* list = GetChildren();
169
170 for( std::vector<SEXPR *>::const_iterator it = list->begin(); it != list->end(); ++it )
171 {
172 result += (*it)->AsString( aLevel );
173
174 if( it != list->end() - 1 )
175 {
176 result += " ";
177 }
178 }
179 result += ")";
180
181 aLevel--;
182 }
183 else if( IsString() )
184 {
185 result += "\"" + GetString() + "\"";
186 }
187 else if( IsSymbol() )
188 {
189 result += GetSymbol();
190 }
191 else if( IsInteger() )
192 {
193 std::stringstream out;
194 out << GetInteger();
195 result += out.str();
196 }
197 else if( IsDouble() )
198 {
199 std::string out;
200
201 // This code does the same thing as FormatDouble2Str() in string_utils.cpp
202 // Unfortunately on msys2 currently trying to use FormatDouble2Str creates a link
203 // issue. So duplicate a similar code here for now.
204 out = fmt::format( "{:.10g}", GetDouble() );
205
206 // Scientific notation not allowed. So detect and change it
207 if( out.find("e") != std::string::npos )
208 {
209 out = fmt::format( "{:.10f}", GetDouble() );
210
211 // remove trailing zeros
212 while( !out.empty() && out[out.size() - 1] == '0' )
213 out.pop_back();
214
215 // we may have just stripped all the zeros after the decimal
216 if( out.size() > 1 && out[out.size() - 1] == '.' )
217 out.pop_back();
218 }
219
220 result += out;
221 }
222
223 return result;
224 }
225
227 {
228 for( auto child : m_children )
229 {
230 delete child;
231 }
232
233 m_children.clear();
234 }
235
237 {
238 SEXPR* sobj = obj.SerializeSEXPR();
239 list.AddChild( sobj );
240
241 return list;
242 }
243
244 SEXPR_LIST& operator<< ( SEXPR_LIST& list, int64_t value )
245 {
246 list.AddChild( new SEXPR_INTEGER( value ) );
247 return list;
248 }
249
250 SEXPR_LIST& operator<< ( SEXPR_LIST& list, int32_t value )
251 {
252 list.AddChild( new SEXPR_INTEGER( value ) );
253 return list;
254 }
255
256 SEXPR_LIST& operator<< ( SEXPR_LIST& list, float value )
257 {
258 list.AddChild( new SEXPR_DOUBLE( value ) );
259 return list;
260 }
261
262 SEXPR_LIST& operator<< ( SEXPR_LIST& list, double value )
263 {
264 list.AddChild( new SEXPR_DOUBLE( value ) );
265 return list;
266 }
267
268 SEXPR_LIST& operator<< ( SEXPR_LIST& list, std::string value )
269 {
270 list.AddChild( new SEXPR_STRING( value ) );
271 return list;
272 }
273
275 {
276 list.AddChild( obj );
277 return list;
278 }
279
281 {
282 SEXPR *res;
283
284 if( setting._Symbol )
285 {
286 res = new SEXPR_SYMBOL( setting._String );
287 }
288 else
289 {
290 res = new SEXPR_STRING( setting._String );
291 }
292
293 list.AddChild( res );
294
295 return list;
296 }
297
299 {
300 obj.DeserializeSEXPR( input );
301
302 return input;
303 }
304
305 SEXPR_LIST& operator>> ( SEXPR_LIST& input, int32_t& inte )
306 {
307 SEXPR* child = input.GetChild( input.m_inStreamChild );
308
309 if( child->IsInteger() )
310 {
311 inte = child->GetInteger();
312 input.m_inStreamChild++;
313 }
314 else
315 {
316 throw std::invalid_argument( "SEXPR is not a integer type!" );
317 }
318
319 return input;
320 }
321
322 SEXPR_LIST& operator>> ( SEXPR_LIST& input, std::string& str )
323 {
324 SEXPR* child = input.GetChild( input.m_inStreamChild );
325
326 if( child->IsString() || child->IsSymbol() )
327 {
328 str = child->GetString();
329 input.m_inStreamChild++;
330 }
331 else
332 {
333 throw std::invalid_argument( "SEXPR is not a string type!" );
334 }
335
336 return input;
337 }
338
339 SEXPR_LIST& operator>> ( SEXPR_LIST& input, int64_t& lint )
340 {
341 SEXPR* child = input.GetChild( input.m_inStreamChild );
342
343 if( child->IsInteger() )
344 {
345 lint = child->GetLongInteger();
346 input.m_inStreamChild++;
347 }
348 else
349 {
350 throw std::invalid_argument("SEXPR is not a long integer type!");
351 }
352
353 return input;
354 }
355
356 SEXPR_LIST& operator>> ( SEXPR_LIST& input, float& fl )
357 {
358 SEXPR* child = input.GetChild( input.m_inStreamChild );
359 if( child->IsDouble() )
360 {
361 fl = child->GetFloat();
362 input.m_inStreamChild++;
363 }
364 else
365 {
366 throw std::invalid_argument( "SEXPR is not a float type!" );
367 }
368
369 return input;
370 }
371
372 SEXPR_LIST& operator>> ( SEXPR_LIST& input, double& dbl )
373 {
374 SEXPR* child = input.GetChild( input.m_inStreamChild );
375
376 if( child->IsDouble() )
377 {
378 dbl = child->GetDouble();
379 input.m_inStreamChild++;
380 }
381 else
382 {
383 throw std::invalid_argument( "SEXPR is not a double type!" );
384 }
385
386 return input;
387 }
388
390 {
391 SEXPR* child = input.GetChild( input.m_inStreamChild );
392
393 if( is._Symbol )
394 {
395 if( child->IsSymbol() )
396 {
397 is._String = child->GetSymbol();
398 input.m_inStreamChild++;
399 }
400 else
401 {
402 throw std::invalid_argument( "operator>>: SEXPR is not a symbol type!" );
403 }
404 }
405 else
406 {
407 if( child->IsString() )
408 {
409 is._String = child->GetString();
410 input.m_inStreamChild++;
411 }
412 else
413 {
414 throw std::invalid_argument( "SEXPR is not a string type!" );
415 }
416 }
417
418 return input;
419 }
420
422 {
423 list.AddChild( list2 );
424
425 return list;
426 }
427
428 size_t SEXPR_LIST::doScan( const SEXPR_SCAN_ARG *args, size_t num_args )
429 {
430 size_t i = 0;
431
432 for( i = 0; i < num_args; i++ )
433 {
434 SEXPR* child = GetChild( i );
435 const SEXPR_SCAN_ARG& arg = args[i];
436
437 try
438 {
440 {
441 *arg.u.dbl_value = child->GetDouble();
442 }
443 else if( arg.type == SEXPR_SCAN_ARG::Type::INT )
444 {
445 *arg.u.dbl_value = child->GetInteger();
446 }
447 else if( arg.type == SEXPR_SCAN_ARG::Type::STRING )
448 {
449 if( child->IsSymbol() )
450 {
451 *arg.u.str_value = child->GetSymbol();
452 }
453 else if( child->IsString() )
454 {
455 *arg.u.str_value = child->GetString();
456 }
457 }
458 else if( arg.type == SEXPR_SCAN_ARG::Type::LONGINT )
459 {
460 *arg.u.lint_value = child->GetLongInteger();
461 }
463 {
464 if( arg.u.sexpr_str->_Symbol )
465 {
466 arg.u.sexpr_str->_String = child->GetSymbol();
467 }
468 else
469 {
470 arg.u.sexpr_str->_String = child->GetString();
471 }
472
473 }
475 {
476 if( child->IsSymbol() )
477 {
478 if( child->GetSymbol() != arg.str_value )
479 {
480 return i;
481 }
482 }
483 else if( child->IsString() )
484 {
485 if( child->GetString() != arg.str_value )
486 {
487 return i;
488 }
489 }
490 }
491 else
492 {
493 throw std::invalid_argument( "unsupported argument type, this shouldn't have happened" );
494 }
495 }
496 catch( const INVALID_TYPE_EXCEPTION& )
497 {
498 return i;
499 }
500 }
501
502 return i;
503 }
504
505 void SEXPR_LIST::doAddChildren( const SEXPR_CHILDREN_ARG *args, size_t num_args )
506 {
507 size_t i = 0;
508
509 for( i = 0; i < num_args; i++ )
510 {
511 const SEXPR_CHILDREN_ARG& arg = args[i];
512
514 {
515 AddChild( new SEXPR_DOUBLE( arg.u.dbl_value ) );
516 }
517 else if( arg.type == SEXPR_CHILDREN_ARG::Type::INT )
518 {
519 AddChild( new SEXPR_INTEGER( arg.u.int_value ) );
520 }
522 {
523 AddChild( new SEXPR_INTEGER( arg.u.lint_value ) );
524 }
525 else if( arg.type == SEXPR_CHILDREN_ARG::Type::STRING )
526 {
527 AddChild( new SEXPR_STRING( arg.str_value ) );
528 }
530 {
531 AddChild( arg.u.sexpr_ptr );
532 }
534 {
535 if( arg.u.symbol )
536 {
537 AddChild( new SEXPR_SYMBOL( arg.str_value ) );
538 }
539 else
540 {
541 AddChild( new SEXPR_STRING( arg.str_value ) );
542 }
543 }
544 else
545 {
546 throw std::invalid_argument( "unexpected argument type, this shouldn't have happened" );
547 }
548 }
549 }
550}
virtual void DeserializeSEXPR(SEXPR &sexp)
Definition isexprable.h:33
virtual SEXPR * SerializeSEXPR() const
Definition isexprable.h:32
union SEXPR::SEXPR_CHILDREN_ARG::@140153117255347061025000322060345331135151360226 u
std::string str_value
Definition sexpr.h:239
int m_inStreamChild
Definition sexpr.h:293
void doAddChildren(const SEXPR_CHILDREN_ARG *args, size_t num_args)
Definition sexpr.cpp:505
virtual ~SEXPR_LIST()
Definition sexpr.cpp:226
size_t doScan(const SEXPR_SCAN_ARG *args, size_t num_args)
Definition sexpr.cpp:428
SEXPR_VECTOR m_children
Definition sexpr.h:257
double * dbl_value
Definition sexpr.h:192
union SEXPR::SEXPR_SCAN_ARG::@066014047110022234005207275010144102035233327174 u
_IN_STRING * sexpr_str
Definition sexpr.h:194
std::string * str_value
Definition sexpr.h:193
int64_t * lint_value
Definition sexpr.h:190
SEXPR_VECTOR const * GetChildren() const
Definition sexpr.cpp:40
void AddChild(SEXPR *aChild)
Definition sexpr.cpp:60
bool IsInteger() const
Definition sexpr.h:53
std::string const & GetSymbol() const
Definition sexpr.cpp:130
std::string AsString(size_t aLevel=0) const
Definition sexpr.cpp:153
bool IsString() const
Definition sexpr.h:51
int32_t GetInteger() const
Definition sexpr.cpp:92
SEXPR_TYPE m_type
Definition sexpr.h:69
size_t GetNumberOfChildren() const
Definition sexpr.cpp:72
float GetFloat() const
Definition sexpr.cpp:125
bool IsList() const
Definition sexpr.h:49
size_t m_lineNumber
Definition sexpr.h:72
int64_t GetLongInteger() const
Definition sexpr.cpp:97
bool IsDouble() const
Definition sexpr.h:52
bool IsSymbol() const
Definition sexpr.h:50
std::string const & GetString() const
Definition sexpr.cpp:82
SEXPR(SEXPR_TYPE aType, size_t aLineNumber)
Definition sexpr.cpp:30
SEXPR * GetChild(size_t aIndex) const
Definition sexpr.cpp:50
double GetDouble() const
Definition sexpr.cpp:107
size_t GetLineNumber() const
Definition sexpr.h:66
SEXPR_LIST * GetList()
Definition sexpr.cpp:143
SEXPR_LIST & operator>>(SEXPR_LIST &input, ISEXPRABLE &obj)
Definition sexpr.cpp:298
SEXPR_LIST & operator<<(SEXPR_LIST &list, const ISEXPRABLE &obj)
Definition sexpr.cpp:236
std::vector< class SEXPR * > SEXPR_VECTOR
Definition sexpr.h:43
SEXPR_TYPE
Definition sexpr.h:35
@ SEXPR_TYPE_ATOM_SYMBOL
Definition sexpr.h:40
@ SEXPR_TYPE_ATOM_INTEGER
Definition sexpr.h:37
@ SEXPR_TYPE_ATOM_DOUBLE
Definition sexpr.h:38
@ SEXPR_TYPE_ATOM_STRING
Definition sexpr.h:39
std::string & _String
Definition sexpr.h:140
const std::string & _String
Definition sexpr.h:122
VECTOR3I res
wxString result
Test unit parsing edge cases and error handling.