42 wxString ret( aNetName );
44 ret.Replace( wxT(
"!" ), wxT(
"~" ) );
64 constexpr
int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
65 constexpr
unsigned int DIVIDERS_MAX_IDX =
sizeof( DIVIDERS ) /
sizeof( DIVIDERS[0] ) - 1;
67 int integer, fraction, pre_fraction, post_fraction;
71 bool negative = ( aValue[0] ==
'-' );
75 int ret = sscanf( aValue.c_str(),
"%d.%n%d%n", &integer, &pre_fraction, &fraction,
87 int digits = post_fraction - pre_fraction;
91 if( (
unsigned) digits > DIVIDERS_MAX_IDX )
93 int diff = digits - DIVIDERS_MAX_IDX;
94 digits = DIVIDERS_MAX_IDX;
95 fraction /= DIVIDERS[diff];
98 int frac_value =
ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
113 case EU_NM: ret = aValue;
break;
114 case EU_MM: ret = (
long long) aValue * 1000000;
break;
115 case EU_INCH: ret = (
long long) aValue * 25400000;
break;
116 case EU_MIL: ret = (
long long) aValue * 25400;
break;
119 if( ( ret > 0 ) != ( aValue > 0 ) )
120 wxLogError(
_(
"Invalid size %lld: too large" ), aValue );
143 std::string Convert<std::string>(
const wxString& aValue )
145 return std::string( aValue.ToUTF8() );
154 if( aValue.ToCDouble( &value ) )
158 aValue.ToStdString() +
"'." );
165 if( aValue.IsEmpty() )
166 throw XML_PARSER_ERROR(
"Conversion to int failed. Original value is empty." );
168 return wxAtoi( aValue );
175 if( aValue != wxT(
"yes" ) && aValue != wxT(
"no" ) )
177 aValue.ToStdString() +
178 "', is neither 'yes' nor 'no'." );
180 return aValue == wxT(
"yes" );
191 value.
spin = aRot.find(
'S' ) != aRot.npos;
192 value.
mirror = aRot.find(
'M' ) != aRot.npos;
193 value.
degrees = strtod( aRot.c_str()
207 return ECOORD( aCoord, ECOORD::EAGLE_UNIT::EU_MM );
224 if( aNode->GetAttribute( aAttribute, &value ) )
225 return Convert<T>( value );
227 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing." );
253 aCurrentNode = aCurrentNode->GetChildren();
255 while( aCurrentNode )
260 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
263 aCurrentNode = aCurrentNode->GetNext();
274 double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
275 wxPoint mid = ( aStart + aEnd ) / 2;
277 double dlen = sqrt( dx*dx + dy*dy );
279 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
286 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
289 mid.x + dist * ( dy / dlen ),
290 mid.y - dist * ( dx / dlen )
301 if( aAlignment == wxT(
"center" ) )
303 else if( aAlignment == wxT(
"center-right" ) )
305 else if( aAlignment == wxT(
"top-left" ) )
307 else if( aAlignment == wxT(
"top-center" ) )
309 else if( aAlignment == wxT(
"top-right" ) )
311 else if( aAlignment == wxT(
"bottom-left" ) )
313 else if( aAlignment == wxT(
"bottom-center" ) )
315 else if( aAlignment == wxT(
"bottom-right" ) )
317 else if( aAlignment == wxT(
"center-left" ) )
342 x1 = parseRequiredAttribute<ECOORD>( aWire, wxT(
"x1" ) );
343 y1 = parseRequiredAttribute<ECOORD>( aWire, wxT(
"y1" ) );
344 x2 = parseRequiredAttribute<ECOORD>( aWire, wxT(
"x2" ) );
345 y2 = parseRequiredAttribute<ECOORD>( aWire, wxT(
"y2" ) );
346 width = parseRequiredAttribute<ECOORD>( aWire, wxT(
"width" ) );
347 layer = parseRequiredAttribute<int>( aWire, wxT(
"layer" ) );
348 curve = parseOptionalAttribute<double>( aWire, wxT(
"curve" ) );
350 opt_wxString s = parseOptionalAttribute<wxString>( aWire, wxT(
"style" ) );
352 if( s == wxT(
"continuous" ) )
354 else if( s == wxT(
"longdash" ) )
356 else if( s == wxT(
"shortdash" ) )
358 else if( s == wxT(
"dashdot" ) )
361 s = parseOptionalAttribute<wxString>( aWire, wxT(
"cap" ) );
363 if( s == wxT(
"round" ) )
365 else if( s == wxT(
"flat" ) )
380 x = parseRequiredAttribute<ECOORD>( aJunction, wxT(
"x" ) );
381 y = parseRequiredAttribute<ECOORD>( aJunction, wxT(
"y" ) );
401 x = parseRequiredAttribute<ECOORD>( aLabel, wxT(
"x" ) );
402 y = parseRequiredAttribute<ECOORD>( aLabel, wxT(
"y" ) );
403 size = parseRequiredAttribute<ECOORD>( aLabel, wxT(
"size" ) );
404 layer = parseRequiredAttribute<int>( aLabel, wxT(
"layer" ) );
405 rot = parseOptionalAttribute<EROT>( aLabel, wxT(
"rot" ) );
406 xref = parseOptionalAttribute<wxString>( aLabel, wxT(
"xref" ) );
426 x = parseRequiredAttribute<ECOORD>( aVia, wxT(
"x" ) );
427 y = parseRequiredAttribute<ECOORD>( aVia, wxT(
"y" ) );
429 wxString ext = parseRequiredAttribute<wxString>( aVia, wxT(
"extent" ) );
432 drill = parseRequiredAttribute<ECOORD>( aVia, wxT(
"drill" ) );
433 diam = parseOptionalAttribute<ECOORD>( aVia, wxT(
"diameter" ) );
434 shape = parseOptionalAttribute<wxString>( aVia, wxT(
"shape" ) );
451 x = parseRequiredAttribute<ECOORD>( aCircle, wxT(
"x" ) );
452 y = parseRequiredAttribute<ECOORD>( aCircle, wxT(
"y" ) );
453 radius = parseRequiredAttribute<ECOORD>( aCircle, wxT(
"radius" ) );
454 width = parseRequiredAttribute<ECOORD>( aCircle, wxT(
"width" ) );
455 layer = parseRequiredAttribute<int>( aCircle, wxT(
"layer" ) );
473 x1 = parseRequiredAttribute<ECOORD>( aRect, wxT(
"x1" ) );
474 y1 = parseRequiredAttribute<ECOORD>( aRect, wxT(
"y1" ) );
475 x2 = parseRequiredAttribute<ECOORD>( aRect, wxT(
"x2" ) );
476 y2 = parseRequiredAttribute<ECOORD>( aRect, wxT(
"y2" ) );
477 layer = parseRequiredAttribute<int>( aRect, wxT(
"layer" ) );
478 rot = parseOptionalAttribute<EROT>( aRect, wxT(
"rot" ) );
501 name = parseRequiredAttribute<wxString>( aTree, wxT(
"name" ) );
502 value = parseOptionalAttribute<wxString>( aTree, wxT(
"value" ) );
504 x = parseOptionalAttribute<ECOORD>( aTree, wxT(
"x" ) );
505 y = parseOptionalAttribute<ECOORD>( aTree, wxT(
"y" ) );
506 size = parseOptionalAttribute<ECOORD>( aTree, wxT(
"size" ) );
508 layer = parseOptionalAttribute<int>( aTree, wxT(
"layer" ) );
509 ratio = parseOptionalAttribute<double>( aTree, wxT(
"ratio" ) );
510 rot = parseOptionalAttribute<EROT>( aTree, wxT(
"rot" ) );
512 opt_wxString stemp = parseOptionalAttribute<wxString>( aTree, wxT(
"display" ) );
515 if( stemp == wxT(
"off" ) )
517 else if( stemp == wxT(
"name" ) )
519 else if( stemp == wxT(
"both" ) )
524 stemp = parseOptionalAttribute<wxString>( aTree, wxT(
"align" ) );
547 x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x1" ) );
548 y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y1" ) );
549 x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x2" ) );
550 y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y2" ) );
551 x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x3" ) );
552 y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y3" ) );
553 textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT(
"textsize" ) );
554 layer = parseRequiredAttribute<int>( aDimension, wxT(
"layer" ) );
555 dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT(
"dtype" ) );
575 text = aText->GetNodeContent();
576 x = parseRequiredAttribute<ECOORD>( aText, wxT(
"x" ) );
577 y = parseRequiredAttribute<ECOORD>( aText, wxT(
"y" ) );
578 size = parseRequiredAttribute<ECOORD>( aText, wxT(
"size" ) );
579 layer = parseRequiredAttribute<int>( aText, wxT(
"layer" ) );
581 font = parseOptionalAttribute<wxString>( aText, wxT(
"font" ) );
582 ratio = parseOptionalAttribute<double>( aText, wxT(
"ratio" ) );
583 rot = parseOptionalAttribute<EROT>( aText, wxT(
"rot" ) );
585 opt_wxString stemp = parseOptionalAttribute<wxString>( aText, wxT(
"align" ) );
597 const wxString& fontName =
font.
CGet();
599 if( fontName == wxT(
"vector" ) )
603 else if( fontName == wxT(
"fixed" ) )
644 x1 = parseRequiredAttribute<ECOORD>( aFrameNode, wxT(
"x1" ) );
645 y1 = parseRequiredAttribute<ECOORD>( aFrameNode, wxT(
"y1" ) );
646 x2 = parseRequiredAttribute<ECOORD>( aFrameNode, wxT(
"x2" ) );
647 y2 = parseRequiredAttribute<ECOORD>( aFrameNode, wxT(
"y2" ) );
648 columns = parseRequiredAttribute<int>( aFrameNode, wxT(
"columns" ) );
649 rows = parseRequiredAttribute<int>( aFrameNode, wxT(
"rows" ) );
650 layer = parseRequiredAttribute<int>( aFrameNode, wxT(
"layer" ) );
651 border_left = parseOptionalAttribute<bool>( aFrameNode, wxT(
"border-left" ) );
652 border_top = parseOptionalAttribute<bool>( aFrameNode, wxT(
"border-top" ) );
653 border_right = parseOptionalAttribute<bool>( aFrameNode, wxT(
"border-right" ) );
654 border_bottom = parseOptionalAttribute<bool>( aFrameNode, wxT(
"border-bottom" ) );
661 name = parseRequiredAttribute<wxString>( aPad, wxT(
"name" ) );
662 x = parseRequiredAttribute<ECOORD>( aPad, wxT(
"x" ) );
663 y = parseRequiredAttribute<ECOORD>( aPad, wxT(
"y" ) );
664 rot = parseOptionalAttribute<EROT>( aPad, wxT(
"rot" ) );
665 stop = parseOptionalAttribute<bool>( aPad, wxT(
"stop" ) );
666 thermals = parseOptionalAttribute<bool>( aPad, wxT(
"thermals" ) );
690 drill = parseRequiredAttribute<ECOORD>( aPad, wxT(
"drill" ) );
693 diameter = parseOptionalAttribute<ECOORD>( aPad, wxT(
"diameter" ) );
695 opt_wxString s = parseOptionalAttribute<wxString>( aPad, wxT(
"shape" ) );
698 if( s == wxT(
"square" ) )
700 else if( s == wxT(
"round" ) )
702 else if( s == wxT(
"octagon" ) )
704 else if( s == wxT(
"long" ) )
706 else if( s == wxT(
"offset" ) )
709 first = parseOptionalAttribute<bool>( aPad, wxT(
"first" ) );
733 dx = parseRequiredAttribute<ECOORD>( aSMD, wxT(
"dx" ) );
734 dy = parseRequiredAttribute<ECOORD>( aSMD, wxT(
"dy" ) );
735 layer = parseRequiredAttribute<int>( aSMD, wxT(
"layer" ) );
737 roundness = parseOptionalAttribute<int>( aSMD, wxT(
"roundness" ) );
738 cream = parseOptionalAttribute<bool>( aSMD, wxT(
"cream" ) );
760 name = parseRequiredAttribute<wxString>( aPin, wxT(
"name" ) );
761 x = parseRequiredAttribute<ECOORD>( aPin, wxT(
"x" ) );
762 y = parseRequiredAttribute<ECOORD>( aPin, wxT(
"y" ) );
764 visible = parseOptionalAttribute<wxString>( aPin, wxT(
"visible" ) );
765 length = parseOptionalAttribute<wxString>( aPin, wxT(
"length" ) );
766 direction = parseOptionalAttribute<wxString>( aPin, wxT(
"direction" ) );
767 function = parseOptionalAttribute<wxString>( aPin, wxT(
"function" ) );
768 swaplevel = parseOptionalAttribute<int>( aPin, wxT(
"swaplevel" ) );
769 rot = parseOptionalAttribute<EROT>( aPin, wxT(
"rot" ) );
784 x = parseRequiredAttribute<ECOORD>( aVertex, wxT(
"x" ) );
785 y = parseRequiredAttribute<ECOORD>( aVertex, wxT(
"y" ) );
786 curve = parseOptionalAttribute<double>( aVertex, wxT(
"curve" ) );
806 width = parseRequiredAttribute<ECOORD>( aPolygon, wxT(
"width" ) );
807 layer = parseRequiredAttribute<int>( aPolygon, wxT(
"layer" ) );
809 spacing = parseOptionalAttribute<ECOORD>( aPolygon, wxT(
"spacing" ) );
810 isolate = parseOptionalAttribute<ECOORD>( aPolygon, wxT(
"isolate" ) );
811 opt_wxString s = parseOptionalAttribute<wxString>( aPolygon, wxT(
"pour" ) );
817 if( s == wxT(
"hatch" ) )
819 else if( s == wxT(
"cutout" ) )
822 orphans = parseOptionalAttribute<bool>( aPolygon, wxT(
"orphans" ) );
823 thermals = parseOptionalAttribute<bool>( aPolygon, wxT(
"thermals" ) );
824 rank = parseOptionalAttribute<int>( aPolygon, wxT(
"rank" ) );
840 x = parseRequiredAttribute<ECOORD>( aHole, wxT(
"x" ) );
841 y = parseRequiredAttribute<ECOORD>( aHole, wxT(
"y" ) );
842 drill = parseRequiredAttribute<ECOORD>( aHole, wxT(
"drill" ) );
864 name = parseRequiredAttribute<wxString>( aElement, wxT(
"name" ) );
865 library = parseRequiredAttribute<wxString>( aElement, wxT(
"library" ) );
866 value = parseRequiredAttribute<wxString>( aElement, wxT(
"value" ) );
867 std::string p = parseRequiredAttribute<std::string>( aElement, wxT(
"package" ) );
869 package = wxString::FromUTF8( p.c_str() );
871 x = parseRequiredAttribute<ECOORD>( aElement, wxT(
"x" ) );
872 y = parseRequiredAttribute<ECOORD>( aElement, wxT(
"y" ) );
875 locked = parseOptionalAttribute<bool>( aElement, wxT(
"locked" ) );
876 smashed = parseOptionalAttribute<bool>( aElement, wxT(
"smashed" ) );
877 rot = parseOptionalAttribute<EROT>( aElement, wxT(
"rot" ) );
895 number = parseRequiredAttribute<int>( aLayer, wxT(
"number" ) );
896 name = parseRequiredAttribute<wxString>( aLayer, wxT(
"name" ) );
897 color = parseRequiredAttribute<int>( aLayer, wxT(
"color" ) );
899 visible = parseOptionalAttribute<bool>( aLayer, wxT(
"visible" ) );
900 active = parseOptionalAttribute<bool>( aLayer, wxT(
"active" ) );
918 name = parseRequiredAttribute<wxString>( aPart, wxT(
"name" ) );
919 library = parseRequiredAttribute<wxString>( aPart, wxT(
"library" ) );
920 deviceset = parseRequiredAttribute<wxString>( aPart, wxT(
"deviceset" ) );
921 device = parseRequiredAttribute<wxString>( aPart, wxT(
"device" ) );
922 technology = parseOptionalAttribute<wxString>( aPart, wxT(
"technology" ) );
923 value = parseOptionalAttribute<wxString>( aPart, wxT(
"value" ) );
925 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
927 if( child->GetName() == wxT(
"attribute" ) )
929 std::string aname, avalue;
931 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
933 if(
x->GetName() == wxT(
"name" ) )
934 aname =
x->GetValue();
935 else if(
x->GetName() == wxT(
"value" ) )
936 avalue =
x->GetValue();
939 if( aname.size() && avalue.size() )
940 attribute[aname] = avalue;
942 else if( child->GetName() == wxT(
"variant" ) )
944 std::string aname, avalue;
946 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
948 if(
x->GetName() == wxT(
"name" ) )
949 aname =
x->GetValue();
950 else if(
x->GetName() == wxT(
"value" ) )
951 avalue =
x->GetValue();
954 if( aname.size() && avalue.size() )
955 variant[aname] = avalue;
974 part = parseRequiredAttribute<wxString>( aInstance, wxT(
"part" ) );
975 gate = parseRequiredAttribute<wxString>( aInstance, wxT(
"gate" ) );
977 x = parseRequiredAttribute<ECOORD>( aInstance, wxT(
"x" ) );
978 y = parseRequiredAttribute<ECOORD>( aInstance, wxT(
"y" ) );
981 smashed = parseOptionalAttribute<bool>( aInstance, wxT(
"smashed" ) );
982 rot = parseOptionalAttribute<EROT>( aInstance, wxT(
"rot" ) );
1000 name = parseRequiredAttribute<wxString>( aGate, wxT(
"name" ) );
1001 symbol = parseRequiredAttribute<wxString>( aGate, wxT(
"symbol" ) );
1003 x = parseRequiredAttribute<ECOORD>( aGate, wxT(
"x" ) );
1004 y = parseRequiredAttribute<ECOORD>( aGate, wxT(
"y" ) );
1006 opt_wxString stemp = parseOptionalAttribute<wxString>( aGate, wxT(
"addlevel" ) );
1009 if( stemp == wxT(
"must" ) )
1011 else if( stemp == wxT(
"can" ) )
1013 else if( stemp == wxT(
"next" ) )
1015 else if( stemp == wxT(
"request" ) )
1017 else if( stemp == wxT(
"always" ) )
1035 gate = parseRequiredAttribute<wxString>( aConnect, wxT(
"gate" ) );
1036 pin = parseRequiredAttribute<wxString>( aConnect, wxT(
"pin" ) );
1037 pad = parseRequiredAttribute<wxString>( aConnect, wxT(
"pad" ) );
1050 name = parseRequiredAttribute<wxString>( aDevice, wxT(
"name" ) );
1051 opt_wxString pack = parseOptionalAttribute<wxString>( aDevice, wxT(
"package" ) );
1055 std::string p( pack->c_str() );
1057 package.Set( wxString::FromUTF8( p.c_str() ) );
1061 wxXmlNode* connectNode =
getChildrenNodes( aDeviceChildren, wxT(
"connects" ) );
1063 while( connectNode )
1065 connects.emplace_back( connectNode );
1066 connectNode = connectNode->GetNext();
1082 name = parseRequiredAttribute<wxString>( aDeviceSet, wxT(
"name" ) );
1083 prefix = parseOptionalAttribute<wxString>( aDeviceSet, wxT(
"prefix" ) );
1084 uservalue = parseOptionalAttribute<bool>( aDeviceSet, wxT(
"uservalue" ) );
1111 number = parseRequiredAttribute<wxString>( aClass, wxT(
"number" ) );
1112 name = parseRequiredAttribute<wxString>( aClass, wxT(
"name" ) );
1114 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1116 if( child->GetName() == wxT(
"clearance" ) )
1118 wxString to = parseRequiredAttribute<wxString>( child, wxT(
"class" ) );
1119 ECOORD value = parseRequiredAttribute<ECOORD>( child, wxT(
"value" ) );
1121 clearanceMap[to] =
value;
void Set(const wxString &aString)
Attempt to convert a string to the base type.
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
ECOORD Convert< ECOORD >(const wxString &aCoord)
opt_double curve
range is -359.9..359.9
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
ECLASS(wxXmlNode *aClass)
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
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.
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
ELAYER(wxXmlNode *aLayer)
EDEVICE(wxXmlNode *aDevice)
int layer_back_most
< extent
ECONNECT(wxXmlNode *aConnect)
EVERTEX(wxXmlNode *aVertex)
EJUNCTION(wxXmlNode *aJunction)
wxString escapeName(const wxString &aNetName)
wxString Convert< wxString >(const wxString &aValue)
EDIMENSION(wxXmlNode *aDimension)
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
ELABEL(wxXmlNode *aLabel, const wxString &aNetName)
EPOLYGON(wxXmlNode *aPolygon)
bool m_isAvailable
A boolean indicating if the data is present or not.
wxSize ConvertSize() const
Calculate text size based on font type and size.
Model an optional XML attribute.
EDEVICE_SET(wxXmlNode *aDeviceSet)
static int parseAlignment(const wxString &aAlignment)
opt_double curve
range is -359.9..359.9
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
int Convert< int >(const wxString &aValue)
OPTIONAL_XML_ATTRIBUTE< T > parseOptionalAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse option aAttribute of the XML node aNode.
opt_wxString dimensionType
EPAD_COMMON(wxXmlNode *aPad)
constexpr auto DEFAULT_ALIGNMENT
double DEG2RAD(double deg)
Structure holding common properties for through-hole and SMD pads.
wxPoint ConvertArcCenter(const wxPoint &aStart, const wxPoint &aEnd, double aAngle)
EFRAME(wxXmlNode *aFrameNode)
double Convert< double >(const wxString &aValue)
ECIRCLE(wxXmlNode *aCircle)
#define THROW_IO_ERROR(msg)
EELEMENT(wxXmlNode *aElement)
static long long int ConvertToNm(int aValue, enum EAGLE_UNIT aUnit)
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
long long int value
Unit used for the value field.
static wxXmlNode * getChildrenNodes(NODE_MAP &aMap, const wxString &aName)
EINSTANCE(wxXmlNode *aInstance)
bool Convert< bool >(const wxString &aValue)