Speed up Altium compound file reader
Just read the footprint list once and store the cache for later use.
This commit is contained in:
parent
b8b2498e0c
commit
1b63d11adf
|
@ -89,159 +89,27 @@ ALTIUM_COMPOUND_FILE::ALTIUM_COMPOUND_FILE( const wxString& aFilePath )
|
|||
}
|
||||
|
||||
|
||||
std::map<wxString, wxString> ALTIUM_COMPOUND_FILE::ListLibFootprints() const
|
||||
std::map<wxString, wxString> ALTIUM_COMPOUND_FILE::ListLibFootprints()
|
||||
{
|
||||
std::map<wxString, wxString> patternMap;
|
||||
if( m_libFootprintDirNameCache.empty() )
|
||||
cacheLibFootprintNames();
|
||||
|
||||
if( !m_reader )
|
||||
return patternMap;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
|
||||
if( !root )
|
||||
return patternMap;
|
||||
|
||||
m_reader->EnumFiles( root, 2,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir,
|
||||
int level ) -> int
|
||||
{
|
||||
std::wstring dirName = UTF16ToWstring( dir.data(), dir.size() );
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString key = ALTIUM_PARSER::ReadString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
patternMap.emplace( key, fpName );
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
|
||||
return patternMap;
|
||||
return m_libFootprintDirNameCache;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*>
|
||||
ALTIUM_COMPOUND_FILE::FindLibFootprintDirName( const wxString& aFpUnicodeName ) const
|
||||
ALTIUM_COMPOUND_FILE::FindLibFootprintDirName( const wxString& aFpUnicodeName )
|
||||
{
|
||||
if( !m_reader )
|
||||
return std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*>( wxEmptyString, nullptr );
|
||||
if( m_libFootprintNameCache.empty() )
|
||||
cacheLibFootprintNames();
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
auto it = m_libFootprintNameCache.find( aFpUnicodeName );
|
||||
|
||||
if( !root )
|
||||
return std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*>( wxEmptyString, nullptr );
|
||||
if( it == m_libFootprintNameCache.end() )
|
||||
return { wxEmptyString, nullptr };
|
||||
|
||||
wxString retStr;
|
||||
const CFB::COMPOUND_FILE_ENTRY* retEntry = nullptr;
|
||||
|
||||
// Cheap and easy check first as most ASCII-coded libs are under the same dir name
|
||||
m_reader->EnumFiles( root, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
// We are only looking for one string, so if we found it, break the loop
|
||||
if( retStr != wxEmptyString )
|
||||
return 1;
|
||||
|
||||
std::wstring dirName = UTF16ToWstring( tentry->name, tentry->nameLen );
|
||||
|
||||
if( aFpUnicodeName.ToStdWstring().compare( 0, 10, dirName, 0, 10 ) )
|
||||
return 0;
|
||||
|
||||
m_reader->EnumFiles( tentry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
if( fpName == aFpUnicodeName )
|
||||
{
|
||||
retStr = dirName;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} );
|
||||
|
||||
if( retStr != wxEmptyString )
|
||||
{
|
||||
retEntry = tentry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
|
||||
if( retStr != wxEmptyString )
|
||||
return std::make_tuple( retStr, retEntry );
|
||||
|
||||
// Now do the expensive check, iterating through each directory in the library and reading the files
|
||||
m_reader->EnumFiles( root, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string& dir,
|
||||
int level ) -> int
|
||||
{
|
||||
if( retStr != wxEmptyString )
|
||||
return 1;
|
||||
|
||||
std::wstring dirName = UTF16ToWstring( tentry->name, tentry->nameLen );
|
||||
|
||||
m_reader->EnumFiles( tentry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
if( fpName == aFpUnicodeName )
|
||||
{
|
||||
retStr = dirName;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} );
|
||||
|
||||
if( retStr != wxEmptyString )
|
||||
{
|
||||
retEntry = tentry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
|
||||
if( retStr != wxEmptyString )
|
||||
return std::make_tuple( retStr, retEntry );
|
||||
|
||||
return std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*>( wxEmptyString, nullptr );
|
||||
return { it->first, it->second };
|
||||
}
|
||||
|
||||
|
||||
|
@ -351,6 +219,53 @@ ALTIUM_COMPOUND_FILE::FindStream( const std::vector<std::string>& aStreamPath )
|
|||
}
|
||||
|
||||
|
||||
void ALTIUM_COMPOUND_FILE::cacheLibFootprintNames()
|
||||
{
|
||||
m_libFootprintDirNameCache.clear();
|
||||
m_libFootprintNameCache.clear();
|
||||
|
||||
if( !m_reader )
|
||||
return;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
|
||||
if( !root )
|
||||
return;
|
||||
|
||||
m_reader->EnumFiles( root, 1,
|
||||
[this]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string& dir,
|
||||
int level ) -> int
|
||||
{
|
||||
if( m_reader->IsStream( tentry ) )
|
||||
return 0;
|
||||
|
||||
m_reader->EnumFiles( tentry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString key = ALTIUM_PARSER::ReadString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
m_libFootprintDirNameCache[key] = fpName;
|
||||
m_libFootprintNameCache[fpName] = tentry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
return 0;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
ALTIUM_PARSER::ALTIUM_PARSER( const ALTIUM_COMPOUND_FILE& aFile,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
||||
{
|
||||
|
@ -587,4 +502,5 @@ wxString ALTIUM_PARSER::ReadUnicodeString( const std::map<wxString, wxString>& a
|
|||
}
|
||||
|
||||
return ReadString( aProps, aKey, aDefault );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,9 +67,9 @@ public:
|
|||
|
||||
const CFB::CompoundFileReader& GetCompoundFileReader() const { return *m_reader; }
|
||||
|
||||
std::map<wxString, wxString> ListLibFootprints() const;
|
||||
std::map<wxString, wxString> ListLibFootprints();
|
||||
|
||||
std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> FindLibFootprintDirName( const wxString& aFpUnicodeName ) const;
|
||||
std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> FindLibFootprintDirName( const wxString& aFpUnicodeName );
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* FindStream( const std::vector<std::string>& aStreamPath ) const;
|
||||
|
||||
|
@ -82,8 +82,14 @@ public:
|
|||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const;
|
||||
|
||||
private:
|
||||
|
||||
void cacheLibFootprintNames();
|
||||
|
||||
std::unique_ptr<CFB::CompoundFileReader> m_reader;
|
||||
std::vector<char> m_buffer;
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> m_libFootprintNameCache;
|
||||
std::map<wxString, wxString> m_libFootprintDirNameCache;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ void ALTIUM_PCB::Parse( const ALTIUM_COMPOUND_FILE& altiumPcbFi
|
|||
}
|
||||
|
||||
|
||||
FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile,
|
||||
FOOTPRINT* ALTIUM_PCB::ParseFootprint( ALTIUM_COMPOUND_FILE& altiumLibFile,
|
||||
const wxString& aFootprintName )
|
||||
{
|
||||
std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( m_board );
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
void Parse( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
|
||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping );
|
||||
|
||||
FOOTPRINT* ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile,
|
||||
FOOTPRINT* ParseFootprint( ALTIUM_COMPOUND_FILE& altiumLibFile,
|
||||
const wxString& aFootprintName );
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue