refactoring: replaced manual plugin registration with link-time plugin binding

This commit is contained in:
Tomasz Włostowski 2017-10-31 00:21:16 +01:00
parent 8a09a1d329
commit 7a44ab914d
8 changed files with 115 additions and 69 deletions

View File

@ -2254,3 +2254,7 @@ bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
}
*/
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN* { return new EAGLE_PLUGIN; } );
};

View File

@ -594,6 +594,10 @@ void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL )
}
}
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } );
};
#if 0 && defined(STANDALONE)
int main( int argc, char** argv )

View File

@ -1141,3 +1141,7 @@ bool GPCB_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
return m_cache->IsWritable();
}
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN* { return new GPCB_PLUGIN; } );
};

View File

@ -60,35 +60,7 @@ PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType )
// This implementation is subject to change, any magic is allowed here.
// The public IO_MGR API is the only pertinent public information.
switch( aFileType )
{
case LEGACY:
return new LEGACY_PLUGIN();
case KICAD_SEXP:
return new PCB_IO();
case EAGLE:
return new EAGLE_PLUGIN();
case PCAD:
return new PCAD_PLUGIN();
case GEDA_PCB:
return new GPCB_PLUGIN();
case GITHUB:
#if defined(BUILD_GITHUB_PLUGIN)
return new GITHUB_PLUGIN();
#else
THROW_IO_ERROR( "BUILD_GITHUB_PLUGIN not enabled in cmake build environment" );
#endif
case FILE_TYPE_NONE:
return NULL;
}
return NULL;
return PLUGIN_REGISTRY::Instance()->Create( aFileType );
}
@ -108,29 +80,17 @@ const wxString IO_MGR::ShowType( PCB_FILE_T aType )
// text spellings. If you change the spellings, you will obsolete
// library tables, so don't do change, only additions are ok.
switch( aType )
const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
for( const auto& plugin : plugins )
{
default:
return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType );
case LEGACY:
return wxString( wxT( "Legacy" ) );
case KICAD_SEXP:
return wxString( wxT( "KiCad" ) );
case EAGLE:
return wxString( wxT( "Eagle" ) );
case PCAD:
return wxString( wxT( "P-Cad" ) );
case GEDA_PCB:
return wxString( wxT( "Geda-PCB" ) );
case GITHUB:
return wxString( wxT( "Github" ) );
if ( plugin.m_type == aType )
{
return plugin.m_name;
}
}
return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType );
}
@ -140,25 +100,15 @@ IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
// text spellings. If you change the spellings, you will obsolete
// library tables, so don't do change, only additions are ok.
if( aType == wxT( "KiCad" ) )
return KICAD_SEXP;
const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
if( aType == wxT( "Legacy" ) )
return LEGACY;
if( aType == wxT( "Eagle" ) )
return EAGLE;
if( aType == wxT( "P-Cad" ) )
return PCAD;
if( aType == wxT( "Geda-PCB" ) )
return GEDA_PCB;
if( aType == wxT( "Github" ) )
return GITHUB;
// wxASSERT( blow up here )
for( const auto& plugin : plugins )
{
if ( plugin.m_name == aType )
{
return plugin.m_type;
}
}
return PCB_FILE_T( -1 );
}

View File

@ -27,7 +27,7 @@
#include <richio.h>
#include <map>
#include <functional>
class BOARD;
class PLUGIN;
@ -65,6 +65,78 @@ public:
FILE_TYPE_NONE
};
/**
* Class PLUGIN_REGISTRY
* Holds a list of available plugins, created using a singleton REGISTER_PLUGIN object.
* This way, plugins can be added link-time.
*/
class PLUGIN_REGISTRY
{
public:
struct ENTRY
{
PCB_FILE_T m_type;
std::function<PLUGIN*(void)> m_createFunc;
wxString m_name;
};
static PLUGIN_REGISTRY *Instance()
{
static PLUGIN_REGISTRY *self = nullptr;
if( !self )
{
self = new PLUGIN_REGISTRY;
}
return self;
}
void Register( PCB_FILE_T aType, const wxString& aName, std::function<PLUGIN*(void)> aCreateFunc )
{
ENTRY ent;
ent.m_type = aType;
ent.m_createFunc = aCreateFunc;
ent.m_name = aName;
m_plugins.push_back( ent );
}
PLUGIN* Create( PCB_FILE_T aFileType ) const
{
for( auto& ent : m_plugins )
{
if ( ent.m_type == aFileType )
{
return ent.m_createFunc();
}
}
return nullptr;
}
const std::vector<ENTRY>& AllPlugins() const
{
return m_plugins;
}
private:
std::vector<ENTRY> m_plugins;
};
/**
* Class REGISTER_PLUGIN
* Registers a plugin. Declare as a static variable in an anonymous namespace.
* @param aType: type of the plugin
* @param aName: name of the file format
* @param aCreateFunc: function that creates a new object for the plugin.
*/
struct REGISTER_PLUGIN
{
REGISTER_PLUGIN( PCB_FILE_T aType, const wxString& aName, std::function<PLUGIN*(void)> aCreateFunc )
{
PLUGIN_REGISTRY::Instance()->Register( aType, aName, aCreateFunc );
}
};
/**
* Function PluginFind
* returns a PLUGIN which the caller can use to import, export, save, or load

View File

@ -2214,3 +2214,7 @@ bool PCB_IO::IsFootprintLibWritable( const wxString& aLibraryPath )
return m_cache->IsWritable();
}
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN* { return new PCB_IO; } );
};

View File

@ -3505,3 +3505,7 @@ LEGACY_PLUGIN::~LEGACY_PLUGIN()
delete m_cache;
delete m_mapping;
}
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN* { return new LEGACY_PLUGIN; } );
};

View File

@ -89,3 +89,7 @@ BOARD* PCAD_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const P
return m_board;
}
namespace {
static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN* { return new PCAD_PLUGIN; } );
};