34#include <wx/tokenzr.h>
45 wxString ret( aNetName );
47 ret.Replace(
"!",
"~" );
55 wxString token = aText;
61 bool sectionOpen =
false;
63 for( wxString::size_type i = 0; i < aText.size(); i++ )
66 if( aText[ i ] ==
'\\' )
68 if( i + 1 != aText.size() )
69 text.Append( aText[ i + 1 ] );
83 if( aText[ i ] ==
'!' )
92 static wxString escapeChars( wxT(
" )]}'\"" ) );
94 if( i + 1 != aText.size() && escapeChars.Find( aText[i + 1] ) == wxNOT_FOUND )
101 text.Append( aText[ i ] );
107 if( aText[i] ==
',' && sectionOpen )
113 text.Append( aText[ i ] );
122 if( aText->StartsWith(
'>' ) && aText->AfterFirst(
' ' ).IsEmpty() )
124 wxString token = aText->Upper();
126 if ( token == wxT(
">NAME" ) ) *aText = wxT(
"${REFERENCE}" );
127 else if( token == wxT(
">VALUE" ) ) *aText = wxT(
"${VALUE}" );
128 else if( token == wxT(
">PART" ) ) *aText = wxT(
"${REFERENCE}" );
129 else if( token == wxT(
">GATE" ) ) *aText = wxT(
"${UNIT}" );
130 else if( token == wxT(
">MODULE" ) ) *aText = wxT(
"${FOOTPRINT_NAME}" );
131 else if( token == wxT(
">SHEETNR" ) ) *aText = wxT(
"${#}" );
132 else if( token == wxT(
">SHEETS" ) ) *aText = wxT(
"${##}" );
133 else if( token == wxT(
">SHEET" ) ) *aText = wxT(
"${#}/${##}" );
134 else if( token == wxT(
">SHEETNR_TOTAL" ) ) *aText = wxT(
"${#}" );
135 else if( token == wxT(
">SHEETS_TOTAL" ) ) *aText = wxT(
"${##}" );
136 else if( token == wxT(
">SHEET_TOTAL" ) ) *aText = wxT(
"${#}/${##}" );
137 else if( token == wxT(
">SHEET_HEADLINE" ) ) *aText = wxT(
"${SHEETNAME}" );
138 else if( token == wxT(
">ASSEMBLY_VARIANT" ) ) *aText = wxT(
"${ASSEMBLY_VARIANT}" );
139 else if( token == wxT(
">DRAWING_NAME" ) ) *aText = wxT(
"${PROJECTNAME}" );
140 else if( token == wxT(
">LAST_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
141 else if( token == wxT(
">PLOT_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
142 else *aText = wxString::Format( wxS(
"${%s}" ), aText->Mid( 1 ).Trim() );
153 aDescr.Replace( wxS(
"\n" ), wxS(
" " ) );
154 aDescr.Replace( wxS(
"\r" ), wxEmptyString );
156 wxRegEx( wxS(
"<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\"[^>]*>" ) )
157 .ReplaceAll( &aDescr, wxS(
"\\1 " ) );
159 aDescr.Replace( wxS(
"<p>" ), wxS(
"\n\n" ) );
160 aDescr.Replace( wxS(
"</p>" ), wxS(
"\n\n" ) );
162 aDescr.Replace( wxS(
"<br>" ), wxS(
"\n" ) );
163 aDescr.Replace( wxS(
"<ul>" ), wxS(
"\n" ) );
164 aDescr.Replace( wxS(
"</ul>" ), wxS(
"\n\n" ) );
165 aDescr.Replace( wxS(
"<li></li>" ), wxS(
"\n" ) );
166 aDescr.Replace( wxS(
"<li>" ), wxS(
"\n \u2022 " ) );
170 wxRegEx( wxS(
"\n +" ) ).ReplaceAll( &aDescr, wxS(
"\n" ) );
171 wxRegEx( wxS(
" +\n" ) ).ReplaceAll( &aDescr, wxS(
"\n" ) );
173 wxRegEx( wxS(
"\n{3,}" ) ).ReplaceAll( &aDescr, wxS(
"\n\n" ) );
174 wxRegEx( wxS(
"^\n+" ) ).ReplaceAll( &aDescr, wxEmptyString );
175 wxRegEx( wxS(
"\n+$" ) ).ReplaceAll( &aDescr, wxEmptyString );
187 std::function<size_t(
const wxXmlNode* )> countNodes =
188 [&](
const wxXmlNode* node )
194 if(
const wxXmlNode* child = node->GetChildren() )
195 count += countNodes( child );
199 node = node->GetNext();
205 cnt = countNodes( aNode );
209 wxLogTrace(
traceEagleIo, wxS(
"XML node '%s' count = %zu took %0.4f ms." ),
210 aNode->GetName(), cnt, timer.
msecs() );
228 static std::array<int, 9> DIVIDERS = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
230 int integer, pre_fraction, post_fraction;
231 long long unsigned fraction;
235 bool negative = ( aValue[0] ==
'-' );
239 int ret = sscanf( aValue.c_str(),
"%d.%n%llu%n", &integer, &pre_fraction, &fraction,
251 int digits = post_fraction - pre_fraction;
255 if( digits >=
static_cast<int>( DIVIDERS.size() ) )
257 long long unsigned denom = pow( 10, digits - DIVIDERS.size() + 1 );
258 digits = DIVIDERS.size() - 1;
262 int frac_value =
ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
277 case EU_NM: ret = aValue;
break;
278 case EU_MM: ret = (
long long) aValue * 1000000;
break;
279 case EU_INCH: ret = (
long long) aValue * 25400000;
break;
280 case EU_MIL: ret = (
long long) aValue * 25400;
break;
283 if( ( ret > 0 ) != ( aValue > 0 ) )
284 wxLogTrace(
traceEagleIo, wxT(
"Invalid size %d: too large" ), aValue );
298 wxStringTokenizer tokens( aUrn,
":" );
300 host = tokens.GetNextToken();
301 path = tokens.GetNextToken();
305 wxString tmp = tokens.GetNextToken();
307 assetId = tmp.BeforeFirst(
'/' );
320 static std::set<wxString> validAssetTypes =
330 if( validAssetTypes.count(
assetType ) == 0 )
359 return std::string( aValue.ToUTF8() );
368 if( aValue.ToCDouble( &value ) )
372 aValue.ToStdString() +
"'." );
379 if( aValue.IsEmpty() )
380 throw XML_PARSER_ERROR(
"Conversion to int failed. Original value is empty." );
382 return wxAtoi( aValue );
389 if( aValue !=
"yes" && aValue !=
"no" )
391 aValue.ToStdString() +
392 "', is neither 'yes' nor 'no'." );
394 return aValue ==
"yes";
405 value.
spin = aRot.find(
'S' ) != aRot.npos;
406 value.
mirror = aRot.find(
'M' ) != aRot.npos;
408 size_t rPos = aRot.find(
'R' );
410 if( rPos == wxString::npos )
419 for( offset = 0; offset < aRot.size(); offset++ )
421 if( wxIsdigit( aRot[offset] ) )
425 wxString degreesStr = aRot.Mid( offset );
428 if( !degreesStr.ToCDouble( &value.
degrees ) )
463 if( aNode->GetAttribute( aAttribute, &value ) )
466 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing at "
467 "line " + wxString::Format(
"%d", aNode->GetLineNumber() ) +
494 aCurrentNode = aCurrentNode->GetChildren();
496 while( aCurrentNode )
501 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
504 aCurrentNode = aCurrentNode->GetNext();
515 double dx = aEnd.
x - aStart.
x, dy = aEnd.
y - aStart.
y;
516 VECTOR2I mid = ( aStart + aEnd ) / 2;
518 double dlen = sqrt( dx*dx + dy*dy );
520 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
528 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
531 mid.
x + dist * ( dy / dlen ),
532 mid.
y - dist * ( dx / dlen )
543 if( aAlignment ==
"center" )
545 else if( aAlignment ==
"center-right" )
547 else if( aAlignment ==
"top-left" )
549 else if( aAlignment ==
"top-center" )
551 else if( aAlignment ==
"top-right" )
553 else if( aAlignment ==
"bottom-left" )
555 else if( aAlignment ==
"bottom-center" )
557 else if( aAlignment ==
"bottom-right" )
559 else if( aAlignment ==
"center-left" )
571 io->Report( aMsg, aSeverity );
580 io->AdvanceProgressPhase();
613 if( s ==
"continuous" )
615 else if( s ==
"longdash" )
617 else if( s ==
"shortdash" )
619 else if( s ==
"dashdot" )
626 else if( s ==
"flat" )
640 for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
642 if( child->GetName() ==
"pinref" )
643 pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
644 else if( child->GetName() ==
"portref" )
645 portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
646 else if( child->GetName() ==
"wire" )
647 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
648 else if( child->GetName() ==
"junction" )
649 junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
650 else if( child->GetName() ==
"label" )
651 labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
652 else if( child->GetName() ==
"probe" )
653 probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
671 for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
673 if( child->GetName() ==
"segment" )
674 segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
746 for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
747 segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
843 text = aDescription->GetNodeContent();
886 else if( stemp ==
"name" )
888 else if( stemp ==
"both" )
1018 text = aText->GetNodeContent();
1042 const wxString& fontName = font.
CGet();
1044 if( fontName ==
"vector" )
1048 else if( fontName ==
"fixed" )
1155 else if( s ==
"round" )
1157 else if( s ==
"octagon" )
1159 else if( s ==
"long" )
1161 else if( s ==
"offset" )
1292 else if( s ==
"cutout" )
1299 for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
1301 if( child->GetName() ==
"vertex" )
1302 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1322 for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
1324 if( child->GetName() ==
"vertex" )
1325 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1364 model = aModel->GetNodeContent();
1404 for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
1406 if( child->GetName() ==
"pinmap" )
1407 pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
1420 pinmapping = std::make_unique<EPINMAPPING>( aSpice );
1422 if( aSpice->GetName() ==
"model" )
1423 model = std::make_unique<EMODEL>( aSpice );
1481 package = wxString::FromUTF8( p.c_str() );
1492 for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
1494 if( child->GetName() ==
"attribute" )
1496 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1497 attributes[ attr->name ] = std::move( attr );
1499 else if( child->GetName() ==
"variant" )
1501 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1502 variants[ variant->name ] = std::move( variant );
1562 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1564 if( child->GetName() ==
"attribute" )
1566 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1567 attributes[ attr->name ] = std::move( attr );
1569 else if( child->GetName() ==
"variant" )
1571 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1572 variants[ variant->name ] = std::move( variant );
1574 else if( child->GetName() ==
"spice" )
1576 spice = std::make_unique<ESPICE>( child, aIo );
1608 for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
1610 if( child->GetName() ==
"attribute" )
1612 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1613 attributes[ attr->name ] = std::move( attr );
1645 if( stemp ==
"must" )
1647 else if( stemp ==
"can" )
1649 else if( stemp ==
"next" )
1651 else if( stemp ==
"request" )
1653 else if( stemp ==
"always" )
1696 for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
1698 if( child->GetName() ==
"attribute" )
1699 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
1735 std::string p( pack->c_str() );
1737 package.Set( wxString::FromUTF8( p.c_str() ) );
1740 for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
1742 if( child->GetName() ==
"connects" )
1744 for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
1746 if( connect->GetName() ==
"connect" )
1747 connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
1752 else if( child->GetName() ==
"packages3dinstances" )
1754 for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
1755 package3dinst = package3dinst->GetNext() )
1757 if( package3dinst->GetName() ==
"package3dinstance" )
1758 package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
1763 else if( child->GetName() ==
"technologies" )
1765 for( wxXmlNode* technology = child->GetChildren(); technology; technology = technology->GetNext() )
1767 if( technology->GetName() ==
"technology" )
1769 std::unique_ptr<ETECHNOLOGY> tmp = std::make_unique<ETECHNOLOGY>( technology, aIo );
1808 for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
1810 if( child->GetName() ==
"description" )
1812 description = std::make_optional<EDESCRIPTION>( child, aIo );
1814 else if( child->GetName() ==
"gates" )
1816 for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
1818 std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
1819 gates[tmp->name] = std::move( tmp );
1824 else if( child->GetName() ==
"devices" )
1826 for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
1828 std::unique_ptr<EDEVICE> tmp = std::make_unique<EDEVICE>( device, aIo );
1829 devices[tmp->name] = std::move( tmp );
1834 else if( child->GetName() ==
"spice" )
1836 spice = std::make_optional<ESPICE>( child, aIo );
1861 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1863 if( child->GetName() ==
"clearance" )
1885 for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
1887 if( child->GetName() ==
"polygon" )
1888 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
1889 else if( child->GetName() ==
"wire" )
1890 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
1891 else if( child->GetName() ==
"text" )
1892 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
1893 else if( child->GetName() ==
"dimension" )
1894 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
1895 else if( child->GetName() ==
"circle" )
1896 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
1897 else if( child->GetName() ==
"spline" )
1898 splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
1899 else if( child->GetName() ==
"rectangle" )
1900 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
1901 else if( child->GetName() ==
"frame" )
1902 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
1903 else if( child->GetName() ==
"hole" )
1904 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
1947 for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
1949 if( child->GetName() ==
"description" )
1951 description = std::make_optional<EDESCRIPTION>( child, aIo );
1953 else if( child->GetName() ==
"plain" )
1955 plain = std::make_unique<EPLAIN>( child, aIo );
1957 else if( child->GetName() ==
"moduleinsts" )
1959 for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
1960 moduleinst = moduleinst->GetNext() )
1962 if( moduleinst->GetName() ==
"moduleinst" )
1964 std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst, aIo );
1965 moduleinsts[ inst->name ] = std::move( inst );
1971 else if( child->GetName() ==
"instances" )
1973 for( wxXmlNode* instance = child->GetChildren(); instance; instance = instance->GetNext() )
1975 if( instance->GetName() ==
"instance" )
1976 instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
1979 AdvanceProgressPhase();
1981 else if( child->GetName() ==
"busses" )
1983 for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
1985 if( bus->GetName() ==
"bus" )
1986 busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
1989 AdvanceProgressPhase();
1991 else if( child->GetName() ==
"nets" )
1993 for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
1995 if( net->GetName() ==
"net" )
1996 nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
1999 AdvanceProgressPhase();
2003 AdvanceProgressPhase();
2034 for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
2036 if( child->GetName() ==
"description" )
2038 description = std::make_optional<EDESCRIPTION>( child, aIo );
2040 else if( child->GetName() ==
"attribute" )
2042 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
2067 for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
2069 if( child->GetName() ==
"description" )
2071 description = std::make_optional<EDESCRIPTION>( child, aIo );
2073 else if( child->GetName() ==
"ports" )
2075 for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
2077 if( port->GetName() ==
"port" )
2079 std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
2080 ports[ tmp->name ] = std::move( tmp );
2086 else if( child->GetName() ==
"variantdefs" )
2088 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2089 variantdef = variantdef->GetNext() )
2091 if( variantdef->GetName() ==
"variantdef" )
2093 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2101 else if( child->GetName() ==
"groups" )
2105 if(
group->GetName() ==
"schematic_group" )
2107 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2108 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2109 groups[ tmp->name ] = std::move( tmp );
2115 else if( child->GetName() ==
"parts" )
2117 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2119 if( part->GetName() ==
"part" )
2121 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2122 parts[ tmp->name ] = std::move( tmp );
2128 else if( child->GetName() ==
"sheets" )
2130 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2132 if( sheet->GetName() ==
"sheet" )
2133 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2196 note = aNote->GetNodeContent();
2208 for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
2210 if( child->GetName() ==
"note" )
2211 notes.emplace_back( std::make_unique<ENOTE>( child ) );
2307 for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
2309 if( child->GetName() ==
"description" )
2311 description = std::make_optional<EDESCRIPTION>( child, aIo );
2313 else if( child->GetName() ==
"polygon" )
2315 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2317 else if( child->GetName() ==
"wire" )
2319 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2321 else if( child->GetName() ==
"text" )
2323 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2325 else if( child->GetName() ==
"dimension" )
2327 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2329 else if( child->GetName() ==
"circle" )
2331 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2333 else if( child->GetName() ==
"rectangle" )
2335 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2337 else if( child->GetName() ==
"frame" )
2339 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2341 else if( child->GetName() ==
"hole" )
2343 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
2345 else if( child->GetName() ==
"pad" )
2347 thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
2349 else if( child->GetName() ==
"smd" )
2351 smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
2394 "library_locally_modified" );
2396 for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
2398 if( child->GetName() ==
"description" )
2400 description = std::make_optional<EDESCRIPTION>( child, aIo );
2402 else if( child->GetName() ==
"packageinstances" )
2404 for( wxXmlNode* instance = child->GetChildren(); instance;
2405 instance = instance->GetNext() )
2406 packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
2440 for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
2442 if( child->GetName() ==
"description" )
2444 description = std::make_optional<EDESCRIPTION>( child, aIo );
2446 else if( child->GetName() ==
"polygon" )
2448 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2450 else if( child->GetName() ==
"wire" )
2452 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2454 else if( child->GetName() ==
"text" )
2456 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2458 else if( child->GetName() ==
"dimension" )
2460 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2462 else if( child->GetName() ==
"pin" )
2464 pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
2466 else if( child->GetName() ==
"circle" )
2468 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2470 else if( child->GetName() ==
"rectangle" )
2472 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2474 else if( child->GetName() ==
"frame" )
2476 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2498 wxString parentNodeName;
2500 if( aLibrary->GetParent() )
2501 parentNodeName = aLibrary->GetParent()->GetName();
2503 if( parentNodeName ==
"libraries" )
2505 name = parseRequiredAttribute<wxString>( aLibrary,
"name" );
2506 urn = parseOptionalAttribute<EURN>( aLibrary,
"urn" );
2509 for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
2511 if( child->GetName() ==
"description" )
2513 description = std::make_optional<EDESCRIPTION>( child, aIo );
2515 else if( child->GetName() ==
"packages" )
2517 for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
2519 if( package->GetName() ==
"package" )
2521 std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
2522 packages[ tmp->name ] = std::move( tmp );
2528 else if( child->GetName() ==
"packages3d" )
2530 for( wxXmlNode* package3d = child->GetChildren(); package3d;
2531 package3d = package3d->GetNext() )
2533 if( package3d->GetName() ==
"package3d" )
2535 std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
2537 packages3d[ tmp->name ] = std::move( tmp );
2541 AdvanceProgressPhase();
2543 else if( child->GetName() ==
"symbols" )
2545 for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
2547 if( symbol->GetName() ==
"symbol" )
2549 std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
2550 symbols[ tmp->name ] = std::move( tmp );
2554 AdvanceProgressPhase();
2556 else if( child->GetName() ==
"devicesets" )
2558 for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
2559 deviceset = deviceset->GetNext() )
2561 if( deviceset->GetName() ==
"deviceset" )
2563 std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
2565 devicesets[ tmp->name ] = std::move( tmp );
2569 AdvanceProgressPhase();
2573 AdvanceProgressPhase();
2579 wxString libName =
name;
2588 if(
urn->IsValid() )
2589 libName += wxS(
"_" ) +
urn->assetId;
2624 for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
2626 if( child->GetName() ==
"description" )
2628 description = std::make_optional<EDESCRIPTION>( child, aIo );
2630 else if( child->GetName() ==
"libraries" )
2634 if(
library->GetName() ==
"library" )
2636 std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>(
library, aIo );
2638 wxString libName = tmp->GetName();
2644 wxString uniqueName;
2645 std::set<wxString> usedNames;
2647 for(
const auto& [setName, setLibrary] :
libraries )
2648 usedNames.emplace( setName );
2653 for(
int i = 1; i <= (int) usedNames.size() + 1; i++ )
2655 uniqueName.Format( wxS(
"%s_%d" ), libName, i );
2657 if( usedNames.find( uniqueName ) == usedNames.end() )
2661 libName = uniqueName;
2664 libraries[ libName ] = std::move( tmp );
2670 else if( child->GetName() ==
"attributes" )
2672 for( wxXmlNode* attribute = child->GetChildren(); attribute;
2673 attribute = attribute->GetNext() )
2675 if( attribute->GetName() ==
"attribute" )
2677 std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
2684 else if( child->GetName() ==
"variantdefs" )
2686 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2687 variantdef = variantdef->GetNext() )
2689 if( variantdef->GetName() ==
"variantdef" )
2691 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2699 else if( child->GetName() ==
"classes" )
2701 for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
2703 if( eclass->GetName() ==
"class" )
2705 std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
2706 classes[ tmp->number ] = std::move( tmp );
2712 else if( child->GetName() ==
"modules" )
2714 for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
2716 if( mod->GetName() ==
"module" )
2718 std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
2719 modules[ tmp->name ] = std::move( tmp );
2725 else if( child->GetName() ==
"groups" )
2729 if(
group->GetName() ==
"schematic_group" )
2731 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2732 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2733 groups[ tmp->name ] = std::move( tmp );
2739 else if( child->GetName() ==
"parts" )
2741 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2743 if( part->GetName() ==
"part" )
2745 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2746 parts[ tmp->name ] = std::move( tmp );
2752 else if( child->GetName() ==
"sheets" )
2754 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2756 if( sheet->GetName() ==
"sheet" )
2757 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2762 else if( child->GetName() ==
"errors" )
2764 for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
2766 if( error->GetName() ==
"approved" )
2767 errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
2784 for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
2786 if( child->GetName() ==
"settings" )
2788 for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
2789 settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
2791 AdvanceProgressPhase();
2793 else if( child->GetName() ==
"grid" )
2795 grid = std::make_optional<EGRID>( child, aIo );
2797 else if( child->GetName() ==
"filters" )
2799 for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
2801 if( filter->GetName() ==
"filter" )
2802 filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
2807 else if( child->GetName() ==
"layers" )
2809 for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
2811 if( layer->GetName() ==
"layer" )
2812 layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
2815 AdvanceProgressPhase();
2817 else if( child->GetName() ==
"schematic" )
2819 schematic = std::make_optional<ESCHEMATIC>( child, aIo );
2821 else if( child->GetName() ==
"library" )
2823 library = std::make_optional<ELIBRARY>( child, aIo );
2829 AdvanceProgressPhase();
2847 for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
2849 if( child->GetName() ==
"compitibility" )
2850 compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
2851 else if( child->GetName() ==
"drawing" )
2852 drawing = std::make_unique<EDRAWING>( child, aIo );
Model an optional XML attribute.
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
void Set(const wxString &aString)
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
EURN Convert< EURN >(const wxString &aUrn)
std::string Convert< std::string >(const wxString &aValue)
static int parseAlignment(const wxString &aAlignment)
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
double Convert< double >(const wxString &aValue)
wxString escapeName(const wxString &aNetName)
Translates Eagle special characters to their counterparts in KiCad.
wxString interpretText(const wxString &aText)
Interprets special characters in Eagle text and converts them to KiCAD notation.
bool substituteVariable(wxString *aText)
Translates Eagle special text reference to a KiCad variable reference.
constexpr auto DEFAULT_ALIGNMENT
int Convert< int >(const wxString &aValue)
wxString Convert< wxString >(const wxString &aValue)
size_t GetNodeCount(const wxXmlNode *aNode)
Fetch the number of XML nodes within aNode.
EROT Convert< EROT >(const wxString &aRot)
parse an Eagle XML "rot" field.
T parseRequiredAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse aAttribute of the XML node aNode.
bool Convert< bool >(const wxString &aValue)
ECOORD Convert< ECOORD >(const wxString &aCoord)
VECTOR2I ConvertEagleTextSize(const opt_wxString &font, const ECOORD &size)
Converts Eagle's text size to KiCad text size depending on the font used.
OPTIONAL_XML_ATTRIBUTE< T > parseOptionalAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse option aAttribute of the XML node aNode.
VECTOR2I ConvertArcCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, double aAngle)
Convert an Eagle curve end to a KiCad center for S_ARC.
wxString convertDescription(wxString aDescr)
Converts Eagle's HTML description into KiCad description format.
T Convert(const wxString &aValue)
Convert a wxString to a generic type T.
OPTIONAL_XML_ATTRIBUTE< wxString > opt_wxString
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
VECTOR2I ConvertEagleTextSize(const opt_wxString &font, const ECOORD &size)
Converts Eagle's text size to KiCad text size depending on the font used.
const wxChar *const traceEagleIo
#define THROW_IO_ERRORF(msg,...)
wxString RemoveHTMLTags(const wxString &aInput)
Removes HTML tags from a string.
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
bool ReplaceIllegalFileNameChars(std::string &aName, int aReplaceChar)
Checks aName for illegal file name characters.
EAGLE_BASE(IO_BASE *aIo=nullptr)
void AdvanceProgressPhase()
void Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Send a message to the IO_BASE REPORTER object if one exists.
EAGLE_DOC(wxXmlNode *aEagleDoc, IO_BASE *aIo=nullptr)
std::optional< ECOMPATIBILITY > compatibility
wxString version
The Eagle XML file version.
std::unique_ptr< EDRAWING > drawing
EAPPROVED(wxXmlNode *aApproved, IO_BASE *aIo=nullptr)
EBUS(wxXmlNode *aBus, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< ESEGMENT > > segments
ECIRCLE(wxXmlNode *aCircle, IO_BASE *aIo=nullptr)
std::map< wxString, ECOORD > clearanceMap
ECLASS(wxXmlNode *aClass, IO_BASE *aIo=nullptr)
ECOMPATIBILITY(wxXmlNode *aCompatibility, IO_BASE *aIo=nullptr)
opt_wxString contactroute
ECONNECT(wxXmlNode *aConnect, IO_BASE *aIo=nullptr)
long long int value
Value expressed in nanometers.
static long long int ConvertToNm(int aValue, enum EAGLE_UNIT aUnit)
Converts a size expressed in a certain unit to nanometers.
EDESCRIPTION(wxXmlNode *aDescription, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EDEVICE > > devices
opt_bool library_locally_modified
opt_bool locally_modified
std::optional< EDESCRIPTION > description
EDEVICE_SET(wxXmlNode *aDeviceSet, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EGATE > > gates
std::optional< ESPICE > spice
std::vector< std::unique_ptr< EPACKAGE3DINST > > package3dinstances
std::vector< std::unique_ptr< ECONNECT > > connects
EDEVICE(wxXmlNode *aDevice, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< ETECHNOLOGY > > technologies
opt_wxString dimensionType
EDIMENSION(wxXmlNode *aDimension, IO_BASE *aIo=nullptr)
EDRAWING(wxXmlNode *aDrawing, IO_BASE *aIo=nullptr)
EELEMENT(wxXmlNode *aElement, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EATTR > > attributes
std::map< wxString, std::unique_ptr< EVARIANT > > variants
EFILTER(wxXmlNode *aGrid, IO_BASE *aIo=nullptr)
EFRAME(wxXmlNode *aFrameNode, IO_BASE *aIo=nullptr)
EGATE(wxXmlNode *aGate, IO_BASE *aIo=nullptr)
EGRID(wxXmlNode *aGrid, IO_BASE *aIo=nullptr)
EHOLE(wxXmlNode *aHole, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EATTR > > attributes
EINSTANCE(wxXmlNode *aInstance, IO_BASE *aIo=nullptr)
EJUNCTION(wxXmlNode *aJunction, IO_BASE *aIo=nullptr)
ELABEL(wxXmlNode *aLabel, IO_BASE *aIo=nullptr)
ELAYER(wxXmlNode *aLayer, IO_BASE *aIo=nullptr)
wxString GetName() const
Fetch the fully unique library name.
ELIBRARY(wxXmlNode *aLibrary, IO_BASE *aIo=nullptr)
EMODEL(wxXmlNode *aModel, IO_BASE *aIo=nullptr)
EMODULEINST(wxXmlNode *aModuleInst, IO_BASE *aIo=nullptr)
opt_wxString moduleVariant
std::map< wxString, std::unique_ptr< EPART > > parts
std::map< wxString, std::unique_ptr< ESCHEMATIC_GROUP > > groups
std::vector< std::unique_ptr< ESHEET > > sheets
std::optional< EDESCRIPTION > description
EMODULE(wxXmlNode *aModule, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EVARIANTDEF > > variantdefs
std::map< wxString, std::unique_ptr< EPORT > > ports
std::vector< std::unique_ptr< ESEGMENT > > segments
ENOTE(wxXmlNode *aNote, IO_BASE *aIo=nullptr)
EPACKAGE3DINST(wxXmlNode *aPackage3dInst, IO_BASE *aIo=nullptr)
opt_bool library_locally_modified
std::optional< EDESCRIPTION > description
std::vector< std::unique_ptr< EPACKAGEINSTANCE > > packageinstances
EPACKAGE3D(wxXmlNode *aPackage3d, IO_BASE *aIo=nullptr)
EPACKAGEINSTANCE(wxXmlNode *aPackageInstance, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EPOLYGON > > polygons
std::vector< std::unique_ptr< EPAD > > thtpads
std::vector< std::unique_ptr< ECIRCLE > > circles
std::vector< std::unique_ptr< ESMD > > smdpads
std::vector< std::unique_ptr< EDIMENSION > > dimensions
opt_bool library_locally_modified
std::vector< std::unique_ptr< EHOLE > > holes
std::vector< std::unique_ptr< EFRAME > > frames
std::vector< std::unique_ptr< ERECT > > rectangles
std::vector< std::unique_ptr< ETEXT > > texts
std::vector< std::unique_ptr< EWIRE > > wires
std::optional< EDESCRIPTION > description
EPACKAGE(wxXmlNode *aPackage, IO_BASE *aIo=nullptr)
opt_bool locally_modified
EPAD_COMMON(wxXmlNode *aPad, IO_BASE *aIo=nullptr)
EPAD(wxXmlNode *aPad, IO_BASE *aIo=nullptr)
std::unique_ptr< ESPICE > spice
opt_bool override_locally_modified
opt_wxString override_package_urn
std::map< wxString, std::unique_ptr< EATTR > > attributes
opt_wxString override_package3d_urn
EPART(wxXmlNode *aPart, IO_BASE *aIo=nullptr)
opt_wxString package3d_urn
std::map< wxString, std::unique_ptr< EVARIANT > > variants
EPINMAPPING(wxXmlNode *aPinMap, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EPINMAP > > pinmaps
EPINMAP(wxXmlNode *aPinMap, IO_BASE *aIo=nullptr)
EPINREF(wxXmlNode *aPinRef, IO_BASE *aIo=nullptr)
EPIN(wxXmlNode *aPin, IO_BASE *aIo=nullptr)
EPLAIN(wxXmlNode *aPlain, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EVERTEX > > vertices
EPOLYGON(wxXmlNode *aPolygon, IO_BASE *aIo=nullptr)
EPORTREF(wxXmlNode *aPortRef, IO_BASE *aIo=nullptr)
EPORT(wxXmlNode *aPort, IO_BASE *aIo=nullptr)
EPROBE(wxXmlNode *aProbe, IO_BASE *aIo=nullptr)
ERECT(wxXmlNode *aRect, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EATTR > > attributes
ESCHEMATIC_GROUP(wxXmlNode *aSchematicGroup, IO_BASE *aIo=nullptr)
std::optional< EDESCRIPTION > description
std::map< wxString, std::unique_ptr< EMODULE > > modules
std::map< wxString, std::unique_ptr< EATTR > > attributes
std::vector< std::unique_ptr< EAPPROVED > > errors
std::optional< EDESCRIPTION > description
std::map< wxString, std::unique_ptr< ECLASS > > classes
std::vector< std::unique_ptr< ESHEET > > sheets
std::map< wxString, std::unique_ptr< EPART > > parts
ESCHEMATIC(wxXmlNode *aSchematic, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< ELIBRARY > > libraries
std::map< wxString, std::unique_ptr< EVARIANTDEF > > variantdefs
std::map< wxString, std::unique_ptr< ESCHEMATIC_GROUP > > groups
ESEGMENT(wxXmlNode *aSegment, IO_BASE *aIo=nullptr)
opt_bool alwaysvectorfont
opt_bool keepoldvectorfont
opt_wxString verticaltext
ESETTING(wxXmlNode *aSetting, IO_BASE *aIo=nullptr)
ESHEET(wxXmlNode *aSheet, IO_BASE *aIo=nullptr)
ESMD(wxXmlNode *aSMD, IO_BASE *aIo=nullptr)
ESPICE(wxXmlNode *aSpice, IO_BASE *aIo=nullptr)
std::unique_ptr< EMODEL > model
std::unique_ptr< EPINMAPPING > pinmapping
std::vector< std::unique_ptr< EVERTEX > > vertices
ESPLINE(wxXmlNode *aSpline, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EFRAME > > frames
std::optional< EDESCRIPTION > description
std::vector< std::unique_ptr< EPIN > > pins
std::vector< std::unique_ptr< ECIRCLE > > circles
opt_bool library_locally_modified
std::vector< std::unique_ptr< ETEXT > > texts
std::vector< std::unique_ptr< EPOLYGON > > polygons
std::vector< std::unique_ptr< ERECT > > rectangles
std::vector< std::unique_ptr< EWIRE > > wires
ESYMBOL(wxXmlNode *aSymbol, IO_BASE *aIo=nullptr)
opt_bool locally_modified
std::vector< std::unique_ptr< EDIMENSION > > dimensions
std::vector< std::unique_ptr< EATTR > > attributes
ETECHNOLOGY(wxXmlNode *aTechnology, IO_BASE *aIo=nullptr)
ETEXT(wxXmlNode *aText, IO_BASE *aIo=nullptr)
VECTOR2I ConvertSize() const
Calculate text size based on font type and size.
Container that parses Eagle library file "urn" definitions.
bool IsValid() const
Check if the string passed to the ctor was a valid Eagle urn.
wxString host
Should always be "urn".
void Parse(const wxString &aUrn)
wxString assetVersion
May be empty depending on the asset type.
wxString assetId
The unique asset identifier for the asset type.
wxString assetType
Must be "symbol", "footprint", "package", "component", or "library".
wxString path
Path to the asset type below.
EVARIANTDEF(wxXmlNode *aVariantDef, IO_BASE *aIo=nullptr)
EVARIANT(wxXmlNode *aVariant, IO_BASE *aIo=nullptr)
EVERTEX(wxXmlNode *aVertex, IO_BASE *aIo=nullptr)
opt_double curve
range is -359.9..359.9
EVIA(wxXmlNode *aVia, IO_BASE *aIo=nullptr)
int layer_back_most
< extent
EWIRE(wxXmlNode *aWire, IO_BASE *aIo=nullptr)
opt_double curve
range is -359.9..359.9
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
wxLogTrace helper definitions.
double DEG2RAD(double deg)
VECTOR2< int32_t > VECTOR2I