KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eagle_bin_parser.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Binary Eagle parsing logic and the eagle_script[] format table ported from
5 * pcb-rnd src_plugins/io_eagle (eagle_bin.c) by Tibor 'Igor2' Palinkas and
6 * Erich S. Heinzle.
7 *
8 * COPYRIGHT (pcb-rnd, eagle_bin.c / eagle_bin.h)
9 *
10 * pcb-rnd, interactive printed circuit board design
11 * Copyright (C) 2017 Tibor 'Igor2' Palinkas
12 * Copyright (C) 2017 Erich S. Heinzle
13 *
14 * Copyright (C) 2026 KiCad Developers, see AUTHORS.txt for contributors.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, you may find one here:
28 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
29 * or you may search the http://www.gnu.org website for the version 2 license,
30 * or you may write to the Free Software Foundation, Inc.,
31 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
32 */
33
34#ifndef EAGLE_BIN_PARSER_H_
35#define EAGLE_BIN_PARSER_H_
36
37#include <cstdint>
38#include <map>
39#include <memory>
40#include <vector>
41
42#include <wx/string.h>
43
44class wxXmlDocument;
45class wxXmlNode;
46class wxInputStream;
47
63{
64public:
70 static bool IsBinaryEagle( wxInputStream& aStream );
71
74
81 std::unique_ptr<wxXmlDocument> Parse( const std::vector<uint8_t>& aBytes );
82
83private:
85 struct EGB_NODE
86 {
87 int id = 0;
88 wxString name;
89 std::map<wxString, wxString> props;
90 std::vector<std::unique_ptr<EGB_NODE>> children;
91 EGB_NODE* parent = nullptr;
92
93 EGB_NODE* AddChild( int aId, const wxString& aName );
94 bool HasProp( const wxString& aKey ) const { return props.count( aKey ) != 0; }
95 wxString Prop( const wxString& aKey ) const;
96 long PropLong( const wxString& aKey ) const;
97
100 wxString PropDoubled( const wxString& aKey ) const;
101 EGB_NODE* FindChildById( int aId ) const;
102 EGB_NODE* FindChildByName( const wxString& aName ) const;
103 };
104
106 struct DRC_CTX
107 {
108 long mdWireWire = 12;
109 long msWidth = 10;
110 double rvPadTop = 0.25;
111 double rvPadInner = 0.25;
112 double rvPadBottom = 0.25;
113 };
114
115 // Recursive descent over the 24-byte block stream.
116 int readBlock( long& aNumBlocks, EGB_NODE* aParent );
117
118 // Trailing optional sections (v4/v5 only).
119 bool readNotes();
120 bool readDrc( DRC_CTX& aDrc );
121
122 const wxString& nextLongText();
123
124 // Post-processing passes that rewrite the intermediate tree to match the XML schema.
125 void postProcess( EGB_NODE* aRoot, const DRC_CTX& aDrc );
126 void postprocLayers( EGB_NODE* aDrawing, EGB_NODE* aLayers );
127 void postprocDrc( EGB_NODE* aDrcNode, const DRC_CTX& aDrc );
128 void postprocLibs( EGB_NODE* aLibraries );
129 void postprocElements( EGB_NODE* aElements );
130 void postprocNames( EGB_NODE* aLibraries, EGB_NODE* aElements );
131 void postprocSignals( EGB_NODE* aSignals );
132 void postprocContactRefs( EGB_NODE* aSignals, EGB_NODE* aElements, EGB_NODE* aLibraries );
133 void postprocWires( EGB_NODE* aRoot );
134 void postprocArcs( EGB_NODE* aRoot );
135 void postprocVias( EGB_NODE* aRoot );
136 void postprocUnits( EGB_NODE* aRoot );
137 void postprocCircles( EGB_NODE* aRoot );
138 void postprocSmd( EGB_NODE* aRoot );
139 void postprocDimensions( EGB_NODE* aRoot );
140 void postprocFreeText( EGB_NODE* aRoot );
141 void postprocRotation( EGB_NODE* aRoot );
142 bool isRotatable( int aId ) const;
143
144 void arcDecode( EGB_NODE* aElem, int aArcType, int aLineType );
145 void fixLongText( EGB_NODE* aNode, const wxString& aField );
146
147 // Convert the finished intermediate tree into wxXmlNode form.
148 wxXmlNode* toXml( const EGB_NODE* aNode ) const;
149
150 // Throw IO_ERROR unless [aOffs, aOffs + aLen) lies within m_buf.
151 void requireBytes( size_t aOffs, size_t aLen ) const;
152
153 // Little-endian field extractors over m_buf.
154 uint32_t loadU32( size_t aOffs, unsigned aLen ) const;
155 int32_t loadS32( size_t aOffs, unsigned aLen ) const;
156 bool loadBmb( size_t aOffs, uint32_t aMask ) const;
157 uint32_t loadUbf( size_t aOffs, uint32_t aField ) const;
158 wxString loadStr( size_t aOffs, unsigned aLen ) const;
159 double loadDouble( size_t aOffs ) const;
160
161 const std::vector<uint8_t>* m_buf = nullptr;
162 size_t m_pos = 0;
163
164 std::unique_ptr<EGB_NODE> m_root;
165
166 std::vector<wxString> m_freeText;
168 wxString m_invalidText;
169};
170
171#endif // EAGLE_BIN_PARSER_H_
wxXmlNode * toXml(const EGB_NODE *aNode) const
void postprocSignals(EGB_NODE *aSignals)
std::unique_ptr< wxXmlDocument > Parse(const std::vector< uint8_t > &aBytes)
Parse a binary Eagle board into an XML DOM compatible with the XML walker.
void requireBytes(size_t aOffs, size_t aLen) const
uint32_t loadUbf(size_t aOffs, uint32_t aField) const
void postprocCircles(EGB_NODE *aRoot)
bool readDrc(DRC_CTX &aDrc)
void postprocFreeText(EGB_NODE *aRoot)
bool isRotatable(int aId) const
void postprocLibs(EGB_NODE *aLibraries)
const wxString & nextLongText()
uint32_t loadU32(size_t aOffs, unsigned aLen) const
size_t m_pos
current read cursor
void postprocUnits(EGB_NODE *aRoot)
void postprocArcs(EGB_NODE *aRoot)
wxString loadStr(size_t aOffs, unsigned aLen) const
void fixLongText(EGB_NODE *aNode, const wxString &aField)
void postProcess(EGB_NODE *aRoot, const DRC_CTX &aDrc)
int readBlock(long &aNumBlocks, EGB_NODE *aParent)
void postprocSmd(EGB_NODE *aRoot)
const std::vector< uint8_t > * m_buf
file contents, not owned
void postprocContactRefs(EGB_NODE *aSignals, EGB_NODE *aElements, EGB_NODE *aLibraries)
void postprocWires(EGB_NODE *aRoot)
std::vector< wxString > m_freeText
NUL-delimited notes strings.
void postprocLayers(EGB_NODE *aDrawing, EGB_NODE *aLayers)
bool loadBmb(size_t aOffs, uint32_t aMask) const
void postprocRotation(EGB_NODE *aRoot)
void arcDecode(EGB_NODE *aElem, int aArcType, int aLineType)
double loadDouble(size_t aOffs) const
static bool IsBinaryEagle(wxInputStream &aStream)
Probe the first two bytes for the binary magic.
void postprocDimensions(EGB_NODE *aRoot)
std::unique_ptr< EGB_NODE > m_root
wxString m_invalidText
returned when out of strings
void postprocDrc(EGB_NODE *aDrcNode, const DRC_CTX &aDrc)
void postprocVias(EGB_NODE *aRoot)
void postprocNames(EGB_NODE *aLibraries, EGB_NODE *aElements)
void postprocElements(EGB_NODE *aElements)
int32_t loadS32(size_t aOffs, unsigned aLen) const
DRC values pulled from the trailing 244-byte block (or sane defaults).
Lightweight mutable tree node for the intermediate Eagle binary tree.
std::map< wxString, wxString > props
long PropLong(const wxString &aKey) const
std::vector< std::unique_ptr< EGB_NODE > > children
EGB_NODE * FindChildById(int aId) const
bool HasProp(const wxString &aKey) const
EGB_NODE * AddChild(int aId, const wxString &aName)
wxString PropDoubled(const wxString &aKey) const
Format a property doubled in 64-bit so the half-to-full widening cannot overflow a 32-bit long.
wxString Prop(const wxString &aKey) const
EGB_NODE * FindChildByName(const wxString &aName) const