Introduce base IO_MGR class and unify RELEASER objects

The IO_RELEASER is a thin-wrapper around a std::unique_ptr, but done
this way to allow easier addition of a custom deleter in the future if
something needs to call back into the IO_MGR.
This commit is contained in:
Ian McInerney 2023-12-27 20:39:29 +00:00
parent 04d15026c5
commit f2702b223c
39 changed files with 144 additions and 260 deletions

View File

@ -303,7 +303,7 @@ void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxS
bool aBestEfforts )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
@ -312,7 +312,7 @@ void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxS
void FP_LIB_TABLE::PrefetchLib( const wxString& aNickname )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
}
@ -369,7 +369,7 @@ const FOOTPRINT* FP_LIB_TABLE::GetEnumeratedFootprint( const wxString& aNickname
const wxString& aFootprintName )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
@ -381,7 +381,7 @@ bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& a
try
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
return row->plugin->FootprintExists( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
@ -397,7 +397,7 @@ FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname,
const wxString& aFootprintName, bool aKeepUUID )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
FOOTPRINT* ret = row->plugin->FootprintLoad( row->GetFullURI( true ), aFootprintName,
aKeepUUID, row->GetProperties() );
@ -412,7 +412,7 @@ FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname,
const FOOTPRINT* aFootprint, bool aOverwrite )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
if( !aOverwrite )
{
@ -438,7 +438,7 @@ FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname,
void FP_LIB_TABLE::FootprintDelete( const wxString& aNickname, const wxString& aFootprintName )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
return row->plugin->FootprintDelete( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
}
@ -447,7 +447,7 @@ void FP_LIB_TABLE::FootprintDelete( const wxString& aNickname, const wxString& a
bool FP_LIB_TABLE::IsFootprintLibWritable( const wxString& aNickname )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
return row->plugin->IsLibraryWritable( row->GetFullURI( true ) );
}
@ -455,7 +455,7 @@ bool FP_LIB_TABLE::IsFootprintLibWritable( const wxString& aNickname )
void FP_LIB_TABLE::FootprintLibDelete( const wxString& aNickname )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
row->plugin->DeleteLibrary( row->GetFullURI( true ), row->GetProperties() );
}
@ -463,7 +463,7 @@ void FP_LIB_TABLE::FootprintLibDelete( const wxString& aNickname )
void FP_LIB_TABLE::FootprintLibCreate( const wxString& aNickname )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( (PCB_IO*) row->plugin );
wxASSERT( row->plugin );
row->plugin->CreateLibrary( row->GetFullURI( true ), row->GetProperties() );
}

View File

@ -561,7 +561,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
if( renameFile )
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
// If the associated screen is shared by more than one sheet, do not
// change the filename of the corresponding screen here.

View File

@ -172,7 +172,7 @@ protected:
STRING_UTF8_MAP choices;
SCH_IO_MGR::SCH_FILE_T pi_type = SCH_IO_MGR::EnumFromStr( row->GetType() );
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( pi_type ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pi_type ) );
pi->GetLibraryOptions( &choices );
DIALOG_PLUGIN_OPTIONS dlg( m_dialog, row->GetNickName(), choices, options, &result );
@ -256,7 +256,7 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, P
for( const SCH_IO_MGR::SCH_FILE_T& type : SCH_IO_MGR::SCH_FILE_T_vector )
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( type ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
if( !pi )
continue;
@ -308,7 +308,7 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, P
auto* libTable = static_cast<SYMBOL_LIB_TABLE_GRID*>( grid->GetTable() );
auto* tableRow = static_cast<SYMBOL_LIB_TABLE_ROW*>( libTable->at( row ) );
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
if( pi )
{
@ -585,7 +585,7 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;
@ -936,8 +936,8 @@ bool PANEL_SYM_LIB_TABLE::convertLibrary( STRING_UTF8_MAP* aOldFileProps, const
if( oldFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
return false;
SCH_IO::SCH_IO_RELEASER oldFilePI( SCH_IO_MGR::FindPlugin( oldFileType ) );
SCH_IO::SCH_IO_RELEASER kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
IO_RELEASER<SCH_IO> oldFilePI( SCH_IO_MGR::FindPlugin( oldFileType ) );
IO_RELEASER<SCH_IO> kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
std::vector<LIB_SYMBOL*> symbols;
std::vector<LIB_SYMBOL*> newSymbols;
std::map<LIB_SYMBOL*, LIB_SYMBOL*> symbolMap;

View File

@ -121,8 +121,7 @@ SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH
if( !project )
project = GetDefaultProject();
SCH_IO* plugin = SCH_IO_MGR::FindPlugin( aFormat );
SCH_IO::SCH_IO_RELEASER pi( plugin );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( aFormat ) );
SCHEMATIC* schematic = new SCHEMATIC( project );

View File

@ -248,8 +248,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
SetScreen( nullptr );
SCH_IO* plugin = SCH_IO_MGR::FindPlugin( schFileType );
SCH_IO::SCH_IO_RELEASER pi( plugin );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
pi->SetProgressReporter( &progressReporter );
@ -670,7 +669,7 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
if( fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY )
continue; // this is "Import non-KiCad schematic"
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;
@ -725,7 +724,7 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;
@ -798,7 +797,7 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
pluginType = SCH_IO_MGR::SCH_KICAD;
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( pluginType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
try
{
@ -1331,12 +1330,12 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
try
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
DIALOG_HTML_REPORTER errorReporter( this );
WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
PROJECT_CHOOSER_PLUGIN* projectChooserPlugin =
dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( (SCH_IO*) pi );
dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() );
if( projectChooserPlugin )
{

View File

@ -862,7 +862,7 @@ bool SYMBOL_LIB_TABLE_RESCUER::WriteRescueLibrary( wxWindow *aParent )
try
{
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
for( const std::unique_ptr<LIB_SYMBOL>& symbol : m_rescueLibSymbols )
pi->SaveSymbol( fn.GetFullPath(), new LIB_SYMBOL( *symbol.get() ), m_properties.get() );

View File

@ -355,7 +355,7 @@ SCH_SHEET* SCH_IO_ALTIUM::LoadSchematicFile( const wxString& aFileName, SCHEMATI
wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
m_pi.reset( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
/// @note No check is being done here to see if the existing symbol library exists so this
/// will overwrite the existing one.

View File

@ -178,7 +178,7 @@ private:
wxString m_libName; // Library name to save symbols
bool m_isIntLib; // Flag to indicate Integrated Library
SCH_IO::SCH_IO_RELEASER m_pi; // Plugin to create KiCad symbol library.
IO_RELEASER<SCH_IO> m_pi; // Plugin to create KiCad symbol library.
std::unique_ptr<STRING_UTF8_MAP> m_properties; // Library plugin properties.
std::unique_ptr<TITLE_BLOCK> m_currentTitleBlock; // Will be assigned at the end of parsing

View File

@ -115,8 +115,7 @@ SCH_SHEET* SCH_IO_CADSTAR_ARCHIVE::LoadSchematicFile( const wxString& aFi
wxFileName libFileName( aSchematic->Prj().GetProjectPath(), libName,
FILEEXT::KiCadSymbolLibFileExtension );
SCH_IO::SCH_IO_RELEASER sch_plugin;
sch_plugin.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
IO_RELEASER<SCH_IO> sch_plugin( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
if( !libTable->HasLibrary( libName ) )
{

View File

@ -455,7 +455,7 @@ SCH_SHEET* SCH_IO_EAGLE::LoadSchematicFile( const wxString& aFileName, SCHEMATIC
wxCHECK_MSG( libTable, nullptr, wxT( "Could not load symbol lib table." ) );
m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
m_pi.reset( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
m_properties = std::make_unique<STRING_UTF8_MAP>();
( *m_properties )[SCH_IO_KICAD_LEGACY::PropBuffering] = "";

View File

@ -247,7 +247,7 @@ private:
std::map<wxString, EAGLE_LIBRARY> m_eagleLibs;
std::unordered_map<wxString, bool> m_userValue; ///< deviceset/@uservalue for device.
SCH_IO::SCH_IO_RELEASER m_pi; ///< PI to create KiCad symbol library.
IO_RELEASER<SCH_IO> m_pi; ///< PI to create KiCad symbol library.
std::unique_ptr<STRING_UTF8_MAP> m_properties; ///< Library plugin properties.
unsigned m_doneCount;

View File

@ -540,8 +540,7 @@ SCH_SHEET* SCH_IO_EASYEDAPRO::LoadSchematicFile( const wxString& aFileName,
};
EASYEDAPRO::IterateZipFiles( aFileName, cbs );
SCH_IO::SCH_IO_RELEASER sch_plugin;
sch_plugin.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
IO_RELEASER<SCH_IO> sch_plugin( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
if( !libTable->HasLibrary( libName ) )
{

View File

@ -356,57 +356,6 @@ public:
*/
virtual ~SCH_IO() { }
/**
* Helper object to release a #SCH_IO in the context of a potential thrown exception
* through its destructor.
*/
class SCH_IO_RELEASER
{
SCH_IO* plugin;
// private assignment operator so it's illegal
SCH_IO_RELEASER& operator=( SCH_IO_RELEASER& aOther ) { return *this; }
// private copy constructor so it's illegal
SCH_IO_RELEASER( const SCH_IO_RELEASER& aOther ) {}
public:
SCH_IO_RELEASER( SCH_IO* aPlugin = nullptr ) :
plugin( aPlugin )
{
}
~SCH_IO_RELEASER()
{
if( plugin )
release();
}
void release()
{
SCH_IO_MGR::ReleasePlugin( plugin );
plugin = nullptr;
}
void set( SCH_IO* aPlugin )
{
if( plugin )
release();
plugin = aPlugin;
}
operator SCH_IO* () const
{
return plugin;
}
SCH_IO* operator -> () const
{
return plugin;
}
};
protected:
SCH_IO( const wxString& aName ) : IO_BASE( aName )

View File

@ -79,16 +79,6 @@ SCH_IO* SCH_IO_MGR::FindPlugin( SCH_FILE_T aFileType )
}
void SCH_IO_MGR::ReleasePlugin( SCH_IO* aPlugin )
{
// This function is a place holder for a future point in time where
// the plugin is a DLL/DSO. It could do reference counting, and then
// unload the DLL/DSO when count goes to zero.
delete aPlugin;
}
const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
{
// keep this function in sync with EnumFromStr() relative to the
@ -158,7 +148,7 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::GuessPluginTypeFromLibPath( const wxString& a
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;
@ -184,7 +174,7 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::GuessPluginTypeFromSchPath( const wxString& a
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;

View File

@ -29,6 +29,7 @@
#include <reporter.h>
#include <i18n_utility.h>
#include <io/io_base.h>
#include <io/io_mgr.h>
#include <wx/arrstr.h>
@ -47,7 +48,7 @@ class PROGRESS_REPORTER;
/**
* A factory which returns an instance of a #SCH_IO.
*/
class SCH_IO_MGR
class SCH_IO_MGR : public IO_MGR
{
public:
@ -78,26 +79,14 @@ public:
* Return a #SCH_IO which the caller can use to import, export, save, or load
* design documents.
*
* The returned #SCH_IO, may be reference counted, so please call PluginRelease()
* when you are done using the returned #SCH_IO. It may or may not be code running
* from a DLL/DSO.
*
* @param aFileType is from #SCH_FILE_T and tells which plugin to find.
*
* @return the plugin corresponding to aFileType or NULL if not found.
* Caller owns the returned object, and must call PluginRelease when done using it.
* Caller owns the returned object.
*/
APIEXPORT
static SCH_IO* FindPlugin( SCH_FILE_T aFileType );
/**
* Release a #SCH_IO back to the system, and may cause it to be unloaded from memory.
*
* @param aPlugin is the one to be released, and which is no longer usable
* after calling this.
*/
static void ReleasePlugin( SCH_IO* aPlugin );
/**
* Return a brief name for a plugin, given aFileType enum.
*/

View File

@ -169,7 +169,7 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
if( schFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
schFileType = SCH_IO_MGR::SCH_KICAD;
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( schFileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
std::unique_ptr< SCH_SHEET> tmpSheet = std::make_unique<SCH_SHEET>( &Schematic() );
// This will cause the sheet UUID to be set to the UUID of the aSheet argument. This is

View File

@ -56,7 +56,7 @@ void SYMBOL_EDIT_FRAME::ImportSymbol()
if( fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY )
continue; // this is "Import non-KiCad schematic"
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
if( !pi )
continue;
@ -98,7 +98,7 @@ void SYMBOL_EDIT_FRAME::ImportSymbol()
return;
}
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( piType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( piType ) );
// TODO dialog to select the symbol to be imported if there is more than one
try
@ -173,7 +173,7 @@ void SYMBOL_EDIT_FRAME::ExportSymbol()
if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
pluginType = SCH_IO_MGR::SCH_KICAD;
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( pluginType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
if( fn.FileExists() )
{

View File

@ -82,7 +82,7 @@ bool SYMBOL_LIB_TABLE_ROW::Refresh()
{
wxArrayString dummyList;
plugin.set( SCH_IO_MGR::FindPlugin( type ) );
plugin.reset( SCH_IO_MGR::FindPlugin( type ) );
SetLoaded( false );
plugin->SetLibTable( static_cast<SYMBOL_LIB_TABLE*>( GetParent() ) );
plugin->EnumerateSymbolLib( dummyList, GetFullURI( true ), GetProperties() );
@ -110,8 +110,7 @@ void SYMBOL_LIB_TABLE_ROW::ShowSettingsDialog( wxWindow* aParent ) const
if( type != SCH_IO_MGR::SCH_DATABASE )
return;
DIALOG_DATABASE_LIB_SETTINGS dlg( aParent,
static_cast<SCH_IO_DATABASE*>( ( SCH_IO* )plugin ) );
DIALOG_DATABASE_LIB_SETTINGS dlg( aParent, static_cast<SCH_IO_DATABASE*>( plugin.get() ) );
dlg.ShowModal();
}

View File

@ -133,10 +133,10 @@ private:
void setPlugin( SCH_IO* aPlugin )
{
plugin.set( aPlugin );
plugin.reset( aPlugin );
}
SCH_IO::SCH_IO_RELEASER plugin;
IO_RELEASER<SCH_IO> plugin;
LIB_T type;
};

View File

@ -173,7 +173,8 @@ bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxStri
wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
wxFileName fn( aFileName );
wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( aFileType ) );
bool res = true; // assume all libraries are successfully saved
STRING_UTF8_MAP properties;

View File

@ -422,7 +422,7 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
SYMBOL_LIB_TABLE_ROW* row = mgr.GetLibrary( targetLib );
SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->GetType() );
SCH_IO::SCH_IO_RELEASER pi( SCH_IO_MGR::FindPlugin( type ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
wxFileName dest = row->GetFullURI( true );
dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );

View File

@ -84,13 +84,13 @@ private:
void setPlugin( PCB_IO* aPlugin )
{
plugin.set( aPlugin );
plugin.reset( aPlugin );
}
friend class FP_LIB_TABLE;
private:
PCB_IO::RELEASER plugin;
IO_RELEASER<PCB_IO> plugin;
PCB_IO_MGR::PCB_FILE_T type;
};

43
include/io/io_mgr.h Normal file
View File

@ -0,0 +1,43 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IO_MGR_H_
#define IO_MGR_H_
#include <memory>
/**
* Helper to hold and release an #IO_BASE object when exceptions are thrown.
*
* (Wrapper around a std::unique_ptr, but created to allow possible custom deleters
* in the future).
*/
template <class T>
using IO_RELEASER = std::unique_ptr<T>;
class IO_MGR
{
public:
};
#endif // IO_MGR_H_

View File

@ -284,7 +284,7 @@ void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
BOARD* otherBoard = nullptr;
try

View File

@ -240,7 +240,7 @@ protected:
STRING_UTF8_MAP choices;
PCB_IO_MGR::PCB_FILE_T pi_type = PCB_IO_MGR::EnumFromStr( row->GetType() );
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( pi_type ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pi_type ) );
pi->GetLibraryOptions( &choices );
DIALOG_PLUGIN_OPTIONS dlg( m_dialog, row->GetNickName(), choices, options, &result );
@ -514,7 +514,7 @@ void PANEL_FP_LIB_TABLE::populatePluginList()
{
for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
if( !pi )
continue;
@ -899,8 +899,8 @@ bool PANEL_FP_LIB_TABLE::convertLibrary( STRING_UTF8_MAP* aOldFileProps,
return false;
PCB_IO::RELEASER oldFilePI( PCB_IO_MGR::PluginFind( oldFileType ) );
PCB_IO::RELEASER kicadPI( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<PCB_IO> oldFilePI( PCB_IO_MGR::PluginFind( oldFileType ) );
IO_RELEASER<PCB_IO> kicadPI( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
wxArrayString fpNames;
wxFileName newFileName( aNewFilePath );

View File

@ -107,8 +107,7 @@ bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCt
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
// release the PLUGIN even if an exception is thrown.
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
wxCHECK( pi, false );
const IO_BASE::IO_FILE_DESC& desc = pi->GetBoardFileDesc();
@ -607,23 +606,21 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
else
{
BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( pluginType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
LAYER_REMAPPABLE_PLUGIN* layerRemappablePlugin =
dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PCB_IO*) pi );
LAYER_REMAPPABLE_PLUGIN* layerRemappableIO = dynamic_cast<LAYER_REMAPPABLE_PLUGIN*>( pi.get() );
if( layerRemappablePlugin )
if( layerRemappableIO )
{
layerRemappablePlugin->RegisterLayerMappingCallback(
layerRemappableIO->RegisterLayerMappingCallback(
std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
}
PROJECT_CHOOSER_PLUGIN* projectChooserPlugin =
dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( (PCB_IO*) pi );
PROJECT_CHOOSER_PLUGIN* projectChooserIO = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() );
if( projectChooserPlugin )
if( projectChooserIO )
{
projectChooserPlugin->RegisterChooseProjectCallback(
projectChooserIO->RegisterChooseProjectCallback(
std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::GetSelectionsModal, this,
std::placeholders::_1 ) );
}
@ -802,7 +799,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
// which prompts the user to continue with overwrite or abort)
if( newLibPath.Length() > 0 )
{
PCB_IO::RELEASER piSexpr( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<PCB_IO> piSexpr( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
for( FOOTPRINT* footprint : loadedFootprints )
{
@ -992,7 +989,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
try
{
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
pi->SaveBoard( tempFile, GetBoard(), nullptr );
}
@ -1092,7 +1089,7 @@ bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject
try
{
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
wxASSERT( pcbFileName.IsAbsolute() );
@ -1273,7 +1270,7 @@ void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
{
try
{
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::IPC2581 ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::IPC2581 ) );
pi->SetProgressReporter( &reporter );
pi->SaveBoard( tempFile, GetBoard(), &props );
return true;

View File

@ -90,7 +90,7 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
if( !pi )
continue;
@ -148,7 +148,7 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
if( !pi )
continue;
@ -174,7 +174,7 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
try
{
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( fileType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( fileType ) );
footprint = pi->ImportFootprint( fn.GetFullPath(), footprintName);
@ -346,7 +346,7 @@ wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
try
{
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( piType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( piType ) );
bool writable = false;
bool exists = false;
@ -658,7 +658,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
}
PCB_IO_MGR::PCB_FILE_T piType = PCB_IO_MGR::KICAD_SEXP;
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( piType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( piType ) );
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
{

View File

@ -337,8 +337,8 @@ bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
try
{
PCB_IO::RELEASER cur( PCB_IO_MGR::PluginFind( curType ) );
PCB_IO::RELEASER dst( PCB_IO_MGR::PluginFind( dstType ) );
IO_RELEASER<PCB_IO> cur( PCB_IO_MGR::PluginFind( curType ) );
IO_RELEASER<PCB_IO> dst( PCB_IO_MGR::PluginFind( dstType ) );
if( !cur )
{

View File

@ -333,58 +333,6 @@ public:
virtual ~PCB_IO()
{};
#ifndef SWIG
/**
* Releases a PLUGIN in the context of a potential thrown exception through its destructor.
*/
class RELEASER
{
PCB_IO* plugin;
// private assignment operator so it's illegal
RELEASER& operator=( RELEASER& aOther ) { return *this; }
// private copy constructor so it's illegal
RELEASER( const RELEASER& aOther ) : plugin( nullptr ) {}
public:
RELEASER( PCB_IO* aPlugin = nullptr ) :
plugin( aPlugin )
{
}
~RELEASER()
{
if( plugin )
release();
}
void release()
{
PCB_IO_MGR::PluginRelease( plugin );
plugin = nullptr;
}
void set( PCB_IO* aPlugin )
{
if( plugin )
release();
plugin = aPlugin;
}
operator PCB_IO* () const
{
return plugin;
}
PCB_IO* operator -> () const
{
return plugin;
}
};
#endif
protected:
PCB_IO( const wxString& aName ) : IO_BASE( aName ),
m_board( nullptr ),

View File

@ -71,16 +71,6 @@ PCB_IO* PCB_IO_MGR::PluginFind( PCB_FILE_T aFileType )
}
void PCB_IO_MGR::PluginRelease( PCB_IO* aPlugin )
{
// This function is a place holder for a future point in time where
// the plugin is a DLL/DSO. It could do reference counting, and then
// unload the DLL/DSO when count goes to zero.
delete aPlugin;
}
const wxString PCB_IO_MGR::ShowType( PCB_FILE_T aType )
{
const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
@ -129,7 +119,7 @@ PCB_IO_MGR::PCB_FILE_T PCB_IO_MGR::FindPluginTypeFromBoardPath( const wxString&
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
if( pi->CanReadBoard( aFileName ) )
return plugin.m_type;
@ -153,7 +143,7 @@ PCB_IO_MGR::PCB_FILE_T PCB_IO_MGR::GuessPluginTypeFromLibPath( const wxString& a
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
PCB_IO::RELEASER pi( plugin.m_createFunc() );
IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
if( pi->CanReadLibrary( aLibPath ) )
return plugin.m_type;
@ -167,10 +157,9 @@ BOARD* PCB_IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName, BOARD*
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
// release the PLUGIN even if an exception is thrown.
PCB_IO::RELEASER pi( PluginFind( aFileType ) );
IO_RELEASER<PCB_IO> pi( PluginFind( aFileType ) );
if( (PCB_IO*) pi ) // test pi->plugin
if( pi ) // test pi->plugin
{
pi->SetProgressReporter( aProgressReporter );
return pi->LoadBoard( aFileName, aAppendToMe, aProperties, aProject );
@ -183,10 +172,9 @@ BOARD* PCB_IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName, BOARD*
void PCB_IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard,
const STRING_UTF8_MAP* aProperties )
{
// release the PLUGIN even if an exception is thrown.
PCB_IO::RELEASER pi( PluginFind( aFileType ) );
IO_RELEASER<PCB_IO> pi( PluginFind( aFileType ) );
if( (PCB_IO*) pi ) // test pi->plugin
if( pi )
{
pi->SaveBoard( aFileName, aBoard, aProperties ); // virtual
return;

View File

@ -31,6 +31,7 @@
#include <wx/arrstr.h>
#include <i18n_utility.h>
#include <io/io_base.h>
#include <io/io_mgr.h>
class BOARD;
class PCB_IO;
@ -42,7 +43,7 @@ class PROGRESS_REPORTER;
/**
* A factory which returns an instance of a #PLUGIN.
*/
class PCB_IO_MGR
class PCB_IO_MGR : public IO_MGR
{
public:
@ -154,24 +155,13 @@ public:
* Return a #PLUGIN which the caller can use to import, export, save, or load
* design documents.
*
* The returned #PLUGIN, may be reference counted, so please call PluginRelease() when you
* are done using the returned #PLUGIN. It may or may not be code running from a DLL/DSO.
*
* @note The caller owns the returned object and must call PluginRelease when done using it.
* @note The caller owns the returned object.
*
* @param aFileType is from #PCB_FILE_T and tells which plugin to find.
* @return the plug in corresponding to \a aFileType or NULL if not found.
*/
static PCB_IO* PluginFind( PCB_FILE_T aFileType );
/**
* Release a #PLUGIN back to the system and may cause it to be unloaded from memory.
*
* @param aPlugin is the one to be released, and which is no longer usable
* after calling this.
*/
static void PluginRelease( PCB_IO* aPlugin );
/**
* Return a brief name for a plugin given \a aFileType enum.
*/

View File

@ -86,9 +86,6 @@ wxArrayString GetFootprints(const wxString& aNickName);
%include <pcb_io/pcb_io_mgr.h>
// ignore RELEASER as nested classes are still unsupported by swig
%ignore IO_MGR::RELEASER;
%include <pcb_io/pcb_io.h>

View File

@ -1049,7 +1049,7 @@ int PCB_CONTROL::AppendBoardFromFile( const TOOL_EVENT& aEvent )
PCB_IO_MGR::PCB_FILE_T pluginType =
PCB_IO_MGR::FindPluginTypeFromBoardPath( fileName, KICTL_KICAD_ONLY );
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( pluginType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
if( !pi )
return 1;
@ -1686,7 +1686,7 @@ int PCB_CONTROL::DdAppendBoard( const TOOL_EVENT& aEvent )
wxString filePath = fileName.GetFullPath();
PCB_IO_MGR::PCB_FILE_T pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( filePath );
PCB_IO::RELEASER pi( PCB_IO_MGR::PluginFind( pluginType ) );
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
if( !pi )
return 1;

View File

@ -101,7 +101,7 @@ void PCB_TEST_FRAME_BASE::SetBoard( std::shared_ptr<BOARD> b )
BOARD* PCB_TEST_FRAME_BASE::LoadAndDisplayBoard( const std::string& filename )
{
PCB_IO::RELEASER pi( new PCB_IO_KICAD_SEXPR );
IO_RELEASER<PCB_IO> pi( new PCB_IO_KICAD_SEXPR );
BOARD* brd = nullptr;
try

View File

@ -58,7 +58,7 @@ public:
virtual ~SCHEMATIC_TEST_FIXTURE()
{
m_schematic.Reset();
SCH_IO_MGR::ReleasePlugin( m_pi );
m_pi.reset();
}
protected:
@ -66,7 +66,7 @@ protected:
virtual wxFileName GetSchematicPath( const wxString& aBaseName );
SCHEMATIC m_schematic;
SCH_IO* m_pi;
IO_RELEASER<SCH_IO> m_pi;
SETTINGS_MANAGER m_manager;
};

View File

@ -35,9 +35,8 @@
*/
BOOST_AUTO_TEST_CASE( FindPlugin )
{
SCH_IO* pi = SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE );
BOOST_CHECK_NE( pi, nullptr );
SCH_IO_MGR::ReleasePlugin( pi );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) );
BOOST_CHECK_NE( pi.get(), nullptr );
}
@ -60,7 +59,7 @@ static wxFileName getEagleTestSchematic( const wxString& sch_file )
*/
BOOST_AUTO_TEST_CASE( Load )
{
SCH_IO* pi = SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) );
const auto fn = getEagleTestSchematic( "eagle-import-testfile.sch" );
@ -70,6 +69,4 @@ BOOST_AUTO_TEST_CASE( Load )
// This doesn't work with a null KiWay.
// const SCH_SHEET* sheet = pi->Load( fn.GetFullPath(), nullptr );
// BOOST_CHECK_NE( nullptr, sheet );
SCH_IO_MGR::ReleasePlugin( pi );
}

View File

@ -97,7 +97,7 @@ BOOST_FIXTURE_TEST_SUITE( Netlists, TEST_NETLIST_EXPORTER_KICAD_FIXTURE )
BOOST_AUTO_TEST_CASE( FindPlugin )
{
BOOST_CHECK_NE( m_pi, nullptr );
BOOST_CHECK_NE( m_pi.get(), nullptr );
}

View File

@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE( CheckCanReadBoard )
{
BOOST_TEST_CONTEXT( entry.m_name )
{
auto plugin = PCB_IO::RELEASER( PCB_IO_MGR::PluginFind( entry.m_type ) );
auto plugin = IO_RELEASER<PCB_IO>( PCB_IO_MGR::PluginFind( entry.m_type ) );
bool expectValidHeader = c.m_expected_type == entry.m_type;
BOOST_CHECK_EQUAL( plugin->CanReadBoard( dataPath ), expectValidHeader );

View File

@ -893,7 +893,7 @@ void PNS_LOG_VIEWER_FRAME::updatePnsPreviewItems( int iter )
static BOARD* loadBoard( const std::string& filename )
{
PLUGIN::RELEASER pi( new PCB_IO_KICAD_SEXPR );
IO_RELEASER<PCB_IO> pi( new PCB_IO_KICAD_SEXPR );
BOARD* brd = nullptr;
try