28#include <compoundfilereader.h>
36#include <wx/translation.h>
40std::string
FormatPath(
const std::vector<std::string>& aVectorPath )
42 return std::accumulate( aVectorPath.cbegin(), aVectorPath.cend(), std::string(),
43 [](
const std::string& ss,
const std::string& s )
45 return ss.empty() ? s : ss +
'\\' + s;
53 FILE* fp = wxFopen( aFilePath,
"rb" );
57 THROW_IO_ERROR( wxString::Format(
_(
"Cannot open file '%s'." ), aFilePath ) );
60 fseek( fp, 0, SEEK_END );
61 long len = ftell( fp );
72 fseek( fp, 0, SEEK_SET );
74 size_t bytesRead = fread(
m_buffer.data(),
sizeof(
unsigned char ), len, fp );
77 if(
static_cast<size_t>( len ) != bytesRead )
86 catch( CFB::CFBException& exception )
96 memcpy(
m_buffer.data(), aBuffer, aLen );
102 catch( CFB::CFBException& exception )
109std::unique_ptr<ALTIUM_COMPOUND_FILE>
112 wxCHECK( cfe.size >= 1,
nullptr );
114 size_t streamSize = cfe.size;
115 wxMemoryBuffer buffer( streamSize );
116 buffer.SetDataLen( streamSize );
123 if( buffer[0] == 0x02 )
125 wxMemoryInputStream memoryInputStream( buffer.GetData(), streamSize );
126 memoryInputStream.SeekI( 1, wxFromStart );
128 wxZlibInputStream zlibInputStream( memoryInputStream );
129 wxMemoryOutputStream decodedPcbLibStream;
130 decodedPcbLibStream << zlibInputStream;
132 wxStreamBuffer* outStream = decodedPcbLibStream.GetOutputStreamBuffer();
134 return std::make_unique<ALTIUM_COMPOUND_FILE>( outStream->GetBufferStart(),
135 outStream->GetIntPosition() );
137 else if( buffer[0] == 0x00 )
139 return std::make_unique<ALTIUM_COMPOUND_FILE>(
140 reinterpret_cast<uint8_t*
>( buffer.GetData() ) + 1, streamSize - 1 );
144 wxFAIL_MSG( wxString::Format(
"Altium IntLib unknown header: %02x %02x %02x %02x %02x",
145 buffer[0], buffer[1], buffer[2], buffer[3], buffer[4] ) );
152const CFB::COMPOUND_FILE_ENTRY*
154 const std::string aName,
const bool aIsStream )
const
159 const CFB::COMPOUND_FILE_ENTRY* ret =
nullptr;
162 [&](
const CFB::COMPOUND_FILE_ENTRY* entry,
const CFB::utf16string& dir,
168 if(
m_reader->IsStream( entry ) == aIsStream )
170 std::string name = UTF16ToUTF8( entry->name );
171 if( name == aName.c_str() )
184std::map<wxString, ALTIUM_SYMBOL_DATA>
187 const CFB::COMPOUND_FILE_ENTRY* root = aStart ? aStart :
m_reader->GetRootEntry();
192 std::map<wxString, ALTIUM_SYMBOL_DATA> folders;
194 m_reader->EnumFiles( root, 1, [&](
const CFB::COMPOUND_FILE_ENTRY* tentry,
const CFB::utf16string&,
int ) ->
int
196 wxString dirName = UTF16ToWstring( tentry->name, tentry->nameLen );
202 [&](
const CFB::COMPOUND_FILE_ENTRY* entry,
const CFB::utf16string&,
int ) ->
int
204 std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
206 if(
m_reader->IsStream( entry ) && fileName == L
"Data" )
207 folders[dirName].m_symbol = entry;
209 if(
m_reader->IsStream( entry ) && fileName == L
"PinFrac" )
210 folders[dirName].m_pinsFrac = entry;
212 if(
m_reader->IsStream( entry ) && fileName == L
"PinWideText" )
213 folders[dirName].m_pinsWideText = entry;
215 if(
m_reader->IsStream( entry ) && fileName == L
"PinTextData" )
216 folders[dirName].m_pinsTextData = entry;
228std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*>
231 const CFB::COMPOUND_FILE_ENTRY* root =
m_reader->GetRootEntry();
236 std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> files;
240 [&](
const CFB::COMPOUND_FILE_ENTRY* tentry,
const CFB::utf16string& dir,
246 std::wstring dirName = UTF16ToWstring( tentry->name, tentry->nameLen );
248 if( dirName != aDir )
253 [&](
const CFB::COMPOUND_FILE_ENTRY* entry,
const CFB::utf16string&,
256 if( m_reader->IsStream( entry ) )
258 std::wstring fileName =
259 UTF16ToWstring( entry->name, entry->nameLen );
261 files[fileName] = entry;
273const CFB::COMPOUND_FILE_ENTRY*
275 const std::vector<std::string>& aStreamPath )
const
283 auto it = aStreamPath.cbegin();
285 while( aStart !=
nullptr )
287 const std::string&
name = *it;
289 if( ++it == aStreamPath.cend() )
305const CFB::COMPOUND_FILE_ENTRY*
313 const CFB::COMPOUND_FILE_ENTRY* aEntry )
316 m_size =
static_cast<size_t>( aEntry->size );
337 std::function<std::map<wxString, wxString>(
const std::string& )> handleBinaryData )
340 std::map<wxString, wxString>
kv;
342 uint32_t length = Read<uint32_t>();
343 bool isBinary = ( length & 0xff000000 ) != 0;
345 length &= 0x00ffffff;
360 bool hasNullByte =
m_pos[length - 1] ==
'\0';
362 if( !hasNullByte && !isBinary )
364 wxLogTrace(
"ALTIUM", wxT(
"Missing null byte at end of property list. Imported data might be "
365 "malformed or missing." ) );
370 std::string str = std::string(
m_pos, length - ( hasNullByte ? 1 : 0 ) );
375 return handleBinaryData( str );
378 std::size_t token_end = 0;
380 while( token_end < str.size() && token_end != std::string::npos )
382 std::size_t token_start = str.find(
'|', token_end );
383 std::size_t token_equal = str.find(
'=', token_end );
384 std::size_t key_start;
386 if( token_start <= token_equal )
388 key_start = token_start + 1;
393 key_start = token_end;
396 token_end = str.find(
'|', key_start );
398 if( token_equal >= token_end )
403 if( token_end == std::string::npos )
405 token_end = str.size() + 1;
408 std::string keyS = str.substr( key_start, token_equal - key_start );
409 std::string valueS = str.substr( token_equal + 1, token_end - token_equal - 1 );
413 wxString key( keyS.c_str(), wxConvISO8859_1 );
415 wxString canonicalKey = key.Trim(
false ).Trim(
true ).MakeUpper();
419 if( canonicalKey.StartsWith(
"%UTF8%" ) )
420 value = wxString( valueS.c_str(), wxConvUTF8 );
422 value = wxString( valueS.c_str(), wxConvISO8859_1 );
424 if( canonicalKey != wxS(
"PATTERN" ) && canonicalKey != wxS(
"SOURCEFOOTPRINTLIBRARY" ) )
428 value.Replace( wxT(
"ÿ" ), wxT(
" " ) );
431 if( canonicalKey == wxT(
"DESIGNATOR" )
432 || canonicalKey == wxT(
"NAME" )
433 || canonicalKey == wxT(
"TEXT" ) )
435 if(
kv[ wxT(
"RECORD" ) ] != wxT(
"4" ) )
439 kv.insert( { canonicalKey, value.Trim() } );
std::string FormatPath(const std::vector< std::string > &aVectorPath)
Helper for debug logging (vector -> string)
wxString AltiumPropertyToKiCadString(const wxString &aString)
size_t GetRemainingBytes() const
std::unique_ptr< char[]> m_content
ALTIUM_BINARY_PARSER(const ALTIUM_COMPOUND_FILE &aFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< wxString, wxString > ReadProperties(std::function< std::map< wxString, wxString >(const std::string &)> handleBinaryData=[](const std::string &) { return std::map< wxString, wxString >();})
const CFB::CompoundFileReader & GetCompoundFileReader() const
std::unique_ptr< ALTIUM_COMPOUND_FILE > DecodeIntLibStream(const CFB::COMPOUND_FILE_ENTRY &cfe)
const CFB::COMPOUND_FILE_ENTRY * FindStreamSingleLevel(const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::string aName, const bool aIsStream) const
std::map< wxString, const CFB::COMPOUND_FILE_ENTRY * > EnumDir(const std::wstring &aDir) const
std::vector< char > m_buffer
std::unique_ptr< CFB::CompoundFileReader > m_reader
ALTIUM_COMPOUND_FILE(const wxString &aFilePath)
Open a CFB file.
std::map< wxString, ALTIUM_SYMBOL_DATA > GetLibSymbols(const CFB::COMPOUND_FILE_ENTRY *aStart) const
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
#define THROW_IO_ERROR(msg)