28#include <wx/tokenzr.h>
29#include <wx/translation.h>
37static double toDouble(
const wxString& aToken )
40 aToken.ToCDouble( &value );
46static int toInt(
const wxString& aToken )
49 aToken.ToCLong( &value );
50 return static_cast<int>( value );
58 for( wxString line : wxStringTokenize( aContents, wxT(
"\n" ), wxTOKEN_RET_EMPTY ) )
60 line.Trim(
true ).Trim(
false );
62 if( line.IsEmpty() || line[0] ==
'#' )
65 return line.StartsWith( wxT(
"PCB FILE 4" ) ) || line.StartsWith( wxT(
"PCB FILE 5" ) );
75 m_reporter->Report( wxString::Format(
_(
"Autotrax import, line %d: %s" ),
m_lineNo, aMsg ),
89 aLine.Trim(
true ).Trim(
false );
97 return wxStringTokenize( aLine, wxT(
" \t\r\n" ), wxTOKEN_STRTOK );
108 wxArrayString tok =
tokenize( line );
110 if( tok.GetCount() < 6 )
112 warn(
_(
"insufficient track fields" ) );
133 wxArrayString tok =
tokenize( line );
135 if( tok.GetCount() < 6 )
137 warn(
_(
"insufficient arc fields" ) );
158 wxArrayString tok =
tokenize( line );
160 if( tok.GetCount() < 4 )
162 warn(
_(
"insufficient via fields" ) );
181 wxArrayString tok =
tokenize( line );
185 if( tok.GetCount() < 8 )
187 warn(
_(
"insufficient pad fields" ) );
215 wxArrayString tok =
tokenize( line );
217 if( tok.GetCount() < 5 )
219 warn(
_(
"insufficient fill fields" ) );
252 wxArrayString tok =
tokenize( aLine );
254 if( tok.GetCount() < 6 )
256 warn(
_(
"insufficient text fields" ) );
265 int rotation =
toInt( tok[3] );
267 aOut.
mirrored = ( rotation & 16 ) != 0;
301 wxArrayString tok =
tokenize( line );
303 if( tok.GetCount() >= 2 )
308 if( tok.GetCount() >= 4 )
316 warn(
_(
"insufficient component fields" ) );
324 if( kw.StartsWith( wxT(
"ENDCOMP" ) ) )
327 if( kw == wxT(
"CT" ) )
332 aOut.
tracks.push_back( t );
334 else if( kw == wxT(
"CA" ) )
339 aOut.
arcs.push_back( a );
341 else if( kw == wxT(
"CV" ) )
346 aOut.
vias.push_back( v );
348 else if( kw == wxT(
"CF" ) )
353 aOut.
fills.push_back( f );
355 else if( kw == wxT(
"CP" ) )
360 aOut.
pads.push_back( p );
362 else if( kw == wxT(
"CS" ) )
367 aOut.
texts.push_back( s );
384 wxString netName = line;
387 bool inNodeTable =
false;
393 if( s.StartsWith( wxT(
"ENDPCB" ) ) )
407 if( line == wxT(
"]" ) )
411 else if( s[0] ==
'(' )
415 else if( s[0] ==
')' )
419 else if( s[0] ==
'{' )
423 else if( s[0] ==
'}' )
427 else if( inNet && !inNodeTable && !netName.IsEmpty() )
429 m_board->netNodes.push_back( { netName, s } );
441 m_lines = wxStringTokenize( aContents, wxT(
"\n" ), wxTOKEN_RET_EMPTY );
445 bool haveHeader =
false;
455 if( kw.StartsWith( wxT(
"PCB FILE 4" ) ) )
460 else if( kw.StartsWith( wxT(
"PCB FILE 5" ) ) )
465 else if( kw.StartsWith( wxT(
"ENDPCB" ) ) )
469 else if( kw.StartsWith( wxT(
"NETDEF" ) ) )
473 else if( kw.StartsWith( wxT(
"COMP" ) ) )
479 else if( kw == wxT(
"FT" ) )
484 aBoard.
tracks.push_back( t );
486 else if( kw == wxT(
"FA" ) )
491 aBoard.
arcs.push_back( a );
493 else if( kw == wxT(
"FV" ) )
498 aBoard.
vias.push_back( v );
500 else if( kw == wxT(
"FF" ) )
505 aBoard.
fills.push_back( f );
507 else if( kw == wxT(
"FP" ) )
512 aBoard.
pads.push_back( p );
514 else if( kw == wxT(
"FS" ) )
519 aBoard.
texts.push_back( s );
static int toInt(const wxString &aToken)
Parse a token as an integer using the C locale, returning 0 on failure.
static double toDouble(const wxString &aToken)
Parse a token as a double using the C locale, returning 0 on failure so a malformed field degrades to...
bool parseVia(AUTOTRAX::VIA &aOut)
AUTOTRAX::BOARD_DATA * m_board
static bool Sniff(const wxString &aContents)
Cheap content sniff: the first non-blank, non-comment line is the magic header "PCB FILE 4" (Autotrax...
bool Parse(const wxString &aContents, AUTOTRAX::BOARD_DATA &aBoard)
Parse aContents into aBoard.
void parseComponent(AUTOTRAX::COMPONENT &aOut)
bool parseArc(AUTOTRAX::ARC &aOut)
bool parseTrack(AUTOTRAX::TRACK &aOut)
void warn(const wxString &aMsg) const
bool parseText(AUTOTRAX::TEXT &aOut)
bool parseTextData(const wxString &aLine, AUTOTRAX::TEXT &aOut) const
Parse the numeric line of a string record, which COMP headers reuse for label placement.
bool parseFill(AUTOTRAX::FILL &aOut)
bool nextLine(wxString &aLine)
Return the next line trimmed of surrounding whitespace, or false at end of input.
static wxArrayString tokenize(const wxString &aLine)
Tokenize a whitespace-separated data line into C-locale-parseable tokens.
bool parsePad(AUTOTRAX::PAD &aOut)
Free or component arc (FA / CA).
int segments
quadrant bitmask; 15 = full circle
Everything parsed out of an Autotrax/Easytrax file, before any KiCad object is created.
std::vector< COMPONENT > components
std::vector< TRACK > tracks
int version
4 = Autotrax, 5 = Easytrax
std::vector< TEXT > texts
std::vector< FILL > fills
A placed component (COMP .. ENDCOMP) holding its own primitives.
std::optional< TEXT > valueText
comment placement, text unused
std::vector< TRACK > tracks
std::optional< TEXT > refdesText
designator placement, text unused
std::vector< FILL > fills
std::vector< TEXT > texts
Free or component rectangular fill (FF / CF), Autotrax's only pour.
Free or component pad/pin (FP / CP).
int shape
1 round, 2 rect, 3 octagon, 4 round-rect
Free or component string (FS / CS).
int direction
0..3, multiplied by 90 degrees counterclockwise
Free or component track segment (FT / CT). All coordinates are in mils.
Free or component via (FV / CV).