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 )
420 size_t offset = rPos + 1;
429 wxString degreesStr = aRot.Mid( offset );
432 if( !degreesStr.ToCDouble( &value.
degrees ) )
467 if( aNode->GetAttribute( aAttribute, &value ) )
470 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing at "
471 "line " + wxString::Format(
"%d", aNode->GetLineNumber() ) +
498 aCurrentNode = aCurrentNode->GetChildren();
500 while( aCurrentNode )
505 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
508 aCurrentNode = aCurrentNode->GetNext();
519 double dx = aEnd.
x - aStart.
x, dy = aEnd.
y - aStart.
y;
520 VECTOR2I mid = ( aStart + aEnd ) / 2;
522 double dlen = sqrt( dx*dx + dy*dy );
524 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
528 THROW_IO_ERROR( wxString::Format(
_(
"Invalid Arc with radius %0.2f and angle %0.2f" ),
533 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
536 mid.
x + dist * ( dy / dlen ),
537 mid.
y - dist * ( dx / dlen )
548 if( aAlignment ==
"center" )
550 else if( aAlignment ==
"center-right" )
552 else if( aAlignment ==
"top-left" )
554 else if( aAlignment ==
"top-center" )
556 else if( aAlignment ==
"top-right" )
558 else if( aAlignment ==
"bottom-left" )
560 else if( aAlignment ==
"bottom-center" )
562 else if( aAlignment ==
"bottom-right" )
564 else if( aAlignment ==
"center-left" )
576 io->Report( aMsg, aSeverity );
585 io->AdvanceProgressPhase();
618 if( s ==
"continuous" )
620 else if( s ==
"longdash" )
622 else if( s ==
"shortdash" )
624 else if( s ==
"dashdot" )
631 else if( s ==
"flat" )
645 for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
647 if( child->GetName() ==
"pinref" )
648 pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
649 else if( child->GetName() ==
"portref" )
650 portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
651 else if( child->GetName() ==
"wire" )
652 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
653 else if( child->GetName() ==
"junction" )
654 junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
655 else if( child->GetName() ==
"label" )
656 labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
657 else if( child->GetName() ==
"probe" )
658 probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
676 for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
678 if( child->GetName() ==
"segment" )
679 segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
751 for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
752 segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
848 text = aDescription->GetNodeContent();
891 else if( stemp ==
"name" )
893 else if( stemp ==
"both" )
1023 text = aText->GetNodeContent();
1047 const wxString& fontName =
font.CGet();
1049 if( fontName ==
"vector" )
1053 else if( fontName ==
"fixed" )
1154 else if( s ==
"round" )
1156 else if( s ==
"octagon" )
1158 else if( s ==
"long" )
1160 else if( s ==
"offset" )
1291 else if( s ==
"cutout" )
1298 for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
1300 if( child->GetName() ==
"vertex" )
1301 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1321 for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
1323 if( child->GetName() ==
"vertex" )
1324 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1363 model = aModel->GetNodeContent();
1403 for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
1405 if( child->GetName() ==
"pinmap" )
1406 pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
1419 pinmapping = std::make_unique<EPINMAPPING>( aSpice );
1421 if( aSpice->GetName() ==
"model" )
1422 model = std::make_unique<EMODEL>( aSpice );
1480 package = wxString::FromUTF8( p.c_str() );
1491 for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
1493 if( child->GetName() ==
"attribute" )
1495 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1496 attributes[ attr->name ] = std::move( attr );
1498 else if( child->GetName() ==
"variant" )
1500 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1501 variants[ variant->name ] = std::move( variant );
1561 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1563 if( child->GetName() ==
"attribute" )
1565 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1566 attributes[ attr->name ] = std::move( attr );
1568 else if( child->GetName() ==
"variant" )
1570 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1571 variants[ variant->name ] = std::move( variant );
1573 else if( child->GetName() ==
"spice" )
1575 spice = std::make_unique<ESPICE>( child, aIo );
1607 for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
1609 if( child->GetName() ==
"attribute" )
1611 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1612 attributes[ attr->name ] = std::move( attr );
1644 if( stemp ==
"must" )
1646 else if( stemp ==
"can" )
1648 else if( stemp ==
"next" )
1650 else if( stemp ==
"request" )
1652 else if( stemp ==
"always" )
1695 for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
1697 if( child->GetName() ==
"attribute" )
1698 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
1734 std::string p( pack->c_str() );
1736 package.Set( wxString::FromUTF8( p.c_str() ) );
1739 for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
1741 if( child->GetName() ==
"connects" )
1743 for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
1745 if( connect->GetName() ==
"connect" )
1746 connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
1751 else if( child->GetName() ==
"packages3dinstances" )
1753 for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
1754 package3dinst = package3dinst->GetNext() )
1756 if( package3dinst->GetName() ==
"package3dinstance" )
1757 package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
1762 else if( child->GetName() ==
"technologies" )
1764 for( wxXmlNode* technology = child->GetChildren(); technology;
1765 technology = technology->GetNext() )
1767 if( technology->GetName() ==
"technology" )
1768 technologies.emplace_back( std::make_unique<ETECHNOLOGY>( technology, aIo ) );
1805 for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
1807 if( child->GetName() ==
"description" )
1809 description = std::make_optional<EDESCRIPTION>( child, aIo );
1811 else if( child->GetName() ==
"gates" )
1813 for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
1815 std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
1816 gates[tmp->name] = std::move( tmp );
1821 else if( child->GetName() ==
"devices" )
1823 for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
1824 devices.emplace_back( std::make_unique<EDEVICE>( device, aIo ) );
1828 else if( child->GetName() ==
"spice" )
1830 spice = std::make_optional<ESPICE>( child, aIo );
1855 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1857 if( child->GetName() ==
"clearance" )
1879 for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
1881 if( child->GetName() ==
"polygon" )
1882 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
1883 else if( child->GetName() ==
"wire" )
1884 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
1885 else if( child->GetName() ==
"text" )
1886 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
1887 else if( child->GetName() ==
"dimension" )
1888 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
1889 else if( child->GetName() ==
"circle" )
1890 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
1891 else if( child->GetName() ==
"spline" )
1892 splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
1893 else if( child->GetName() ==
"rectangle" )
1894 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
1895 else if( child->GetName() ==
"frame" )
1896 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
1897 else if( child->GetName() ==
"hole" )
1898 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
1941 for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
1943 if( child->GetName() ==
"description" )
1945 description = std::make_optional<EDESCRIPTION>( child, aIo );
1947 else if( child->GetName() ==
"plain" )
1949 plain = std::make_unique<EPLAIN>( child, aIo );
1951 else if( child->GetName() ==
"moduleinsts" )
1953 for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
1954 moduleinst = moduleinst->GetNext() )
1956 if( moduleinst->GetName() ==
"moduleinst" )
1958 std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst, aIo );
1959 moduleinsts[ inst->name ] = std::move( inst );
1965 else if( child->GetName() ==
"instances" )
1967 for( wxXmlNode* instance = child->GetChildren(); instance; instance = instance->GetNext() )
1969 if( instance->GetName() ==
"instance" )
1970 instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
1973 AdvanceProgressPhase();
1975 else if( child->GetName() ==
"busses" )
1977 for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
1979 if( bus->GetName() ==
"bus" )
1980 busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
1983 AdvanceProgressPhase();
1985 else if( child->GetName() ==
"nets" )
1987 for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
1989 if( net->GetName() ==
"net" )
1990 nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
1993 AdvanceProgressPhase();
1997 AdvanceProgressPhase();
2028 for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
2030 if( child->GetName() ==
"description" )
2032 description = std::make_optional<EDESCRIPTION>( child, aIo );
2034 else if( child->GetName() ==
"attribute" )
2036 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
2061 for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
2063 if( child->GetName() ==
"description" )
2065 description = std::make_optional<EDESCRIPTION>( child, aIo );
2067 else if( child->GetName() ==
"ports" )
2069 for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
2071 if( port->GetName() ==
"port" )
2073 std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
2074 ports[ tmp->name ] = std::move( tmp );
2080 else if( child->GetName() ==
"variantdefs" )
2082 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2083 variantdef = variantdef->GetNext() )
2085 if( variantdef->GetName() ==
"variantdef" )
2087 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2095 else if( child->GetName() ==
"groups" )
2099 if(
group->GetName() ==
"schematic_group" )
2101 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2102 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2103 groups[ tmp->name ] = std::move( tmp );
2109 else if( child->GetName() ==
"parts" )
2111 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2113 if( part->GetName() ==
"part" )
2115 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2116 parts[ tmp->name ] = std::move( tmp );
2122 else if( child->GetName() ==
"sheets" )
2124 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2126 if( sheet->GetName() ==
"sheet" )
2127 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2190 note = aNote->GetNodeContent();
2202 for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
2204 if( child->GetName() ==
"note" )
2205 notes.emplace_back( std::make_unique<ENOTE>( child ) );
2301 for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
2303 if( child->GetName() ==
"description" )
2305 description = std::make_optional<EDESCRIPTION>( child, aIo );
2307 else if( child->GetName() ==
"polygon" )
2309 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2311 else if( child->GetName() ==
"wire" )
2313 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2315 else if( child->GetName() ==
"text" )
2317 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2319 else if( child->GetName() ==
"dimension" )
2321 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2323 else if( child->GetName() ==
"circle" )
2325 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2327 else if( child->GetName() ==
"rectangle" )
2329 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2331 else if( child->GetName() ==
"frame" )
2333 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2335 else if( child->GetName() ==
"hole" )
2337 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
2339 else if( child->GetName() ==
"pad" )
2341 thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
2343 else if( child->GetName() ==
"smd" )
2345 smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
2388 "library_locally_modified" );
2390 for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
2392 if( child->GetName() ==
"description" )
2394 description = std::make_optional<EDESCRIPTION>( child, aIo );
2396 else if( child->GetName() ==
"packageinstances" )
2398 for( wxXmlNode* instance = child->GetChildren(); instance;
2399 instance = instance->GetNext() )
2400 packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
2434 for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
2436 if( child->GetName() ==
"description" )
2438 description = std::make_optional<EDESCRIPTION>( child, aIo );
2440 else if( child->GetName() ==
"polygon" )
2442 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2444 else if( child->GetName() ==
"wire" )
2446 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2448 else if( child->GetName() ==
"text" )
2450 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2452 else if( child->GetName() ==
"dimension" )
2454 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2456 else if( child->GetName() ==
"pin" )
2458 pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
2460 else if( child->GetName() ==
"circle" )
2462 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2464 else if( child->GetName() ==
"rectangle" )
2466 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2468 else if( child->GetName() ==
"frame" )
2470 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2492 wxString parentNodeName;
2494 if( aLibrary->GetParent() )
2495 parentNodeName = aLibrary->GetParent()->GetName();
2497 if( parentNodeName ==
"libraries" )
2499 name = parseRequiredAttribute<wxString>( aLibrary,
"name" );
2500 urn = parseOptionalAttribute<EURN>( aLibrary,
"urn" );
2503 for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
2505 if( child->GetName() ==
"description" )
2507 description = std::make_optional<EDESCRIPTION>( child, aIo );
2509 else if( child->GetName() ==
"packages" )
2511 for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
2513 if( package->GetName() ==
"package" )
2515 std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
2516 packages[ tmp->name ] = std::move( tmp );
2522 else if( child->GetName() ==
"packages3d" )
2524 for( wxXmlNode* package3d = child->GetChildren(); package3d;
2525 package3d = package3d->GetNext() )
2527 if( package3d->GetName() ==
"package3d" )
2529 std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
2531 packages3d[ tmp->name ] = std::move( tmp );
2535 AdvanceProgressPhase();
2537 else if( child->GetName() ==
"symbols" )
2539 for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
2541 if( symbol->GetName() ==
"symbol" )
2543 std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
2544 symbols[ tmp->name ] = std::move( tmp );
2548 AdvanceProgressPhase();
2550 else if( child->GetName() ==
"devicesets" )
2552 for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
2553 deviceset = deviceset->GetNext() )
2555 if( deviceset->GetName() ==
"deviceset" )
2557 std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
2559 devicesets[ tmp->name ] = std::move( tmp );
2563 AdvanceProgressPhase();
2567 AdvanceProgressPhase();
2573 wxString libName =
name;
2582 if(
urn->IsValid() )
2583 libName += wxS(
"_" ) +
urn->assetId;
2618 for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
2620 if( child->GetName() ==
"description" )
2622 description = std::make_optional<EDESCRIPTION>( child, aIo );
2624 else if( child->GetName() ==
"libraries" )
2628 if(
library->GetName() ==
"library" )
2630 std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>(
library, aIo );
2632 wxString libName = tmp->GetName();
2638 wxString uniqueName;
2639 std::set<wxString> usedNames;
2641 for(
const auto& [setName, setLibrary] :
libraries )
2642 usedNames.emplace( setName );
2644 if( usedNames.find( libName ) != usedNames.end() )
2650 uniqueName.Format( wxS(
"%s_%d" ), libName, i );
2652 }
while( usedNames.find( uniqueName ) != usedNames.end() );
2655 libName = uniqueName;
2658 libraries[ libName ] = std::move( tmp );
2664 else if( child->GetName() ==
"attributes" )
2666 for( wxXmlNode* attribute = child->GetChildren(); attribute;
2667 attribute = attribute->GetNext() )
2669 if( attribute->GetName() ==
"attribute" )
2671 std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
2678 else if( child->GetName() ==
"variantdefs" )
2680 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2681 variantdef = variantdef->GetNext() )
2683 if( variantdef->GetName() ==
"variantdef" )
2685 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2693 else if( child->GetName() ==
"classes" )
2695 for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
2697 if( eclass->GetName() ==
"class" )
2699 std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
2700 classes[ tmp->number ] = std::move( tmp );
2706 else if( child->GetName() ==
"modules" )
2708 for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
2710 if( mod->GetName() ==
"module" )
2712 std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
2713 modules[ tmp->name ] = std::move( tmp );
2719 else if( child->GetName() ==
"groups" )
2723 if(
group->GetName() ==
"schematic_group" )
2725 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2726 std::make_unique<ESCHEMATIC_GROUP>(
group, aIo );
2727 groups[ tmp->name ] = std::move( tmp );
2733 else if( child->GetName() ==
"parts" )
2735 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2737 if( part->GetName() ==
"part" )
2739 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2740 parts[ tmp->name ] = std::move( tmp );
2746 else if( child->GetName() ==
"sheets" )
2748 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2750 if( sheet->GetName() ==
"sheet" )
2751 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2756 else if( child->GetName() ==
"errors" )
2758 for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
2760 if( error->GetName() ==
"approved" )
2761 errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
2778 for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
2780 if( child->GetName() ==
"settings" )
2782 for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
2783 settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
2785 AdvanceProgressPhase();
2787 else if( child->GetName() ==
"grid" )
2789 grid = std::make_optional<EGRID>( child, aIo );
2791 else if( child->GetName() ==
"filters" )
2793 for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
2795 if( filter->GetName() ==
"filter" )
2796 filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
2801 else if( child->GetName() ==
"layers" )
2803 for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
2805 if( layer->GetName() ==
"layer" )
2806 layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
2809 AdvanceProgressPhase();
2811 else if( child->GetName() ==
"schematic" )
2813 schematic = std::make_optional<ESCHEMATIC>( child, aIo );
2815 else if( child->GetName() ==
"library" )
2817 library = std::make_optional<ELIBRARY>( child, aIo );
2823 AdvanceProgressPhase();
2841 for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
2843 if( child->GetName() ==
"compitibility" )
2844 compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
2845 else if( child->GetName() ==
"drawing" )
2846 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