KiCad PCB EDA Suite
altium_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  * Copyright (C) 2019-2020 Thomas Pointhuber <[email protected]>
5  * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #ifndef ALTIUM_PARSER_H
26 #define ALTIUM_PARSER_H
27 
28 #include <map>
29 #include <memory>
30 
31 #include <wx/gdicmn.h>
32 #include <vector>
33 
34 
35 namespace CFB
36 {
37 class CompoundFileReader;
38 struct COMPOUND_FILE_ENTRY;
39 } // namespace CFB
40 
41 // Helper method to find file inside compound file
42 const CFB::COMPOUND_FILE_ENTRY* FindStream(
43  const CFB::CompoundFileReader& aReader, const char* aStreamName );
44 
45 
47 {
48 public:
49  ALTIUM_PARSER( const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
50  ALTIUM_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize );
51  ~ALTIUM_PARSER() = default;
52 
53  template <typename Type>
54  Type Read()
55  {
56  if( GetRemainingBytes() >= sizeof( Type ) )
57  {
58  Type val = *(Type*) ( m_pos );
59  m_pos += sizeof( Type );
60  return val;
61  }
62  else
63  {
64  m_error = true;
65  return 0;
66  }
67  }
68 
69  wxString ReadWxString()
70  {
71  uint8_t len = Read<uint8_t>();
72  if( GetRemainingBytes() >= len )
73  {
74  // TODO: Identify where the actual code page is stored. For now, this default code page
75  // has limited impact, because recent Altium files come with a UTF16 string table
76  wxString val = wxString( m_pos, wxConvISO8859_1, len );
77  m_pos += len;
78  return val;
79  }
80  else
81  {
82  m_error = true;
83  return wxString( "" );
84  }
85  }
86 
87  std::map<uint32_t, wxString> ReadWideStringTable()
88  {
89  std::map<uint32_t, wxString> table;
90  size_t remaining = GetRemainingBytes();
91 
92  while( remaining >= 8 )
93  {
94  uint32_t index = Read<uint32_t>();
95  uint32_t length = Read<uint32_t>();
96  wxString str;
97  remaining -= 8;
98 
99  if( length <= 2 )
100  length = 0; // for empty strings, not even the null bytes are present
101  else
102  {
103  if( length > remaining )
104  break;
105 
106  str = wxString( m_pos, wxMBConvUTF16LE(), length - 2 );
107  }
108 
109  table.emplace( index, str );
110  m_pos += length;
111  remaining -= length;
112  }
113 
114  return table;
115  }
116 
117  std::vector<char> ReadVector( size_t aSize )
118  {
119  if( aSize > GetRemainingBytes() )
120  {
121  m_error = true;
122  return {};
123  }
124  else
125  {
126  std::vector<char> data( m_pos, m_pos + aSize );
127  m_pos += aSize;
128  return data;
129  }
130  }
131 
132  int32_t ReadKicadUnit()
133  {
134  return ConvertToKicadUnit( Read<int32_t>() );
135  }
136 
137  int32_t ReadKicadUnitX()
138  {
139  return ReadKicadUnit();
140  }
141 
142  int32_t ReadKicadUnitY()
143  {
144  return -ReadKicadUnit();
145  }
146 
147  wxPoint ReadWxPoint()
148  {
149  int32_t x = ReadKicadUnitX();
150  int32_t y = ReadKicadUnitY();
151  return { x, y };
152  }
153 
154  wxSize ReadWxSize()
155  {
156  int32_t x = ReadKicadUnit();
157  int32_t y = ReadKicadUnit();
158  return { x, y };
159  }
160 
162  {
163  uint32_t length = Read<uint32_t>();
164  m_subrecord_end = m_pos + length;
165  return length;
166  }
167 
168  std::map<wxString, wxString> ReadProperties();
169 
170  static int32_t ConvertToKicadUnit( const double aValue );
171 
172  static int ReadInt( const std::map<wxString, wxString>& aProps,
173  const wxString& aKey, int aDefault );
174 
175  static double ReadDouble( const std::map<wxString, wxString>& aProps,
176  const wxString& aKey, double aDefault );
177 
178  static bool ReadBool( const std::map<wxString, wxString>& aProps,
179  const wxString& aKey, bool aDefault );
180 
181  static int32_t ReadKicadUnit( const std::map<wxString, wxString>& aProps,
182  const wxString& aKey, const wxString& aDefault );
183 
184  static wxString ReadString( const std::map<wxString, wxString>& aProps,
185  const wxString& aKey, const wxString& aDefault );
186 
187  void Skip( size_t aLength )
188  {
189  if( GetRemainingBytes() >= aLength )
190  {
191  m_pos += aLength;
192  }
193  else
194  {
195  m_error = true;
196  }
197  }
198 
200  {
201  if( m_subrecord_end == nullptr || m_subrecord_end < m_pos )
202  {
203  m_error = true;
204  }
205  else
206  {
208  }
209  };
210 
211  size_t GetRemainingBytes() const
212  {
213  return m_pos == nullptr ? 0 : m_size - ( m_pos - m_content.get() );
214  }
215 
217  {
218  return m_pos == nullptr || m_subrecord_end == nullptr || m_subrecord_end <= m_pos ?
219  0 :
221  };
222 
224  {
225  return m_error;
226  }
227 
228 private:
229  std::unique_ptr<char[]> m_content;
230  size_t m_size;
231 
232  char* m_pos; // current read pointer
233  char* m_subrecord_end; // pointer which points to next subrecord start
234  bool m_error;
235 };
236 
237 
238 #endif //ALTIUM_PARSER_H
~ALTIUM_PARSER()=default
char * m_subrecord_end
size_t GetRemainingBytes() const
std::map< uint32_t, wxString > ReadWideStringTable()
Definition: altium_parser.h:87
void Skip(size_t aLength)
static double ReadDouble(const std::map< wxString, wxString > &aProps, const wxString &aKey, double aDefault)
size_t GetRemainingSubrecordBytes() const
wxSize ReadWxSize()
std::vector< char > ReadVector(size_t aSize)
size_t ReadAndSetSubrecordLength()
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
std::map< wxString, wxString > ReadProperties()
wxPoint ReadWxPoint()
static bool ReadBool(const std::map< wxString, wxString > &aProps, const wxString &aKey, bool aDefault)
int32_t ReadKicadUnit()
ALTIUM_PARSER(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
wxString ReadWxString()
Definition: altium_parser.h:69
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
int32_t ReadKicadUnitX()
void SkipSubrecord()
const CFB::COMPOUND_FILE_ENTRY * FindStream(const CFB::CompoundFileReader &aReader, const char *aStreamName)
int32_t ReadKicadUnitY()
std::unique_ptr< char[]> m_content
bool HasParsingError()
static int32_t ConvertToKicadUnit(const double aValue)