Better clarity and memory leak fixes for LTspice importer.

Moves some exception processing to a REPORTER interface so we don't
leak a bunch of memory by exiting early.

Also adds some assertion processing to make sure we're not leaking
in other places.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15158
This commit is contained in:
Jeff Young 2023-10-25 00:09:42 +01:00
parent 46aecefb04
commit fefb3d96dd
4 changed files with 54 additions and 21 deletions

View File

@ -191,13 +191,10 @@ void LTSPICE_SCH_PARSER::CreateKicadSYMBOLs( SCH_SHEET_PATH* aSheet,
// Calculating bounding box
BOX2I bbox;
std::vector<LTSPICE_FILE> tempVector;
LTSPICE_SCHEMATIC::LT_SYMBOL tempSymbol;
LTSPICE_FILE tempAsyFile( lt_symbol.Name + ".asy", { 0, 0 } );
LTSPICE_SCHEMATIC::LT_ASC dummyAsc;
tempVector.push_back( tempAsyFile );
tempSymbol = m_lt_schematic->SymbolBuilder( lt_symbol.Name, dummyAsc );
LIB_SYMBOL* tempLibSymbol = new LIB_SYMBOL( lt_symbol.Name );

View File

@ -108,8 +108,15 @@ SCH_SHEET* SCH_LTSPICE_PLUGIN::LoadSchematicFile( const wxString& aFileName, SCH
}
}
LTSPICE_SCHEMATIC ascFile( aFileName, ltspiceDataDir, m_reporter, m_progressReporter );
ascFile.Load( aSchematic, rootSheet, aFileName );
try
{
LTSPICE_SCHEMATIC ascFile( aFileName, ltspiceDataDir, m_reporter, m_progressReporter );
ascFile.Load( aSchematic, rootSheet, aFileName, m_reporter );
}
catch( IO_ERROR& e )
{
m_reporter->Report( e.What(), RPT_SEVERITY_ERROR );
}
aSchematic->CurrentSheet().UpdateAllScreenReferences();

View File

@ -34,7 +34,7 @@
void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
const wxFileName& aLibraryFileName )
const wxFileName& aLibraryFileName, REPORTER* aReporter )
{
std::map<wxString, wxString> mapOfAscFiles;
std::map<wxString, wxString> mapOfAsyFiles;
@ -70,7 +70,7 @@ void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
while( !ascFileQueue.empty() )
{
SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
SCH_SCREEN* screen = nullptr;
// Reading the .asc file
wxString ascFilePath = mapOfAscFiles[ ascFileQueue.front() ];
@ -96,6 +96,9 @@ void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
if( IsAsySubsheet( asyBuffer ) )
{
if( !screen )
screen = new SCH_SCREEN( m_schematic );
newSubSchematicElement.ParentIndex = parentSheetIndex;
newSubSchematicElement.Screen = screen;
newSubSchematicElement.Sheet = new SCH_SHEET();
@ -116,23 +119,23 @@ void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
wxString buffer = SafeReadFile( mapOfAscFiles[ascFiles[i].ElementName], wxS( "r" ) );
// Getting the keywords to read
std::vector<LTSPICE_FILE> sourceFiles = GetSchematicElements( buffer );
{
std::vector<LTSPICE_FILE> sourceFiles = GetSchematicElements( buffer );
m_fileCache[ wxS( "asyFiles" ) ] = ReadAsyFiles( sourceFiles, mapOfAsyFiles );
m_fileCache[ wxS( "ascFiles" ) ][ wxS( "parentFile" ) ] = buffer;
m_fileCache[ wxS( "asyFiles" ) ] = ReadAsyFiles( sourceFiles, mapOfAsyFiles );
m_fileCache[ wxS( "ascFiles" ) ][ wxS( "parentFile" ) ] = buffer;
for( const LTSPICE_FILE& file : sourceFiles )
wxASSERT( file.Sheet == nullptr && file.Screen == nullptr );
}
SCH_SHEET* curSheet;
SCH_SHEET_PATH curSheetPath;
LTSPICE_SCH_PARSER parser( this );
if( i > 0 )
{
std::vector<LTSPICE_FILE> tempVector;
tempVector.push_back( ascFiles[i] );
curSheet = ascFiles[i].Sheet;
std::map tempAsyMap = ReadAsyFiles( tempVector, mapOfAsyFiles );
SCH_SHEET* curSheet = ascFiles[i].Sheet;
std::map tempAsyMap = ReadAsyFile( ascFiles[i], mapOfAsyFiles );
wxString ascFileName = ascFiles[i].ElementName;
LT_ASC dummyAsc;
LT_SYMBOL tempSymbol = SymbolBuilder( ascFileName, tempAsyMap[ascFileName], dummyAsc );
@ -169,7 +172,7 @@ void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
}
else
{
curSheet = ascFiles[i].Sheet;
SCH_SHEET* curSheet = ascFiles[i].Sheet;
ascFiles[i].SheetPath.push_back( curSheet );
curSheetPath = ascFiles[i].SheetPath;
@ -180,8 +183,15 @@ void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
for( const LTSPICE_FILE& ascFile : ascFiles )
subSchematicAsyFiles.push_back( ascFile.ElementName );
std::vector<LTSPICE_SCHEMATIC::LT_ASC> lt_ascs = StructureBuilder();
parser.Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
try
{
std::vector<LTSPICE_SCHEMATIC::LT_ASC> lt_ascs = StructureBuilder();
parser.Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
}
catch( IO_ERROR& e )
{
aReporter->Report( e.What(), RPT_SEVERITY_ERROR );
}
}
}
@ -259,6 +269,21 @@ void LTSPICE_SCHEMATIC::GetAscAndAsyFilePaths( const wxDir& aDir, bool aRecursiv
}
std::map<wxString, wxString>
LTSPICE_SCHEMATIC::ReadAsyFile( const LTSPICE_FILE& aSourceFile,
const std::map<wxString, wxString>& aAsyFileMap )
{
std::map<wxString, wxString> resultantMap;
wxString fileName = aSourceFile.ElementName;
if( aAsyFileMap.count( fileName ) )
resultantMap[fileName] = SafeReadFile( aAsyFileMap.at( fileName ), wxS( "r" ) );
return resultantMap;
}
std::map<wxString, wxString>
LTSPICE_SCHEMATIC::ReadAsyFiles( const std::vector<LTSPICE_FILE>& aSourceFiles,
const std::map<wxString, wxString>& aAsyFileMap )

View File

@ -294,7 +294,8 @@ public:
* @param aRootSheet is the root sheet referencing variable.
* @param aLibraryFileName is the name of the library which gets created when the plugin runs.
*/
void Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const wxFileName& aLibraryFileName );
void Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const wxFileName& aLibraryFileName,
REPORTER* aReporter );
/**
* Used to get file path for Asc and Asy files.
@ -334,6 +335,9 @@ public:
std::map<wxString, wxString> ReadAsyFiles( const std::vector<LTSPICE_FILE>& aSourceFiles,
const std::map<wxString, wxString>& aAsyFileMap );
std::map<wxString, wxString> ReadAsyFile( const LTSPICE_FILE& aSourceFile,
const std::map<wxString, wxString>& aAsyFileMap );
/**
* Build Intermediate data structure.
* @return LT_ASC struct filled with all info from asc and asy files.