29#include <wx/xml/xml.h>
31#include <wx/tokenzr.h>
32#include <wx/xlocale.h>
33#include <wx/translation.h>
49 if( child->GetName().IsSameAs( aTag,
false ) )
65 wxString
name = aNode->GetAttribute( wxT(
"Name" ) );
70 return aNode->GetNodeContent().Trim(
true ).Trim(
false );
75 const wxString& aDefault )
88 return childStr( aNode, aTag ).CmpNoCase( wxT(
"True" ) ) == 0;
100 wxString str = aValue;
101 str.Trim(
true ).Trim(
false );
107 wxString lower = str.Lower();
109 if( lower.EndsWith( wxT(
"mm" ) ) )
114 else if( lower.EndsWith( wxT(
"mil" ) ) )
123 str.ToCDouble( &val );
136 std::vector<wxString>
result;
137 wxStringTokenizer tokenizer( aContent, wxT(
" \t\r\n" ), wxTOKEN_STRTOK );
139 while( tokenizer.HasMoreTokens() )
141 wxString tok = tokenizer.GetNextToken();
144 && ( tok.CmpNoCase( wxT(
"mm" ) ) == 0 || tok.CmpNoCase( wxT(
"mil" ) ) == 0 ) )
161 if( tokens.size() < 2 )
188 return toMils( tokens[0] );
200 double val = aDefault;
208 std::vector<std::pair<double, double>> pts;
212 if( child->GetName() == wxT(
"pt" ) )
217 pts.emplace_back( x, y );
227 static const std::map<wxString, JUSTIFY> justifyMap = {
239 auto it = justifyMap.find( aValue );
254 XNODE* root =
static_cast<XNODE*
>( doc.GetRoot() );
267 const wxString& tag = node->GetName();
269 if( tag == wxT(
"library" ) )
271 else if( tag == wxT(
"netlist" ) )
273 else if( tag == wxT(
"schematicDesign" ) )
316 const wxString& tag = child->GetName();
318 if( tag == wxT(
"textStyleDef" ) )
322 else if( tag == wxT(
"symbolDef" ) )
326 aSchematic.
symbolDefs.push_back( std::move( sd ) );
328 else if( tag == wxT(
"compDef" ) )
332 aSchematic.
compDefs.push_back( std::move( cd ) );
334 else if( tag == wxT(
"compAlias" ) )
337 wxString both = child->GetAttribute( wxT(
"Name" ) );
338 wxString alias = both.BeforeFirst(
' ' );
339 wxString original = both.AfterFirst(
' ' );
340 original.Trim(
true ).Trim(
false );
342 if( !alias.IsEmpty() && !original.IsEmpty() )
352 style.
name = aNode->GetAttribute( wxT(
"Name" ) );
357 if( child->GetName() != wxT(
"font" ) )
366 wxString weight =
childStr( child, wxT(
"fontWeight" ) );
369 if( weight.ToLong( &weightVal ) )
370 font.
isBold = ( weightVal >= 700 );
383 aSchematic.
textStyles.push_back( std::move( style ) );
393 aSymDef.
name = aNode->GetAttribute( wxT(
"Name" ) );
398 const wxString& tag = child->GetName();
400 if( tag == wxT(
"pin" ) )
402 else if( tag == wxT(
"line" ) )
404 else if( tag == wxT(
"arc" ) )
406 else if( tag == wxT(
"triplePointArc" ) )
408 else if( tag == wxT(
"poly" ) )
410 else if( tag == wxT(
"text" ) )
412 else if( tag == wxT(
"ieeeSymbol" ) )
414 else if( tag == wxT(
"attr" ) )
426 aCompDef.
name = aNode->GetAttribute( wxT(
"Name" ) );
435 if(
childStr( header, wxT(
"numParts" ) ).ToLong( &num ) && num > 0 )
436 aCompDef.
numParts =
static_cast<int>( num );
438 aCompDef.
isPower = (
childStr( header, wxT(
"compType" ) ) == wxT(
"Power" ) );
445 const wxString& tag = child->GetName();
447 if( tag == wxT(
"compPin" ) )
450 pin.padDes = child->GetAttribute( wxT(
"Name" ) );
452 pin.symPinNum =
childStr( child, wxT(
"symPinNum" ) );
457 if(
childStr( child, wxT(
"partNum" ) ).ToLong( &part ) && part > 0 )
458 pin.partNum =
static_cast<int>( part );
462 else if( tag == wxT(
"attachedSymbol" ) )
465 if(
childStr( child, wxT(
"altType" ) ) != wxT(
"Normal" ) )
469 childStr( child, wxT(
"partNum" ) ).ToLong( &part );
471 wxString symName =
childStr( child, wxT(
"symbolName" ) );
475 if( part >= 1 && part <= aCompDef.
numParts && !symName.IsEmpty() )
478 else if( tag == wxT(
"attachedPattern" ) )
482 else if( tag == wxT(
"attr" ) )
485 wxString
name = child->GetAttribute( wxT(
"Name" ) );
487 if(
name.StartsWith( wxT(
"Description " ) ) )
488 aCompDef.
description =
name.AfterFirst(
' ' ).Trim(
true ).Trim(
false );
505 pin.defaultPinDes =
childStr( aNode, wxT(
"defaultPinDes" ) );
509 pin.outsideEdgeStyle =
childStr( aNode, wxT(
"outsideEdgeStyle" ) );
510 pin.insideEdgeStyle =
childStr( aNode, wxT(
"insideEdgeStyle" ) );
514 wxString des =
childStr( disp, wxT(
"dispPinDes" ) );
517 pin.showPinDes = ( des.CmpNoCase( wxT(
"True" ) ) == 0 );
521 if( !
name.IsEmpty() )
522 pin.showPinName = (
name.CmpNoCase( wxT(
"True" ) ) == 0 );
552 wxString style =
childStr( aNode, wxT(
"style" ) );
554 if( style == wxT(
"DashedLine" ) )
556 else if( style == wxT(
"DottedLine" ) )
590 std::vector<std::pair<double, double>> pts =
collectPts( aNode );
597 arc.
x = pts[0].first;
598 arc.
y = pts[0].second;
600 double dx1 = pts[1].first - arc.
x;
601 double dy1 = pts[1].second - arc.
y;
602 double dx2 = pts[2].first - arc.
x;
603 double dy2 = pts[2].second - arc.
y;
605 arc.
radius = std::sqrt( dx1 * dx1 + dy1 * dy1 );
608 if( pts[1] == pts[2] )
614 double endAngle = atan2( dy2, dx2 ) * 180.0 /
M_PI;
645 item.
text = aNode->GetAttribute( wxT(
"Name" ) );
652 wxString visible =
childStr( aNode, wxT(
"isVisible" ) );
654 if( !visible.IsEmpty() )
655 item.
isVisible = ( visible.CmpNoCase( wxT(
"True" ) ) == 0 );
693 wxString nameAttr = aNode->GetAttribute( wxT(
"Name" ) );
697 attr.
name = nameAttr.BeforeFirst(
' ' );
700 attr.
placement.
text = nameAttr.AfterFirst(
' ' ).Trim(
true ).Trim(
false );
714 if( child->GetName() != wxT(
"compInst" ) )
718 ci.
refDes = child->GetAttribute( wxT(
"Name" ) );
723 aSchematic.
compInsts.push_back( std::move( ci ) );
734 if(
XNODE* header =
FindChild( aNode, wxT(
"schDesignHeader" ) ) )
753 if( child->GetName() == wxT(
"sheet" ) )
756 sheet.
name = child->GetAttribute( wxT(
"Name" ) );
758 long num =
static_cast<long>( aSchematic.
sheets.size() ) + 1;
759 childStr( child, wxT(
"sheetNum" ) ).ToLong( &num );
760 sheet.
sheetNum =
static_cast<int>( num );
763 aSchematic.
sheets.push_back( std::move( sheet ) );
776 wxT(
"Approved By" ),
778 wxT(
"Company Name" ),
779 wxT(
"Current Date" ),
780 wxT(
"Current Time" ),
781 wxT(
"Drawing Number" ),
783 wxT(
"Sheet Number" ),
784 wxT(
"Number Of Sheets" ),
785 wxT(
"Variant Description" ),
786 wxT(
"Variant Name" ),
790static bool splitFieldDef(
const wxString& aBoth, wxString& aName, wxString& aValue )
801 if( aBoth.StartsWith( wxString( known ) + wxT(
' ' ) ) )
804 aValue = aBoth.Mid( aName.length() + 1 );
809 aName = aBoth.BeforeFirst(
' ' );
810 aValue = aBoth.AfterFirst(
' ' );
811 return !aName.IsEmpty();
817 if( aNode->GetName() == wxT(
"fieldSet" ) )
821 if( field->GetName() != wxT(
"fieldDef" ) )
824 wxString both = field->GetAttribute( wxT(
"Name" ) );
825 wxString
name, value;
829 value.Trim(
true ).Trim(
false );
831 if( !value.IsEmpty() )
841 const wxString& tag = aNode->GetName();
843 if( tag != wxT(
"www.lura.sk" ) && tag != wxT(
"schematicDesign" )
844 && tag != wxT(
"schDesignHeader" ) && tag != wxT(
"designInfo" ) )
850 child =
static_cast<XNODE*
>( child->GetNext() ) )
896 bus.
name = aNode->GetAttribute( wxT(
"Name" ) );
920 const wxString& tag = child->GetName();
922 if( tag == wxT(
"wire" ) )
926 if( wire.
pts.size() >= 2 )
927 aSheet.
wires.push_back( std::move( wire ) );
929 else if( tag == wxT(
"bus" ) )
933 if( bus.
pts.size() >= 2 )
934 aSheet.
buses.push_back( std::move( bus ) );
936 else if( tag == wxT(
"busEntry" ) )
943 aSheet.
busEntries.push_back( std::move( entry ) );
945 else if( tag == wxT(
"port" ) )
957 aSheet.
ports.push_back( std::move( port ) );
959 else if( tag == wxT(
"junction" ) )
967 aSheet.
junctions.push_back( std::move( junc ) );
969 else if( tag == wxT(
"symbol" ) )
977 if(
childStr( child, wxT(
"partNum" ) ).ToLong( &part ) && part > 0 )
978 inst.
partNum =
static_cast<int>( part );
986 if( sub->GetName() == wxT(
"attr" ) )
990 aSheet.
symbols.push_back( std::move( inst ) );
992 else if( tag == wxT(
"text" ) )
996 else if( tag == wxT(
"line" ) )
1000 if( line.
pts.size() >= 2 )
1001 aSheet.
lines.push_back( std::move( line ) );
1003 else if( tag == wxT(
"arc" ) )
1007 else if( tag == wxT(
"triplePointArc" ) )
1011 else if( tag == wxT(
"poly" ) )
1015 if( poly.
pts.size() >= 3 )
1016 aSheet.
polys.push_back( std::move( poly ) );
1018 else if( tag == wxT(
"ieeeSymbol" ) )
1022 else if( tag == wxT(
"field" ) )
1025 field.
name = child->GetAttribute( wxT(
"Name" ) );
1028 if( !field.
name.IsEmpty() )
1029 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
wxString result
Test unit parsing edge cases and error handling.