29#include <wx/xml/xml.h>
31#include <wx/tokenzr.h>
32#include <wx/xlocale.h>
48 if( child->GetName().IsSameAs( aTag,
false ) )
64 wxString
name = aNode->GetAttribute( wxT(
"Name" ) );
69 return aNode->GetNodeContent().Trim(
true ).Trim(
false );
74 const wxString& aDefault )
87 return childStr( aNode, aTag ).CmpNoCase( wxT(
"True" ) ) == 0;
99 wxString str = aValue;
100 str.Trim(
true ).Trim(
false );
106 wxString lower = str.Lower();
108 if( lower.EndsWith( wxT(
"mm" ) ) )
113 else if( lower.EndsWith( wxT(
"mil" ) ) )
122 str.ToCDouble( &val );
135 std::vector<wxString>
result;
136 wxStringTokenizer tokenizer( aContent, wxT(
" \t\r\n" ), wxTOKEN_STRTOK );
138 while( tokenizer.HasMoreTokens() )
140 wxString tok = tokenizer.GetNextToken();
143 && ( tok.CmpNoCase( wxT(
"mm" ) ) == 0 || tok.CmpNoCase( wxT(
"mil" ) ) == 0 ) )
160 if( tokens.size() < 2 )
187 return toMils( tokens[0] );
199 double val = aDefault;
207 std::vector<std::pair<double, double>> pts;
211 if( child->GetName() == wxT(
"pt" ) )
216 pts.emplace_back( x, y );
226 static const std::map<wxString, JUSTIFY> justifyMap = {
238 auto it = justifyMap.find( aValue );
253 XNODE* root =
static_cast<XNODE*
>( doc.GetRoot() );
266 const wxString& tag = node->GetName();
268 if( tag == wxT(
"library" ) )
270 else if( tag == wxT(
"netlist" ) )
272 else if( tag == wxT(
"schematicDesign" ) )
315 const wxString& tag = child->GetName();
317 if( tag == wxT(
"textStyleDef" ) )
321 else if( tag == wxT(
"symbolDef" ) )
325 aSchematic.
symbolDefs.push_back( std::move( sd ) );
327 else if( tag == wxT(
"compDef" ) )
331 aSchematic.
compDefs.push_back( std::move( cd ) );
333 else if( tag == wxT(
"compAlias" ) )
336 wxString both = child->GetAttribute( wxT(
"Name" ) );
337 wxString alias = both.BeforeFirst(
' ' );
338 wxString original = both.AfterFirst(
' ' );
339 original.Trim(
true ).Trim(
false );
341 if( !alias.IsEmpty() && !original.IsEmpty() )
351 style.
name = aNode->GetAttribute( wxT(
"Name" ) );
356 if( child->GetName() != wxT(
"font" ) )
365 wxString weight =
childStr( child, wxT(
"fontWeight" ) );
368 if( weight.ToLong( &weightVal ) )
369 font.
isBold = ( weightVal >= 700 );
382 aSchematic.
textStyles.push_back( std::move( style ) );
392 aSymDef.
name = aNode->GetAttribute( wxT(
"Name" ) );
397 const wxString& tag = child->GetName();
399 if( tag == wxT(
"pin" ) )
401 else if( tag == wxT(
"line" ) )
403 else if( tag == wxT(
"arc" ) )
405 else if( tag == wxT(
"triplePointArc" ) )
407 else if( tag == wxT(
"poly" ) )
409 else if( tag == wxT(
"text" ) )
411 else if( tag == wxT(
"ieeeSymbol" ) )
413 else if( tag == wxT(
"attr" ) )
425 aCompDef.
name = aNode->GetAttribute( wxT(
"Name" ) );
434 if(
childStr(
header, wxT(
"numParts" ) ).ToLong( &num ) && num > 0 )
435 aCompDef.
numParts =
static_cast<int>( num );
444 const wxString& tag = child->GetName();
446 if( tag == wxT(
"compPin" ) )
449 pin.padDes = child->GetAttribute( wxT(
"Name" ) );
451 pin.symPinNum =
childStr( child, wxT(
"symPinNum" ) );
456 if(
childStr( child, wxT(
"partNum" ) ).ToLong( &part ) && part > 0 )
457 pin.partNum =
static_cast<int>( part );
461 else if( tag == wxT(
"attachedSymbol" ) )
464 if(
childStr( child, wxT(
"altType" ) ) != wxT(
"Normal" ) )
468 childStr( child, wxT(
"partNum" ) ).ToLong( &part );
470 wxString symName =
childStr( child, wxT(
"symbolName" ) );
474 if( part >= 1 && part <= aCompDef.
numParts && !symName.IsEmpty() )
477 else if( tag == wxT(
"attachedPattern" ) )
481 else if( tag == wxT(
"attr" ) )
484 wxString
name = child->GetAttribute( wxT(
"Name" ) );
486 if(
name.StartsWith( wxT(
"Description " ) ) )
487 aCompDef.
description =
name.AfterFirst(
' ' ).Trim(
true ).Trim(
false );
504 pin.defaultPinDes =
childStr( aNode, wxT(
"defaultPinDes" ) );
508 pin.outsideEdgeStyle =
childStr( aNode, wxT(
"outsideEdgeStyle" ) );
509 pin.insideEdgeStyle =
childStr( aNode, wxT(
"insideEdgeStyle" ) );
513 wxString des =
childStr( disp, wxT(
"dispPinDes" ) );
516 pin.showPinDes = ( des.CmpNoCase( wxT(
"True" ) ) == 0 );
520 if( !
name.IsEmpty() )
521 pin.showPinName = (
name.CmpNoCase( wxT(
"True" ) ) == 0 );
551 wxString style =
childStr( aNode, wxT(
"style" ) );
553 if( style == wxT(
"DashedLine" ) )
555 else if( style == wxT(
"DottedLine" ) )
589 std::vector<std::pair<double, double>> pts =
collectPts( aNode );
596 arc.
x = pts[0].first;
597 arc.
y = pts[0].second;
599 double dx1 = pts[1].first - arc.
x;
600 double dy1 = pts[1].second - arc.
y;
601 double dx2 = pts[2].first - arc.
x;
602 double dy2 = pts[2].second - arc.
y;
604 arc.
radius = std::sqrt( dx1 * dx1 + dy1 * dy1 );
607 if( pts[1] == pts[2] )
613 double endAngle = atan2( dy2, dx2 ) * 180.0 /
M_PI;
644 item.
text = aNode->GetAttribute( wxT(
"Name" ) );
651 wxString visible =
childStr( aNode, wxT(
"isVisible" ) );
653 if( !visible.IsEmpty() )
654 item.
isVisible = ( visible.CmpNoCase( wxT(
"True" ) ) == 0 );
692 wxString nameAttr = aNode->GetAttribute( wxT(
"Name" ) );
696 attr.
name = nameAttr.BeforeFirst(
' ' );
699 attr.
placement.
text = nameAttr.AfterFirst(
' ' ).Trim(
true ).Trim(
false );
713 if( child->GetName() != wxT(
"compInst" ) )
717 ci.
refDes = child->GetAttribute( wxT(
"Name" ) );
722 aSchematic.
compInsts.push_back( std::move( ci ) );
752 if( child->GetName() == wxT(
"sheet" ) )
755 sheet.
name = child->GetAttribute( wxT(
"Name" ) );
757 long num =
static_cast<long>( aSchematic.
sheets.size() ) + 1;
758 childStr( child, wxT(
"sheetNum" ) ).ToLong( &num );
759 sheet.
sheetNum =
static_cast<int>( num );
762 aSchematic.
sheets.push_back( std::move( sheet ) );
775 wxT(
"Approved By" ),
777 wxT(
"Company Name" ),
778 wxT(
"Current Date" ),
779 wxT(
"Current Time" ),
780 wxT(
"Drawing Number" ),
782 wxT(
"Sheet Number" ),
783 wxT(
"Number Of Sheets" ),
784 wxT(
"Variant Description" ),
785 wxT(
"Variant Name" ),
789static bool splitFieldDef(
const wxString& aBoth, wxString& aName, wxString& aValue )
800 if( aBoth.StartsWith( wxString( known ) + wxT(
' ' ) ) )
803 aValue = aBoth.Mid( aName.length() + 1 );
808 aName = aBoth.BeforeFirst(
' ' );
809 aValue = aBoth.AfterFirst(
' ' );
810 return !aName.IsEmpty();
816 if( aNode->GetName() == wxT(
"fieldSet" ) )
820 if( field->GetName() != wxT(
"fieldDef" ) )
823 wxString both = field->GetAttribute( wxT(
"Name" ) );
824 wxString
name, value;
828 value.Trim(
true ).Trim(
false );
830 if( !value.IsEmpty() )
840 const wxString& tag = aNode->GetName();
842 if( tag != wxT(
"www.lura.sk" ) && tag != wxT(
"schematicDesign" )
843 && tag != wxT(
"schDesignHeader" ) && tag != wxT(
"designInfo" ) )
849 child =
static_cast<XNODE*
>( child->GetNext() ) )
895 bus.
name = aNode->GetAttribute( wxT(
"Name" ) );
919 const wxString& tag = child->GetName();
921 if( tag == wxT(
"wire" ) )
925 if( wire.
pts.size() >= 2 )
926 aSheet.
wires.push_back( std::move( wire ) );
928 else if( tag == wxT(
"bus" ) )
932 if( bus.
pts.size() >= 2 )
933 aSheet.
buses.push_back( std::move( bus ) );
935 else if( tag == wxT(
"busEntry" ) )
942 aSheet.
busEntries.push_back( std::move( entry ) );
944 else if( tag == wxT(
"port" ) )
956 aSheet.
ports.push_back( std::move( port ) );
958 else if( tag == wxT(
"junction" ) )
966 aSheet.
junctions.push_back( std::move( junc ) );
968 else if( tag == wxT(
"symbol" ) )
976 if(
childStr( child, wxT(
"partNum" ) ).ToLong( &part ) && part > 0 )
977 inst.
partNum =
static_cast<int>( part );
985 if( sub->GetName() == wxT(
"attr" ) )
989 aSheet.
symbols.push_back( std::move( inst ) );
991 else if( tag == wxT(
"text" ) )
995 else if( tag == wxT(
"line" ) )
999 if( line.
pts.size() >= 2 )
1000 aSheet.
lines.push_back( std::move( line ) );
1002 else if( tag == wxT(
"arc" ) )
1006 else if( tag == wxT(
"triplePointArc" ) )
1010 else if( tag == wxT(
"poly" ) )
1014 if( poly.
pts.size() >= 3 )
1015 aSheet.
polys.push_back( std::move( poly ) );
1017 else if( tag == wxT(
"ieeeSymbol" ) )
1021 else if( tag == wxT(
"field" ) )
1024 field.
name = child->GetAttribute( wxT(
"Name" ) );
1027 if( !field.
name.IsEmpty() )
1028 aSheet.
fields.push_back( std::move( field ) );
void LoadFromFile(const wxString &aFilename, SCHEMATIC &aSchematic)
void parseNetlist(XNODE *aNode, SCHEMATIC &aSchematic)
static bool childFlag(XNODE *aNode, const wxString &aTag)
void parseSymbolDef(XNODE *aNode, SYMBOL_DEF &aSymDef)
void parseSchematicDesign(XNODE *aNode, SCHEMATIC &aSchematic)
IEEE_SYMBOL parseIeeeSymbol(XNODE *aNode)
ARC parseArc(XNODE *aNode)
TEXT_ITEM parseText(XNODE *aNode)
void parseFieldSets(XNODE *aNode, SCHEMATIC &aSchematic)
std::vector< std::pair< double, double > > collectPts(XNODE *aNode) const
double childDouble(XNODE *aNode, const wxString &aTag, double aDefault=0.0) const
static wxString NodeText(XNODE *aNode)
void parseLibrary(XNODE *aNode, SCHEMATIC &aSchematic)
double toMils(const wxString &aValue) const
void parseCompDef(XNODE *aNode, COMP_DEF &aCompDef)
bool parsePtNode(XNODE *aPtNode, double &aX, double &aY) const
static XNODE * FindChild(XNODE *aNode, const wxString &aTag)
void parseTextStyleDef(XNODE *aNode, SCHEMATIC &aSchematic)
ATTR parseAttr(XNODE *aNode)
BUS parseBus(XNODE *aNode)
bool parsePt(XNODE *aNode, double &aX, double &aY) const
POLY parsePoly(XNODE *aNode)
WIRE parseWire(XNODE *aNode)
PIN parsePin(XNODE *aNode)
void parseSheet(XNODE *aNode, SHEET &aSheet)
void parseHeader(XNODE *aNode, SCHEMATIC &aSchematic)
static JUSTIFY parseJustify(const wxString &aValue)
LINE parseLine(XNODE *aNode)
static wxString childStr(XNODE *aNode, const wxString &aTag, const wxString &aDefault=wxEmptyString)
ARC parseTriplePointArc(XNODE *aNode)
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
XNODE * GetChildren() const
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
void LoadInputFile(const wxString &aFileName, wxXmlDocument *aXmlDoc)
static double childAngle(XNODE *aNode, const wxString &aTag, double aDefault=0.0)
static const wxChar *const TITLE_FIELD_NAMES[]
static std::vector< wxString > splitMeasureTokens(const wxString &aContent)
static bool splitFieldDef(const wxString &aBoth, wxString &aName, wxString &aValue)
Center/radius/angles form; triplePointArc is converted at parse time.
std::vector< std::pair< double, double > > pts
std::vector< wxString > attachedSymbols
std::vector< COMP_PIN > compPins
A (compPin "padDes" ...) inside a compDef, mapping a symbol pin ordinal to the physical pad designato...
A placed title-block field whose name references the fieldDef holding the displayed text.
One font description inside a (textStyleDef ...).
std::vector< std::pair< double, double > > pts
std::vector< std::pair< double, double > > pts
std::map< wxString, const COMP_DEF * > compDefsByName
std::map< wxString, const COMP_INST * > compInstsByRef
std::vector< SHEET > sheets
std::vector< SYMBOL_DEF > symbolDefs
std::vector< TEXT_STYLE > textStyles
std::vector< COMP_INST > compInsts
std::map< wxString, const TEXT_STYLE * > textStylesByName
std::map< wxString, wxString > compAliases
compAlias name -> compDef name
std::vector< COMP_DEF > compDefs
std::map< wxString, const SYMBOL_DEF * > symbolDefsByName
std::vector< PORT > ports
std::vector< BUS_ENTRY > busEntries
std::vector< WIRE > wires
std::vector< JUNCTION > junctions
std::vector< POLY > polys
std::vector< TEXT_ITEM > texts
std::vector< LINE > lines
std::vector< FIELD_PLACEMENT > fields
std::vector< IEEE_SYMBOL > ieeeSymbols
std::vector< SYMBOL_INST > symbols
std::vector< POLY > polys
std::vector< ATTR > attrs
std::vector< TEXT_ITEM > texts
std::vector< IEEE_SYMBOL > ieeeSymbols
std::vector< LINE > lines
std::vector< ATTR > attrs
std::map< wxString, wxString > fields
std::vector< std::pair< double, double > > pts
std::vector< std::string > header
wxString result
Test unit parsing edge cases and error handling.