LCOV - code coverage report
Current view: top level - pression - pluginRegistry.cpp (source / functions) Hit Total Coverage
Test: Pression Lines: 90 128 70.3 %
Date: 2016-12-06 05:44:58 Functions: 19 27 70.4 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009, Cedric Stalder <cedric.stalder@gmail.com>
       3             :  *               2010-2013, Stefan Eilemann <eile@eyescale.ch>
       4             :  *
       5             :  * This file is part of Collage <https://github.com/Eyescale/Collage>
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or modify it under
       8             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       9             :  * by the Free Software Foundation.
      10             :  *
      11             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      13             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      14             :  * details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             :  */
      20             : 
      21             : #include "pluginRegistry.h"
      22             : 
      23             : #include "compressorInfo.h"
      24             : #include "log.h"
      25             : #include "plugin.h"
      26             : #include "pluginVisitor.h"
      27             : 
      28             : #include <lunchbox/algorithm.h>
      29             : #include <lunchbox/debug.h>
      30             : #include <lunchbox/file.h>
      31             : 
      32             : #ifdef _WIN32
      33             : #  include <lunchbox/os.h> // GetModuleFileName
      34             : #  include <direct.h>
      35             : #  define getcwd _getcwd
      36             : #else
      37             : #  include <unistd.h>   // for getcwd
      38             : #endif
      39             : 
      40             : #ifndef MAXPATHLEN
      41             : #  define MAXPATHLEN 1024
      42             : #endif
      43             : 
      44             : namespace pression
      45             : {
      46             : namespace detail
      47             : {
      48             : class PluginRegistry
      49             : {
      50             : public:
      51           1 :     PluginRegistry()
      52           1 :     {
      53           1 :         char* env = getenv( "EQ_PLUGIN_PATH" );
      54           2 :         std::string envString( env ? env : "" );
      55             : 
      56           1 :         if( envString.empty( ))
      57             :         {
      58             :             char cwd[MAXPATHLEN];
      59           1 :             directories.push_back( getcwd( cwd, MAXPATHLEN ));
      60             : 
      61             : #ifdef _WIN32
      62             :             if( GetModuleFileName( 0, cwd, MAXPATHLEN ) > 0 )
      63             :                 directories.push_back( lunchbox::getDirname( cwd ));
      64             : #else
      65             : #  ifdef Darwin
      66             :             env = getenv( "DYLD_LIBRARY_PATH" );
      67             : #  else
      68           1 :             env = getenv( "LD_LIBRARY_PATH" );
      69             : #  endif
      70           1 :         if( env )
      71           1 :             envString = env;
      72             : #  endif
      73             :         }
      74             : 
      75             : #ifdef _WIN32
      76             :         const char separator = ';';
      77             : #else
      78           1 :         const char separator = ':';
      79             : #endif
      80             : 
      81          49 :         while( !envString.empty( ))
      82             :         {
      83          24 :             size_t nextPos = envString.find( separator );
      84          24 :             if ( nextPos == std::string::npos )
      85           1 :                 nextPos = envString.size();
      86             : 
      87          48 :             std::string path = envString.substr( 0, nextPos );
      88          24 :             if ( nextPos == envString.size( ))
      89           1 :                 envString = "";
      90             :             else
      91          23 :                 envString = envString.substr( nextPos + 1, envString.size() );
      92             : 
      93          24 :             if( !path.empty( ))
      94          24 :                 directories.push_back( path );
      95             :         }
      96           1 :     }
      97             : 
      98           1 :     ~PluginRegistry()
      99           1 :     {
     100           1 :         LBASSERTINFO( plugins.empty(), "Plugin registry not de-initialized" );
     101           1 :     }
     102             : 
     103             :     Strings directories;
     104             :     Plugins plugins;
     105             : };
     106             : }
     107             : 
     108           1 : PluginRegistry::PluginRegistry()
     109           1 :     : impl_( new detail::PluginRegistry )
     110           1 : {}
     111             : 
     112           2 : PluginRegistry::~PluginRegistry()
     113             : {
     114           1 :     delete impl_;
     115           1 : }
     116             : 
     117           9 : const Strings& PluginRegistry::getDirectories() const
     118             : {
     119           9 :     return impl_->directories;
     120             : }
     121             : 
     122           9 : void  PluginRegistry::addDirectory( const std::string& path )
     123             : {
     124           9 :     impl_->directories.push_back( path );
     125           9 : }
     126             : 
     127           0 : void PluginRegistry::removeDirectory( const std::string& path )
     128             : {
     129           0 :     Strings::iterator i = lunchbox::find( impl_->directories, path );
     130           0 :     if( i != impl_->directories.end( ))
     131           0 :         impl_->directories.erase( i );
     132           0 : }
     133             : 
     134           1 : bool PluginRegistry::addLunchboxPlugins()
     135             : {
     136             : #ifdef PRESSION_DSO_NAME
     137             :     return
     138           4 :         addPlugin( PRESSION_DSO_NAME ) || // Found by LDD
     139             :         // Hard-coded compile locations as backup:
     140           1 :         addPlugin( std::string( PRESSION_BUILD_DIR ) + "lib/" +
     141           3 :                    PRESSION_DSO_NAME ) ||
     142             : #  ifdef NDEBUG
     143             :         addPlugin( std::string( PRESSION_BUILD_DIR ) +
     144             :                    "lib/Release/" + PRESSION_DSO_NAME )
     145             : #  else
     146           1 :         addPlugin( std::string( PRESSION_BUILD_DIR ) + "lib/Debug/" +
     147           1 :                    PRESSION_DSO_NAME )
     148             : #  endif
     149             :         ;
     150             : #endif
     151             :     return false;
     152             : }
     153             : 
     154           1 : void PluginRegistry::init()
     155             : {
     156             :     // for each directory
     157         105 :     for( StringsCIter i = impl_->directories.begin();
     158          70 :          i != impl_->directories.end(); ++i )
     159             :     {
     160          34 :         const std::string& dir = *i;
     161          34 :         LBLOG( LOG_PLUGIN ) << "Searching plugins in " << dir << std::endl;
     162             : 
     163             : #ifdef _WIN32
     164             :         const Strings& files =
     165             :                 lunchbox::searchDirectory( dir, ".*Compressor.*\\.dll" );
     166             :         const char DIRSEP = '\\';
     167             : #elif defined (Darwin)
     168             :         const Strings& files =
     169             :                 lunchbox::searchDirectory( dir, "lib.*Compressor.*\\.dylib" );
     170             :         const char DIRSEP = '/';
     171             : #else
     172             :         const Strings& files =
     173          68 :                 lunchbox::searchDirectory( dir, "lib.*Compressor.*\\.so" );
     174          34 :         const char DIRSEP = '/';
     175             : #endif
     176             :         // for each file found in the directory
     177          34 :         for( StringsCIter j = files.begin(); j != files.end(); ++j )
     178             :         {
     179             :             // build path + name of library
     180           0 :             const std::string libraryName = dir.empty() ? *j : dir+DIRSEP+*j;
     181           0 :             addPlugin( libraryName );
     182             :         }
     183             :     }
     184           1 : }
     185             : 
     186             : namespace
     187             : {
     188           1 : Plugin* _loadPlugin( const std::string& filename, const Strings& directories )
     189             : {
     190           1 :     if( filename.size() < 3 )
     191           0 :         return 0;
     192             : 
     193           1 :     Plugin* plugin = new Plugin( filename );
     194           1 :     if( plugin->isGood( ))
     195           1 :         return plugin;
     196           0 :     delete plugin;
     197             : 
     198           0 :     if( filename[0] == '/' || filename[1] == ':' /* Win drive letter */ )
     199           0 :         return 0;
     200             : 
     201           0 :     for( StringsCIter i = directories.begin(); i != directories.end(); ++i )
     202             :     {
     203           0 :         const std::string& dir = *i;
     204           0 :         plugin = new Plugin( dir + "/" + filename );
     205           0 :         if( plugin->isGood( ))
     206           0 :             return plugin;
     207           0 :         delete plugin;
     208             :     }
     209           0 :     return 0;
     210             : }
     211             : }
     212             : 
     213           1 : bool PluginRegistry::addPlugin( const std::string& filename )
     214             : {
     215           1 :     Plugin* plugin = _loadPlugin( filename, impl_->directories );
     216           1 :     if( !plugin )
     217           0 :         return false;
     218             : 
     219           1 :     const CompressorInfos& infos = plugin->getInfos();
     220           1 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i)
     221             :     {
     222           0 :         const CompressorInfos& infos2 = (*i)->getInfos();
     223             : 
     224             :         // Simple test to avoid loading the same dll twice
     225           0 :         if( infos.front().name == infos2.front().name )
     226             :         {
     227           0 :             delete plugin;
     228           0 :             return true;
     229             :         }
     230             :     }
     231             : 
     232           1 :     impl_->plugins.push_back( plugin );
     233           1 :     LBLOG( LOG_PLUGIN ) << "Found " << plugin->getInfos().size()
     234           1 :                         << " compression engines in " << filename << std::endl;
     235           1 :     return true;
     236             : }
     237             : 
     238           1 : void PluginRegistry::exit()
     239             : {
     240           2 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i)
     241             :     {
     242           1 :         Plugin* plugin = *i;
     243           1 :         delete plugin;
     244             :     }
     245             : 
     246           1 :     impl_->plugins.clear();
     247           1 : }
     248             : 
     249             : namespace
     250             : {
     251         370 : template< class P,  class I > class Finder : public PluginVisitorT< P, I >
     252             : {
     253             : public:
     254         370 :     explicit Finder( const uint32_t name ) : plugin( 0 ), name_( name ) {}
     255        6956 :     virtual VisitorResult visit( P& candidate, I& info )
     256             :     {
     257        6956 :         if( info.name != name_ )
     258        6586 :             return TRAVERSE_CONTINUE;
     259             : 
     260         370 :         plugin = &candidate;
     261         370 :         return TRAVERSE_TERMINATE;
     262             :     }
     263             : 
     264             :     P* plugin;
     265             : private:
     266             :     const uint32_t name_;
     267             : };
     268             : }
     269             : 
     270         370 : Plugin* PluginRegistry::findPlugin( const uint32_t name )
     271             : {
     272         740 :     Finder< Plugin, EqCompressorInfo > finder( name );
     273         370 :     accept( finder );
     274         740 :     return finder.plugin;
     275             : }
     276             : 
     277           0 : const Plugin* PluginRegistry::findPlugin( const uint32_t name ) const
     278             : {
     279           0 :     Finder< const Plugin, const EqCompressorInfo > finder( name );
     280           0 :     accept( finder );
     281           0 :     return finder.plugin;
     282             : }
     283             : 
     284         370 : VisitorResult PluginRegistry::accept( PluginVisitor& visitor )
     285             : {
     286         370 :     VisitorResult result = TRAVERSE_CONTINUE;
     287         370 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i )
     288         370 :         switch( (*i)->accept( visitor ))
     289             :         {
     290             :         case TRAVERSE_TERMINATE:
     291         370 :             return TRAVERSE_TERMINATE;
     292             :         case TRAVERSE_PRUNE:
     293           0 :             result = TRAVERSE_PRUNE;
     294             :         default:
     295           0 :             break;
     296             :         }
     297             : 
     298           0 :     return result;
     299             : }
     300           0 : VisitorResult PluginRegistry::accept( ConstPluginVisitor& visitor ) const
     301             : {
     302           0 :     VisitorResult result = TRAVERSE_CONTINUE;
     303           0 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i )
     304           0 :         switch( (*i)->accept( visitor ))
     305             :         {
     306             :         case TRAVERSE_TERMINATE:
     307           0 :             return TRAVERSE_TERMINATE;
     308             :         case TRAVERSE_PRUNE:
     309           0 :             result = TRAVERSE_PRUNE;
     310             :         case TRAVERSE_CONTINUE:
     311           0 :             break;
     312             :         }
     313             : 
     314           0 :     return result;
     315             : }
     316             : 
     317           2 : const Plugins& PluginRegistry::getPlugins() const
     318             : {
     319           2 :     return impl_->plugins;
     320             : }
     321             : 
     322           3 : }

Generated by: LCOV version 1.11