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 wxLogError(
_(
"Invalid size %lld: 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 ) )
524 THROW_IO_ERROR( wxString::Format(
_(
"Invalid Arc with radius %0.2f and angle %0.2f" ),
529 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
532 mid.
x + dist * ( dy / dlen ),
533 mid.
y - dist * ( dx / dlen )
544 if( aAlignment ==
"center" )
546 else if( aAlignment ==
"center-right" )
548 else if( aAlignment ==
"top-left" )
550 else if( aAlignment ==
"top-center" )
552 else if( aAlignment ==
"top-right" )
554 else if( aAlignment ==
"bottom-left" )
556 else if( aAlignment ==
"bottom-center" )
558 else if( aAlignment ==
"bottom-right" )
560 else if( aAlignment ==
"center-left" )
572 io->Report( aMsg, aSeverity );
581 io->AdvanceProgressPhase();
614 if( s ==
"continuous" )
616 else if( s ==
"longdash" )
618 else if( s ==
"shortdash" )
620 else if( s ==
"dashdot" )
627 else if( s ==
"flat" )
641 for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
643 if( child->GetName() ==
"pinref" )
644 pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
645 else if( child->GetName() ==
"portref" )
646 portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
647 else if( child->GetName() ==
"wire" )
648 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
649 else if( child->GetName() ==
"junction" )
650 junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
651 else if( child->GetName() ==
"label" )
652 labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
653 else if( child->GetName() ==
"probe" )
654 probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
672 for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
674 if( child->GetName() ==
"segment" )
675 segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
747 for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
748 segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
844 text = aDescription->GetNodeContent();
887 else if( stemp ==
"name" )
889 else if( stemp ==
"both" )
1019 text = aText->GetNodeContent();
1043 const wxString& fontName = font.
CGet();
1045 if( fontName ==
"vector" )
1049 else if( fontName ==
"fixed" )
1156 else if( s ==
"round" )
1158 else if( s ==
"octagon" )
1160 else if( s ==
"long" )
1162 else if( s ==
"offset" )
1293 else if( s ==
"cutout" )
1300 for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
1302 if( child->GetName() ==
"vertex" )
1303 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1323 for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
1325 if( child->GetName() ==
"vertex" )
1326 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1365 model = aModel->GetNodeContent();
1405 for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
1407 if( child->GetName() ==
"pinmap" )
1408 pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
1421 pinmapping = std::make_unique<EPINMAPPING>( aSpice );
1423 if( aSpice->GetName() ==
"model" )
1424 model = std::make_unique<EMODEL>( aSpice );
1482 package = wxString::FromUTF8( p.c_str() );
1493 for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
1495 if( child->GetName() ==
"attribute" )
1497 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1498 attributes[ attr->name ] = std::move( attr );
1500 else if( child->GetName() ==
"variant" )
1502 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1503 variants[ variant->name ] = std::move( variant );
1563 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1565 if( child->GetName() ==
"attribute" )
1567 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1568 attributes[ attr->name ] = std::move( attr );
1570 else if( child->GetName() ==
"variant" )
1572 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1573 variants[ variant->name ] = std::move( variant );
1575 else if( child->GetName() ==
"spice" )
1577 spice = std::make_unique<ESPICE>( child, aIo );
1609 for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
1611 if( child->GetName() ==
"attribute" )
1613 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1614 attributes[ attr->name ] = std::move( attr );
1646 if( stemp ==
"must" )
1648 else if( stemp ==
"can" )
1650 else if( stemp ==
"next" )
1652 else if( stemp ==
"request" )
1654 else if( stemp ==
"always" )
1697 for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
1699 if( child->GetName() ==
"attribute" )
1700 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
1736 std::string p( pack->c_str() );
1738 package.Set( wxString::FromUTF8( p.c_str() ) );
1741 for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
1743 if( child->GetName() ==
"connects" )
1745 for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
1747 if( connect->GetName() ==
"connect" )
1748 connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
1753 else if( child->GetName() ==
"packages3dinstances" )
1755 for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
1756 package3dinst = package3dinst->GetNext() )
1758 if( package3dinst->GetName() ==
"package3dinstance" )
1759 package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
1764 else if( child->GetName() ==
"technologies" )
1766 for( wxXmlNode* technology = child->GetChildren(); technology; technology = technology->GetNext() )
1768 if( technology->GetName() ==
"technology" )
1770 std::unique_ptr<ETECHNOLOGY> tmp = std::make_unique<ETECHNOLOGY>( technology, aIo );
1809 for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
1811 if( child->GetName() ==
"description" )
1813 description = std::make_optional<EDESCRIPTION>( child, aIo );
1815 else if( child->GetName() ==
"gates" )
1817 for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
1819 std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
1820 gates[tmp->name] = std::move( tmp );
1825 else if( child->GetName() ==
"devices" )
1827 for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
1829 std::unique_ptr<EDEVICE> tmp = std::make_unique<EDEVICE>( device, aIo );
1830 devices[tmp->name] = std::move( tmp );
1835 else if( child->GetName() ==
"spice" )
1837 spice = std::make_optional<ESPICE>( child, aIo );
1862 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1864 if( child->GetName() ==
"clearance" )
1886 for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
1888 if( child->GetName() ==
"polygon" )
1889 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
1890 else if( child->GetName() ==
"wire" )
1891 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
1892 else if( child->GetName() ==
"text" )
1893 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
1894 else if( child->GetName() ==
"dimension" )
1895 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
1896 else if( child->GetName() ==
"circle" )
1897 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
1898 else if( child->GetName() ==
"spline" )
1899 splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
1900 else if( child->GetName() ==
"rectangle" )
1901 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
1902 else if( child->GetName() ==
"frame" )
1903 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
1904 else if( child->GetName() ==
"hole" )
1905 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
1948 for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
1950 if( child->GetName() ==
"description" )
1952 description = std::make_optional<EDESCRIPTION>( child, aIo );
1954 else if( child->GetName() ==
"plain" )
1956 plain = std::make_unique<EPLAIN>( child, aIo );
1958 else if( child->GetName() ==
"moduleinsts" )
1960 for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
1961 moduleinst = moduleinst->GetNext() )
1963 if( moduleinst->GetName() ==
"moduleinst" )
1965 std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst, aIo );
1966 moduleinsts[ inst->name ] = std::move( inst );
1972 else if( child->GetName() ==
"instances" )
1974 for( wxXmlNode* instance = child->GetChildren(); instance; instance = instance->GetNext() )
1976 if( instance->GetName() ==
"instance" )
1977 instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
1980 AdvanceProgressPhase();
1982 else if( child->GetName() ==
"busses" )
1984 for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
1986 if( bus->GetName() ==
"bus" )
1987 busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
1990 AdvanceProgressPhase();
1992 else if( child->GetName() ==
"nets" )
1994 for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
1996 if( net->GetName() ==
"net" )
1997 nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
2000 AdvanceProgressPhase();
2004 AdvanceProgressPhase();
2035 for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
2037 if( child->GetName() ==
"description" )
2039 description = std::make_optional<EDESCRIPTION>( child, aIo );
2041 else if( child->GetName() ==
"attribute" )
2043 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
2068 for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
2070 if( child->GetName() ==
"description" )
2072 description = std::make_optional<EDESCRIPTION>( child, aIo );
2074 else if( child->GetName() ==
"ports" )
2076 for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
2078 if( port->GetName() ==
"port" )
2080 std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
2081 ports[ tmp->name ] = std::move( tmp );
2087 else if( child->GetName() ==
"variantdefs" )
2089 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2090 variantdef = variantdef->GetNext() )
2092 if( variantdef->GetName() ==
"variantdef" )
2094 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2102 else if( child->GetName() ==
"groups" )
2106 if(
group->GetName() ==
"schematic_group" )
2108 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2109 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2110 groups[ tmp->name ] = std::move( tmp );
2116 else if( child->GetName() ==
"parts" )
2118 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2120 if( part->GetName() ==
"part" )
2122 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2123 parts[ tmp->name ] = std::move( tmp );
2129 else if( child->GetName() ==
"sheets" )
2131 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2133 if( sheet->GetName() ==
"sheet" )
2134 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2197 note = aNote->GetNodeContent();
2209 for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
2211 if( child->GetName() ==
"note" )
2212 notes.emplace_back( std::make_unique<ENOTE>( child ) );
2308 for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
2310 if( child->GetName() ==
"description" )
2312 description = std::make_optional<EDESCRIPTION>( child, aIo );
2314 else if( child->GetName() ==
"polygon" )
2316 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2318 else if( child->GetName() ==
"wire" )
2320 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2322 else if( child->GetName() ==
"text" )
2324 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2326 else if( child->GetName() ==
"dimension" )
2328 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2330 else if( child->GetName() ==
"circle" )
2332 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2334 else if( child->GetName() ==
"rectangle" )
2336 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2338 else if( child->GetName() ==
"frame" )
2340 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2342 else if( child->GetName() ==
"hole" )
2344 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
2346 else if( child->GetName() ==
"pad" )
2348 thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
2350 else if( child->GetName() ==
"smd" )
2352 smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
2395 "library_locally_modified" );
2397 for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
2399 if( child->GetName() ==
"description" )
2401 description = std::make_optional<EDESCRIPTION>( child, aIo );
2403 else if( child->GetName() ==
"packageinstances" )
2405 for( wxXmlNode* instance = child->GetChildren(); instance;
2406 instance = instance->GetNext() )
2407 packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
2441 for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
2443 if( child->GetName() ==
"description" )
2445 description = std::make_optional<EDESCRIPTION>( child, aIo );
2447 else if( child->GetName() ==
"polygon" )
2449 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2451 else if( child->GetName() ==
"wire" )
2453 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2455 else if( child->GetName() ==
"text" )
2457 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2459 else if( child->GetName() ==
"dimension" )
2461 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2463 else if( child->GetName() ==
"pin" )
2465 pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
2467 else if( child->GetName() ==
"circle" )
2469 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2471 else if( child->GetName() ==
"rectangle" )
2473 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2475 else if( child->GetName() ==
"frame" )
2477 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2499 wxString parentNodeName;
2501 if( aLibrary->GetParent() )
2502 parentNodeName = aLibrary->GetParent()->GetName();
2504 if( parentNodeName ==
"libraries" )
2506 name = parseRequiredAttribute<wxString>( aLibrary,
"name" );
2507 urn = parseOptionalAttribute<EURN>( aLibrary,
"urn" );
2510 for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
2512 if( child->GetName() ==
"description" )
2514 description = std::make_optional<EDESCRIPTION>( child, aIo );
2516 else if( child->GetName() ==
"packages" )
2518 for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
2520 if( package->GetName() ==
"package" )
2522 std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
2523 packages[ tmp->name ] = std::move( tmp );
2529 else if( child->GetName() ==
"packages3d" )
2531 for( wxXmlNode* package3d = child->GetChildren(); package3d;
2532 package3d = package3d->GetNext() )
2534 if( package3d->GetName() ==
"package3d" )
2536 std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
2538 packages3d[ tmp->name ] = std::move( tmp );
2542 AdvanceProgressPhase();
2544 else if( child->GetName() ==
"symbols" )
2546 for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
2548 if( symbol->GetName() ==
"symbol" )
2550 std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
2551 symbols[ tmp->name ] = std::move( tmp );
2555 AdvanceProgressPhase();
2557 else if( child->GetName() ==
"devicesets" )
2559 for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
2560 deviceset = deviceset->GetNext() )
2562 if( deviceset->GetName() ==
"deviceset" )
2564 std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
2566 devicesets[ tmp->name ] = std::move( tmp );
2570 AdvanceProgressPhase();
2574 AdvanceProgressPhase();
2580 wxString libName =
name;
2589 if(
urn->IsValid() )
2590 libName += wxS(
"_" ) +
urn->assetId;
2625 for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
2627 if( child->GetName() ==
"description" )
2629 description = std::make_optional<EDESCRIPTION>( child, aIo );
2631 else if( child->GetName() ==
"libraries" )
2635 if(
library->GetName() ==
"library" )
2637 std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>(
library, aIo );
2639 wxString libName = tmp->GetName();
2645 wxString uniqueName;
2646 std::set<wxString> usedNames;
2648 for(
const auto& [setName, setLibrary] :
libraries )
2649 usedNames.emplace( setName );
2654 for(
int i = 1; i <= (int) usedNames.size() + 1; i++ )
2656 uniqueName.Format( wxS(
"%s_%d" ), libName, i );
2658 if( usedNames.find( uniqueName ) == usedNames.end() )
2662 libName = uniqueName;
2665 libraries[ libName ] = std::move( tmp );
2671 else if( child->GetName() ==
"attributes" )
2673 for( wxXmlNode* attribute = child->GetChildren(); attribute;
2674 attribute = attribute->GetNext() )
2676 if( attribute->GetName() ==
"attribute" )
2678 std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
2685 else if( child->GetName() ==
"variantdefs" )
2687 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2688 variantdef = variantdef->GetNext() )
2690 if( variantdef->GetName() ==
"variantdef" )
2692 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2700 else if( child->GetName() ==
"classes" )
2702 for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
2704 if( eclass->GetName() ==
"class" )
2706 std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
2707 classes[ tmp->number ] = std::move( tmp );
2713 else if( child->GetName() ==
"modules" )
2715 for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
2717 if( mod->GetName() ==
"module" )
2719 std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
2720 modules[ tmp->name ] = std::move( tmp );
2726 else if( child->GetName() ==
"groups" )
2730 if(
group->GetName() ==
"schematic_group" )
2732 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2733 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2734 groups[ tmp->name ] = std::move( tmp );
2740 else if( child->GetName() ==
"parts" )
2742 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2744 if( part->GetName() ==
"part" )
2746 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2747 parts[ tmp->name ] = std::move( tmp );
2753 else if( child->GetName() ==
"sheets" )
2755 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2757 if( sheet->GetName() ==
"sheet" )
2758 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2763 else if( child->GetName() ==
"errors" )
2765 for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
2767 if( error->GetName() ==
"approved" )
2768 errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
2785 for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
2787 if( child->GetName() ==
"settings" )
2789 for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
2790 settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
2792 AdvanceProgressPhase();
2794 else if( child->GetName() ==
"grid" )
2796 grid = std::make_optional<EGRID>( child, aIo );
2798 else if( child->GetName() ==
"filters" )
2800 for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
2802 if( filter->GetName() ==
"filter" )
2803 filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
2808 else if( child->GetName() ==
"layers" )
2810 for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
2812 if( layer->GetName() ==
"layer" )
2813 layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
2816 AdvanceProgressPhase();
2818 else if( child->GetName() ==
"schematic" )
2820 schematic = std::make_optional<ESCHEMATIC>( child, aIo );
2822 else if( child->GetName() ==
"library" )
2824 library = std::make_optional<ELIBRARY>( child, aIo );
2830 AdvanceProgressPhase();
2848 for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
2850 if( child->GetName() ==
"compitibility" )
2851 compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
2852 else if( child->GetName() ==
"drawing" )
2853 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_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)
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