38#include <wx/tokenzr.h>
49 wxString ret( aNetName );
51 ret.Replace(
"!",
"~" );
59 wxString token = aText;
65 bool sectionOpen =
false;
67 for( wxString::size_type i = 0; i < aText.size(); i++ )
70 if( aText[ i ] ==
'\\' )
72 if( i + 1 != aText.size() )
73 text.Append( aText[ i + 1 ] );
87 if( aText[ i ] ==
'!' )
96 static wxString escapeChars( wxT(
" )]}'\"" ) );
98 if( i + 1 != aText.size() && escapeChars.Find( aText[i + 1] ) == wxNOT_FOUND )
105 text.Append( aText[ i ] );
111 if( aText[i] ==
',' && sectionOpen )
117 text.Append( aText[ i ] );
126 if( aText->StartsWith(
'>' ) && aText->AfterFirst(
' ' ).IsEmpty() )
128 wxString token = aText->Upper();
130 if ( token == wxT(
">NAME" ) ) *aText = wxT(
"${REFERENCE}" );
131 else if( token == wxT(
">VALUE" ) ) *aText = wxT(
"${VALUE}" );
132 else if( token == wxT(
">PART" ) ) *aText = wxT(
"${REFERENCE}" );
133 else if( token == wxT(
">GATE" ) ) *aText = wxT(
"${UNIT}" );
134 else if( token == wxT(
">MODULE" ) ) *aText = wxT(
"${FOOTPRINT_NAME}" );
135 else if( token == wxT(
">SHEETNR" ) ) *aText = wxT(
"${#}" );
136 else if( token == wxT(
">SHEETS" ) ) *aText = wxT(
"${##}" );
137 else if( token == wxT(
">SHEET" ) ) *aText = wxT(
"${#}/${##}" );
138 else if( token == wxT(
">SHEETNR_TOTAL" ) ) *aText = wxT(
"${#}" );
139 else if( token == wxT(
">SHEETS_TOTAL" ) ) *aText = wxT(
"${##}" );
140 else if( token == wxT(
">SHEET_TOTAL" ) ) *aText = wxT(
"${#}/${##}" );
141 else if( token == wxT(
">SHEET_HEADLINE" ) ) *aText = wxT(
"${SHEETNAME}" );
142 else if( token == wxT(
">ASSEMBLY_VARIANT" ) ) *aText = wxT(
"${ASSEMBLY_VARIANT}" );
143 else if( token == wxT(
">DRAWING_NAME" ) ) *aText = wxT(
"${PROJECTNAME}" );
144 else if( token == wxT(
">LAST_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
145 else if( token == wxT(
">PLOT_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
146 else *aText = wxString::Format( wxS(
"${%s}" ), aText->Mid( 1 ).Trim() );
157 aDescr.Replace( wxS(
"\n" ), wxS(
" " ) );
158 aDescr.Replace( wxS(
"\r" ), wxEmptyString );
160 wxRegEx( wxS(
"<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\"[^>]*>" ) )
161 .ReplaceAll( &aDescr, wxS(
"\\1 " ) );
163 aDescr.Replace( wxS(
"<p>" ), wxS(
"\n\n" ) );
164 aDescr.Replace( wxS(
"</p>" ), wxS(
"\n\n" ) );
166 aDescr.Replace( wxS(
"<br>" ), wxS(
"\n" ) );
167 aDescr.Replace( wxS(
"<ul>" ), wxS(
"\n" ) );
168 aDescr.Replace( wxS(
"</ul>" ), wxS(
"\n\n" ) );
169 aDescr.Replace( wxS(
"<li></li>" ), wxS(
"\n" ) );
170 aDescr.Replace( wxS(
"<li>" ), wxS(
"\n \u2022 " ) );
174 wxRegEx( wxS(
"\n +" ) ).ReplaceAll( &aDescr, wxS(
"\n" ) );
175 wxRegEx( wxS(
" +\n" ) ).ReplaceAll( &aDescr, wxS(
"\n" ) );
177 wxRegEx( wxS(
"\n{3,}" ) ).ReplaceAll( &aDescr, wxS(
"\n\n" ) );
178 wxRegEx( wxS(
"^\n+" ) ).ReplaceAll( &aDescr, wxEmptyString );
179 wxRegEx( wxS(
"\n+$" ) ).ReplaceAll( &aDescr, wxEmptyString );
191 std::function<size_t(
const wxXmlNode* )> countNodes =
192 [&](
const wxXmlNode* node )
198 if(
const wxXmlNode* child = node->GetChildren() )
199 count += countNodes( child );
203 node = node->GetNext();
209 cnt = countNodes( aNode );
213 wxLogTrace(
traceEagleIo, wxS(
"XML node '%s' count = %zu took %0.4f ms." ),
214 aNode->GetName(), cnt, timer.
msecs() );
232 static std::array<int, 9> DIVIDERS = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
234 int integer, pre_fraction, post_fraction;
235 long long unsigned fraction;
239 bool negative = ( aValue[0] ==
'-' );
243 int ret = sscanf( aValue.c_str(),
"%d.%n%llu%n", &integer, &pre_fraction, &fraction,
255 int digits = post_fraction - pre_fraction;
259 if( digits >=
static_cast<int>( DIVIDERS.size() ) )
261 long long unsigned denom = pow( 10, digits - DIVIDERS.size() + 1 );
262 digits = DIVIDERS.size() - 1;
266 int frac_value =
ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
281 case EU_NM: ret = aValue;
break;
282 case EU_MM: ret = (
long long) aValue * 1000000;
break;
283 case EU_INCH: ret = (
long long) aValue * 25400000;
break;
284 case EU_MIL: ret = (
long long) aValue * 25400;
break;
287 if( ( ret > 0 ) != ( aValue > 0 ) )
288 wxLogError(
_(
"Invalid size %lld: too large" ), aValue );
302 wxStringTokenizer tokens( aUrn,
":" );
304 host = tokens.GetNextToken();
305 path = tokens.GetNextToken();
309 wxString tmp = tokens.GetNextToken();
311 assetId = tmp.BeforeFirst(
'/' );
324 static std::set<wxString> validAssetTypes =
333 if( validAssetTypes.count(
assetType ) == 0 )
362 return std::string( aValue.ToUTF8() );
371 if( aValue.ToCDouble( &value ) )
375 aValue.ToStdString() +
"'." );
382 if( aValue.IsEmpty() )
383 throw XML_PARSER_ERROR(
"Conversion to int failed. Original value is empty." );
385 return wxAtoi( aValue );
392 if( aValue !=
"yes" && aValue !=
"no" )
394 aValue.ToStdString() +
395 "', is neither 'yes' nor 'no'." );
397 return aValue ==
"yes";
408 value.
spin = aRot.find(
'S' ) != aRot.npos;
409 value.
mirror = aRot.find(
'M' ) != aRot.npos;
411 size_t rPos = aRot.find(
'R' );
413 if( rPos == wxString::npos )
422 for( offset = 0; offset < aRot.size(); offset++ )
424 if( wxIsdigit( aRot[offset] ) )
428 wxString degreesStr = aRot.Mid( offset );
431 if( !degreesStr.ToCDouble( &value.
degrees ) )
466 if( aNode->GetAttribute( aAttribute, &value ) )
469 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing at "
470 "line " + wxString::Format(
"%d", aNode->GetLineNumber() ) +
497 aCurrentNode = aCurrentNode->GetChildren();
499 while( aCurrentNode )
504 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
507 aCurrentNode = aCurrentNode->GetNext();
518 double dx = aEnd.
x - aStart.
x, dy = aEnd.
y - aStart.
y;
519 VECTOR2I mid = ( aStart + aEnd ) / 2;
521 double dlen = sqrt( dx*dx + dy*dy );
523 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
527 THROW_IO_ERROR( wxString::Format(
_(
"Invalid Arc with radius %0.2f and angle %0.2f" ),
532 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
535 mid.
x + dist * ( dy / dlen ),
536 mid.
y - dist * ( dx / dlen )
547 if( aAlignment ==
"center" )
549 else if( aAlignment ==
"center-right" )
551 else if( aAlignment ==
"top-left" )
553 else if( aAlignment ==
"top-center" )
555 else if( aAlignment ==
"top-right" )
557 else if( aAlignment ==
"bottom-left" )
559 else if( aAlignment ==
"bottom-center" )
561 else if( aAlignment ==
"bottom-right" )
563 else if( aAlignment ==
"center-left" )
575 io->Report( aMsg, aSeverity );
584 io->AdvanceProgressPhase();
617 if( s ==
"continuous" )
619 else if( s ==
"longdash" )
621 else if( s ==
"shortdash" )
623 else if( s ==
"dashdot" )
630 else if( s ==
"flat" )
644 for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
646 if( child->GetName() ==
"pinref" )
647 pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
648 else if( child->GetName() ==
"portref" )
649 portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
650 else if( child->GetName() ==
"wire" )
651 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
652 else if( child->GetName() ==
"junction" )
653 junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
654 else if( child->GetName() ==
"label" )
655 labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
656 else if( child->GetName() ==
"probe" )
657 probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
675 for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
677 if( child->GetName() ==
"segment" )
678 segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
750 for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
751 segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
847 text = aDescription->GetNodeContent();
890 else if( stemp ==
"name" )
892 else if( stemp ==
"both" )
1022 text = aText->GetNodeContent();
1046 const wxString& fontName =
font.CGet();
1048 if( fontName ==
"vector" )
1052 else if( fontName ==
"fixed" )
1153 else if( s ==
"round" )
1155 else if( s ==
"octagon" )
1157 else if( s ==
"long" )
1159 else if( s ==
"offset" )
1290 else if( s ==
"cutout" )
1297 for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
1299 if( child->GetName() ==
"vertex" )
1300 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1320 for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
1322 if( child->GetName() ==
"vertex" )
1323 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1362 model = aModel->GetNodeContent();
1402 for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
1404 if( child->GetName() ==
"pinmap" )
1405 pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
1418 pinmapping = std::make_unique<EPINMAPPING>( aSpice );
1420 if( aSpice->GetName() ==
"model" )
1421 model = std::make_unique<EMODEL>( aSpice );
1479 package = wxString::FromUTF8( p.c_str() );
1490 for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
1492 if( child->GetName() ==
"attribute" )
1494 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1495 attributes[ attr->name ] = std::move( attr );
1497 else if( child->GetName() ==
"variant" )
1499 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1500 variants[ variant->name ] = std::move( variant );
1560 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1562 if( child->GetName() ==
"attribute" )
1564 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1565 attributes[ attr->name ] = std::move( attr );
1567 else if( child->GetName() ==
"variant" )
1569 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1570 variants[ variant->name ] = std::move( variant );
1572 else if( child->GetName() ==
"spice" )
1574 spice = std::make_unique<ESPICE>( child, aIo );
1606 for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
1608 if( child->GetName() ==
"attribute" )
1610 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1611 attributes[ attr->name ] = std::move( attr );
1643 if( stemp ==
"must" )
1645 else if( stemp ==
"can" )
1647 else if( stemp ==
"next" )
1649 else if( stemp ==
"request" )
1651 else if( stemp ==
"always" )
1694 for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
1696 if( child->GetName() ==
"attribute" )
1697 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
1733 std::string p( pack->c_str() );
1735 package.Set( wxString::FromUTF8( p.c_str() ) );
1738 for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
1740 if( child->GetName() ==
"connects" )
1742 for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
1744 if( connect->GetName() ==
"connect" )
1745 connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
1750 else if( child->GetName() ==
"packages3dinstances" )
1752 for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
1753 package3dinst = package3dinst->GetNext() )
1755 if( package3dinst->GetName() ==
"package3dinstance" )
1756 package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
1761 else if( child->GetName() ==
"technologies" )
1763 for( wxXmlNode* technology = child->GetChildren(); technology;
1764 technology = technology->GetNext() )
1766 if( technology->GetName() ==
"technology" )
1767 technologies.emplace_back( std::make_unique<ETECHNOLOGY>( technology, aIo ) );
1804 for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
1806 if( child->GetName() ==
"description" )
1808 description = std::make_optional<EDESCRIPTION>( child, aIo );
1810 else if( child->GetName() ==
"gates" )
1812 for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
1814 std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
1815 gates[tmp->name] = std::move( tmp );
1820 else if( child->GetName() ==
"devices" )
1822 for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
1823 devices.emplace_back( std::make_unique<EDEVICE>( device, aIo ) );
1827 else if( child->GetName() ==
"spice" )
1829 spice = std::make_optional<ESPICE>( child, aIo );
1854 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1856 if( child->GetName() ==
"clearance" )
1878 for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
1880 if( child->GetName() ==
"polygon" )
1881 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
1882 else if( child->GetName() ==
"wire" )
1883 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
1884 else if( child->GetName() ==
"text" )
1885 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
1886 else if( child->GetName() ==
"dimension" )
1887 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
1888 else if( child->GetName() ==
"circle" )
1889 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
1890 else if( child->GetName() ==
"spline" )
1891 splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
1892 else if( child->GetName() ==
"rectangle" )
1893 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
1894 else if( child->GetName() ==
"frame" )
1895 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
1896 else if( child->GetName() ==
"hole" )
1897 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
1940 for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
1942 if( child->GetName() ==
"description" )
1944 description = std::make_optional<EDESCRIPTION>( child, aIo );
1946 else if( child->GetName() ==
"plain" )
1948 plain = std::make_unique<EPLAIN>( child, aIo );
1950 else if( child->GetName() ==
"moduleinsts" )
1952 for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
1953 moduleinst = moduleinst->GetNext() )
1955 if( moduleinst->GetName() ==
"moduleinst" )
1957 std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst, aIo );
1958 moduleinsts[ inst->name ] = std::move( inst );
1964 else if( child->GetName() ==
"instances" )
1966 for( wxXmlNode* instance = child->GetChildren(); instance; instance = instance->GetNext() )
1968 if( instance->GetName() ==
"instance" )
1969 instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
1972 AdvanceProgressPhase();
1974 else if( child->GetName() ==
"busses" )
1976 for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
1978 if( bus->GetName() ==
"bus" )
1979 busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
1982 AdvanceProgressPhase();
1984 else if( child->GetName() ==
"nets" )
1986 for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
1988 if( net->GetName() ==
"net" )
1989 nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
1992 AdvanceProgressPhase();
1996 AdvanceProgressPhase();
2027 for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
2029 if( child->GetName() ==
"description" )
2031 description = std::make_optional<EDESCRIPTION>( child, aIo );
2033 else if( child->GetName() ==
"attribute" )
2035 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
2060 for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
2062 if( child->GetName() ==
"description" )
2064 description = std::make_optional<EDESCRIPTION>( child, aIo );
2066 else if( child->GetName() ==
"ports" )
2068 for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
2070 if( port->GetName() ==
"port" )
2072 std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
2073 ports[ tmp->name ] = std::move( tmp );
2079 else if( child->GetName() ==
"variantdefs" )
2081 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2082 variantdef = variantdef->GetNext() )
2084 if( variantdef->GetName() ==
"variantdef" )
2086 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2094 else if( child->GetName() ==
"groups" )
2098 if(
group->GetName() ==
"schematic_group" )
2100 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2101 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2102 groups[ tmp->name ] = std::move( tmp );
2108 else if( child->GetName() ==
"parts" )
2110 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2112 if( part->GetName() ==
"part" )
2114 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2115 parts[ tmp->name ] = std::move( tmp );
2121 else if( child->GetName() ==
"sheets" )
2123 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2125 if( sheet->GetName() ==
"sheet" )
2126 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2189 note = aNote->GetNodeContent();
2201 for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
2203 if( child->GetName() ==
"note" )
2204 notes.emplace_back( std::make_unique<ENOTE>( child ) );
2300 for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
2302 if( child->GetName() ==
"description" )
2304 description = std::make_optional<EDESCRIPTION>( child, aIo );
2306 else if( child->GetName() ==
"polygon" )
2308 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2310 else if( child->GetName() ==
"wire" )
2312 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2314 else if( child->GetName() ==
"text" )
2316 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2318 else if( child->GetName() ==
"dimension" )
2320 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2322 else if( child->GetName() ==
"circle" )
2324 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2326 else if( child->GetName() ==
"rectangle" )
2328 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2330 else if( child->GetName() ==
"frame" )
2332 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2334 else if( child->GetName() ==
"hole" )
2336 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
2338 else if( child->GetName() ==
"pad" )
2340 thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
2342 else if( child->GetName() ==
"smd" )
2344 smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
2387 "library_locally_modified" );
2389 for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
2391 if( child->GetName() ==
"description" )
2393 description = std::make_optional<EDESCRIPTION>( child, aIo );
2395 else if( child->GetName() ==
"packageinstances" )
2397 for( wxXmlNode* instance = child->GetChildren(); instance;
2398 instance = instance->GetNext() )
2399 packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
2433 for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
2435 if( child->GetName() ==
"description" )
2437 description = std::make_optional<EDESCRIPTION>( child, aIo );
2439 else if( child->GetName() ==
"polygon" )
2441 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2443 else if( child->GetName() ==
"wire" )
2445 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2447 else if( child->GetName() ==
"text" )
2449 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2451 else if( child->GetName() ==
"dimension" )
2453 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2455 else if( child->GetName() ==
"pin" )
2457 pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
2459 else if( child->GetName() ==
"circle" )
2461 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2463 else if( child->GetName() ==
"rectangle" )
2465 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2467 else if( child->GetName() ==
"frame" )
2469 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2491 wxString parentNodeName;
2493 if( aLibrary->GetParent() )
2494 parentNodeName = aLibrary->GetParent()->GetName();
2496 if( parentNodeName ==
"libraries" )
2498 name = parseRequiredAttribute<wxString>( aLibrary,
"name" );
2499 urn = parseOptionalAttribute<EURN>( aLibrary,
"urn" );
2502 for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
2504 if( child->GetName() ==
"description" )
2506 description = std::make_optional<EDESCRIPTION>( child, aIo );
2508 else if( child->GetName() ==
"packages" )
2510 for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
2512 if( package->GetName() ==
"package" )
2514 std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
2515 packages[ tmp->name ] = std::move( tmp );
2521 else if( child->GetName() ==
"packages3d" )
2523 for( wxXmlNode* package3d = child->GetChildren(); package3d;
2524 package3d = package3d->GetNext() )
2526 if( package3d->GetName() ==
"package3d" )
2528 std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
2530 packages3d[ tmp->name ] = std::move( tmp );
2534 AdvanceProgressPhase();
2536 else if( child->GetName() ==
"symbols" )
2538 for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
2540 if( symbol->GetName() ==
"symbol" )
2542 std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
2543 symbols[ tmp->name ] = std::move( tmp );
2547 AdvanceProgressPhase();
2549 else if( child->GetName() ==
"devicesets" )
2551 for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
2552 deviceset = deviceset->GetNext() )
2554 if( deviceset->GetName() ==
"deviceset" )
2556 std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
2558 devicesets[ tmp->name ] = std::move( tmp );
2562 AdvanceProgressPhase();
2566 AdvanceProgressPhase();
2572 wxString libName =
name;
2581 if(
urn->IsValid() )
2582 libName += wxS(
"_" ) +
urn->assetId;
2617 for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
2619 if( child->GetName() ==
"description" )
2621 description = std::make_optional<EDESCRIPTION>( child, aIo );
2623 else if( child->GetName() ==
"libraries" )
2627 if(
library->GetName() ==
"library" )
2629 std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>(
library, aIo );
2631 wxString libName = tmp->GetName();
2637 wxString uniqueName;
2638 std::set<wxString> usedNames;
2640 for(
const auto& [setName, setLibrary] :
libraries )
2641 usedNames.emplace( setName );
2643 if( usedNames.find( libName ) != usedNames.end() )
2649 uniqueName.Format( wxS(
"%s_%d" ), libName, i );
2651 }
while( usedNames.find( uniqueName ) != usedNames.end() );
2654 libName = uniqueName;
2657 libraries[ libName ] = std::move( tmp );
2663 else if( child->GetName() ==
"attributes" )
2665 for( wxXmlNode* attribute = child->GetChildren(); attribute;
2666 attribute = attribute->GetNext() )
2668 if( attribute->GetName() ==
"attribute" )
2670 std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
2677 else if( child->GetName() ==
"variantdefs" )
2679 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2680 variantdef = variantdef->GetNext() )
2682 if( variantdef->GetName() ==
"variantdef" )
2684 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2692 else if( child->GetName() ==
"classes" )
2694 for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
2696 if( eclass->GetName() ==
"class" )
2698 std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
2699 classes[ tmp->number ] = std::move( tmp );
2705 else if( child->GetName() ==
"modules" )
2707 for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
2709 if( mod->GetName() ==
"module" )
2711 std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
2712 modules[ tmp->name ] = std::move( tmp );
2718 else if( child->GetName() ==
"groups" )
2722 if(
group->GetName() ==
"schematic_group" )
2724 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2725 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2726 groups[ tmp->name ] = std::move( tmp );
2732 else if( child->GetName() ==
"parts" )
2734 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2736 if( part->GetName() ==
"part" )
2738 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2739 parts[ tmp->name ] = std::move( tmp );
2745 else if( child->GetName() ==
"sheets" )
2747 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2749 if( sheet->GetName() ==
"sheet" )
2750 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2755 else if( child->GetName() ==
"errors" )
2757 for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
2759 if( error->GetName() ==
"approved" )
2760 errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
2777 for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
2779 if( child->GetName() ==
"settings" )
2781 for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
2782 settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
2784 AdvanceProgressPhase();
2786 else if( child->GetName() ==
"grid" )
2788 grid = std::make_optional<EGRID>( child, aIo );
2790 else if( child->GetName() ==
"filters" )
2792 for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
2794 if( filter->GetName() ==
"filter" )
2795 filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
2800 else if( child->GetName() ==
"layers" )
2802 for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
2804 if( layer->GetName() ==
"layer" )
2805 layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
2808 AdvanceProgressPhase();
2810 else if( child->GetName() ==
"schematic" )
2812 schematic = std::make_optional<ESCHEMATIC>( child, aIo );
2814 else if( child->GetName() ==
"library" )
2816 library = std::make_optional<ELIBRARY>( child, aIo );
2822 AdvanceProgressPhase();
2840 for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
2842 if( child->GetName() ==
"compitibility" )
2843 compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
2844 else if( child->GetName() ==
"drawing" )
2845 drawing = std::make_unique<EDRAWING>( child, aIo );
Model an optional XML attribute.
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)
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
const wxChar *const traceEagleIo
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
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)
opt_bool library_locally_modified
std::vector< std::unique_ptr< EDEVICE > > devices
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::vector< 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