From c6504628f0de897e223bf20be681b77c478163ec Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Wed, 5 Jan 2022 23:35:42 +0100 Subject: [PATCH] altium: Fix Compound File Reader which returned wrong entries It was possible that we confuse multiple files with the same name. This should not be that relevant for board and schematic import, but is important for library import! --- common/plugins/altium/altium_parser.cpp | 71 +++++++++++++++---------- common/plugins/altium/altium_parser.h | 4 +- pcbnew/plugins/altium/altium_pcb.cpp | 6 +-- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/common/plugins/altium/altium_parser.cpp b/common/plugins/altium/altium_parser.cpp index 5f9f412e77..566a1bcc4c 100644 --- a/common/plugins/altium/altium_parser.cpp +++ b/common/plugins/altium/altium_parser.cpp @@ -32,39 +32,54 @@ #include #include -const CFB::COMPOUND_FILE_ENTRY* FindStream( const CFB::CompoundFileReader& aReader, - const char* aStreamName ) +static const CFB::COMPOUND_FILE_ENTRY* +FindStreamSingleLevel( const CFB::CompoundFileReader& aReader, + const CFB::COMPOUND_FILE_ENTRY* aEntry, const std::string aName, + const bool aIsStream ) { const CFB::COMPOUND_FILE_ENTRY* ret = nullptr; - aReader.EnumFiles( aReader.GetRootEntry(), -1, - [&]( const CFB::COMPOUND_FILE_ENTRY* aEntry, const CFB::utf16string& aU16dir, - int level ) -> void - { - if( aReader.IsStream( aEntry ) ) - { - std::string name = UTF16ToUTF8( aEntry->name ); - if( aU16dir.length() > 0 ) - { - std::string dir = UTF16ToUTF8( aU16dir.c_str() ); - if( strncmp( aStreamName, dir.c_str(), dir.length() ) == 0 - && aStreamName[dir.length()] == '\\' - && strcmp( aStreamName + dir.length() + 1, name.c_str() ) == 0 ) - { - ret = aEntry; - } - } - else - { - if( strcmp( aStreamName, name.c_str() ) == 0 ) - { - ret = aEntry; - } - } - } - } ); + + aReader.EnumFiles( aEntry, 1, + [&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir, + int level ) -> void + { + if( aReader.IsStream( entry ) == aIsStream ) + { + std::string name = UTF16ToUTF8( entry->name ); + if( name == aName.c_str() ) + { + ret = entry; + } + } + } ); + return ret; } +const CFB::COMPOUND_FILE_ENTRY* FindStream( const CFB::CompoundFileReader& aReader, + const std::string aStreamName ) +{ + const CFB::COMPOUND_FILE_ENTRY* currentDirEntry = aReader.GetRootEntry(); + + size_t startCh = 0; + size_t delimiter = aStreamName.find( '\\', startCh ); + while( delimiter != std::string::npos ) + { + std::string directoryName = aStreamName.substr( startCh, delimiter ); + currentDirEntry = FindStreamSingleLevel( aReader, currentDirEntry, directoryName, false ); + if( currentDirEntry == nullptr ) + { + return nullptr; + } + + startCh = delimiter + 1; + delimiter = aStreamName.find( '\\', startCh ); + } + + std::string fileName = aStreamName.substr( startCh, delimiter ); + return FindStreamSingleLevel( aReader, currentDirEntry, fileName, true ); +} + ALTIUM_PARSER::ALTIUM_PARSER( const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry ) diff --git a/common/plugins/altium/altium_parser.h b/common/plugins/altium/altium_parser.h index f129fd9d78..1302d97c72 100644 --- a/common/plugins/altium/altium_parser.h +++ b/common/plugins/altium/altium_parser.h @@ -40,8 +40,8 @@ struct COMPOUND_FILE_ENTRY; } // namespace CFB // Helper method to find file inside compound file -const CFB::COMPOUND_FILE_ENTRY* FindStream( - const CFB::CompoundFileReader& aReader, const char* aStreamName ); +const CFB::COMPOUND_FILE_ENTRY* FindStream( const CFB::CompoundFileReader& aReader, + const std::string aStreamName ); class ALTIUM_PARSER diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 7d92a8451b..15748e9332 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -480,7 +480,7 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader, std::string mappedFile = mappedDirectory->second + "Header"; - const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, mappedFile.c_str() ); + const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, mappedFile ); if( file == nullptr ) { continue; @@ -528,7 +528,7 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader, if( directory != ALTIUM_PCB_DIR::FILE_HEADER ) mappedFile += "Data"; - const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, mappedFile.c_str() ); + const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, mappedFile ); if( file != nullptr ) fp( aReader, file ); @@ -1445,7 +1445,7 @@ void ALTIUM_PCB::ParseModelsData( const CFB::CompoundFileReader& aReader, idx++; - const CFB::COMPOUND_FILE_ENTRY* stepEntry = FindStream( aReader, stepPath.c_str() ); + const CFB::COMPOUND_FILE_ENTRY* stepEntry = FindStream( aReader, stepPath.ToStdString() ); if( stepEntry == nullptr ) {