LCOV - code coverage report
Current view: top level - lunchbox - file.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 29 93 31.2 %
Date: 2016-11-11 05:21:33 Functions: 7 14 50.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2016, Cedric Stalder <cedric.stalder@gmail.com>
       3             :  *                          Stefan Eilemann <eile@equalizergraphics.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "file.h"
      20             : 
      21             : #include "debug.h"
      22             : #include "memoryMap.h"
      23             : #include "os.h"
      24             : 
      25             : #include <servus/serializable.h>
      26             : #include <servus/uint128_t.h>
      27             : #include <boost/algorithm/string/predicate.hpp>
      28             : #include <boost/filesystem/path.hpp>
      29             : #include <boost/foreach.hpp>
      30             : #include <boost/regex.hpp>
      31             : #include <boost/tokenizer.hpp>
      32             : #include <sys/stat.h>
      33             : #ifdef _MSC_VER
      34             : #  include <windows.h>
      35             : #  include <direct.h>
      36             : #  define getcwd _getcwd
      37             : #  define MAXPATHLEN _MAX_PATH
      38             : #elif __APPLE__
      39             : #  include <dirent.h>
      40             : #  include <mach-o/dyld.h>
      41             : #else
      42             : #  include <dirent.h>
      43             : #  include <limits.h>
      44             : #  include <unistd.h>
      45             : #endif
      46             : 
      47             : namespace lunchbox
      48             : {
      49           1 : Strings searchDirectory( const std::string& directory,
      50             :                          const std::string& pattern )
      51             : {
      52           1 :     Strings files;
      53           2 :     const boost::regex regex( pattern );
      54             : 
      55             : #ifdef _MSC_VER
      56             :     WIN32_FIND_DATA file;
      57             :     const std::string search = directory.empty() ? "*.*" : directory + "\\*.*";
      58             :     HANDLE hSearch = FindFirstFile( search.c_str(), &file );
      59             : 
      60             :     if( hSearch == INVALID_HANDLE_VALUE )
      61             :     {
      62             :         LBVERB << "Error finding the first file to match " << pattern << " in "
      63             :                << directory << std::endl;
      64             :         FindClose( hSearch );
      65             :         return files;
      66             :     }
      67             : 
      68             :     if( boost::regex_match( file.cFileName, regex ))
      69             :         files.push_back( file.cFileName );
      70             :     while( FindNextFile( hSearch, &file ))
      71             :     {
      72             :         if( boost::regex_match( file.cFileName, regex ))
      73             :             files.push_back( file.cFileName );
      74             :     }
      75             :     FindClose( hSearch );
      76             : 
      77             : #else
      78             : 
      79           1 :     DIR* dir = opendir( directory.c_str() );
      80           1 :     if( !dir )
      81             :     {
      82           0 :         LBVERB << "Can't open directory " << directory << std::endl;
      83           0 :         return files;
      84             :     }
      85             : 
      86             :     struct dirent* entry;
      87             : 
      88          71 :     while(( entry = readdir( dir )) != 0 )
      89             :     {
      90          70 :         const std::string candidate( entry->d_name );
      91          35 :         if( boost::regex_match( candidate, regex ))
      92          35 :             files.push_back( entry->d_name );
      93             :     }
      94             : 
      95           1 :     closedir(dir);
      96             : #endif
      97           1 :     return files;
      98             : }
      99             : 
     100           1 : std::string getFilename( const std::string& filename )
     101             : {
     102           1 :     const size_t lastSeparator = filename.find_last_of("/\\");
     103           1 :     if( lastSeparator == std::string::npos )
     104           0 :         return filename;
     105             :     // lastSeparator + 1 may be at most equal to filename.size(), which is good
     106           1 :     return filename.substr( lastSeparator + 1 );
     107             : }
     108             : 
     109           0 : std::string getDirname( const std::string& filename )
     110             : {
     111           0 :     const size_t lastSeparator = filename.find_last_of("/\\");
     112           0 :     if( lastSeparator == std::string::npos )
     113           0 :         return "./"; // The final separator is always in the output.
     114             :     // The separator will be part of the output.
     115             :     // If lastSeparator == 0 (e.g. /file-or-dir) it will assume that the rest
     116             :     // of the path is a filename.
     117           0 :     return filename.substr( 0, lastSeparator + 1 );
     118             : }
     119             : 
     120           3 : std::string getExecutableDir()
     121             : {
     122             :     // http://stackoverflow.com/questions/933850
     123             : #ifdef _MSC_VER
     124             :     char result[MAX_PATH];
     125             :     const std::string execPath( result, GetModuleFileName( NULL, result,
     126             :                                                            MAX_PATH ));
     127             : #elif __APPLE__
     128             :     char result[PATH_MAX+1];
     129             :     uint32_t size = sizeof(result);
     130             :     if( _NSGetExecutablePath( result, &size ) != 0 )
     131             :         return std::string();
     132             :     const std::string execPath( result );
     133             : #else
     134             :     char result[PATH_MAX];
     135           3 :     const ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
     136           3 :     if( count < 0 )
     137             :     {
     138             :         // Not all UNIX have /proc/self/exe
     139           0 :         LBWARN << "Could not find absolute executable path" << std::endl;
     140           0 :         return "";
     141             :     }
     142           6 :     const std::string execPath( result, count );
     143             : #endif
     144             : 
     145           6 :     const boost::filesystem::path path( execPath );
     146             : #ifdef __APPLE__
     147             :     if( boost::algorithm::ends_with( path.parent_path().string(),
     148             :                                      "Contents/MacOS" ))
     149             :     {
     150             :         return
     151             :           path.parent_path().parent_path().parent_path().parent_path().string();
     152             :     }
     153             : #endif
     154           3 :     return path.parent_path().string();
     155             : }
     156             : 
     157           1 : std::string getWorkDir()
     158             : {
     159             :     char cwd[ MAXPATHLEN ];
     160           1 :     return ::getcwd( cwd, MAXPATHLEN );
     161             : }
     162             : 
     163           1 : std::string getRootDir()
     164             : {
     165           2 :     const std::string& exeDir = getExecutableDir();
     166           1 :     if( exeDir.empty( ))
     167           0 :         return exeDir;
     168             : 
     169           2 :     const boost::filesystem::path path( exeDir );
     170             : #ifdef _MSC_VER
     171             :     const Strings buildTypes { "debug", "relwithdebinfo", "release",
     172             :                                "minsizerel" };
     173             :     std::string buildType( path.stem().string( ));
     174             :     std::transform( buildType.begin(), buildType.end(), buildType.begin(),
     175             :                     ::tolower );
     176             :     if( std::find( buildTypes.begin(), buildTypes.end(),
     177             :                    buildType ) != buildTypes.end( ))
     178             :     {
     179             :         return path.parent_path().parent_path().string();
     180             :     }
     181             : #endif
     182           1 :     return path.parent_path().string();
     183             : }
     184             : 
     185           0 : std::string getLibraryPath()
     186             : {
     187           0 :     const std::string& exeDir = getExecutableDir();
     188           0 :     if( exeDir.empty( ))
     189           0 :         return exeDir;
     190             : 
     191             : #ifdef _MSC_VER
     192             :     return exeDir;
     193             : #elif __APPLE__
     194             :     const boost::filesystem::path path( exeDir );
     195             : 
     196             :     // foo.app/Contents/MacOS/foo
     197             :     if( boost::algorithm::ends_with( exeDir, ".app/Contents/MacOS" ))
     198             :         return path.parent_path().parent_path().parent_path().parent_path().
     199             :                    string() + "/lib";
     200             :     return path.parent_path().string() + "/lib";
     201             : #else
     202           0 :     const boost::filesystem::path path( exeDir );
     203           0 :     return path.parent_path().string() + "/lib";
     204             : #endif
     205             : }
     206             : 
     207             : #define STDSTRING( macro ) std::string( STRINGIFY( macro ))
     208             : #define STRINGIFY( foo ) #foo
     209             : 
     210           0 : Strings getLibraryPaths()
     211             : {
     212           0 :     Strings paths;
     213           0 :     const std::string& appPath = getLibraryPath();
     214           0 :     if( !appPath.empty( ))
     215           0 :         paths.push_back( appPath );
     216             : 
     217             : #ifdef _MSC_VER
     218             :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/bin" );
     219             :     const char* env = ::getenv( "PATH" );
     220             : #elif __APPLE__
     221             :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/lib" );
     222             :     const char* env = ::getenv( "DYLD_LIBRARY_PATH" );
     223             : #else
     224           0 :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/lib" );
     225           0 :     const char* env = ::getenv( "LD_LIBRARY_PATH" );
     226             : #endif
     227             : 
     228           0 :     if( !env )
     229           0 :         return paths;
     230             : 
     231           0 :     const std::string envString( env );
     232             : #ifdef _MSC_VER
     233             :     boost::char_separator< char > separator(";");
     234             : #else
     235           0 :     boost::char_separator< char > separator(":");
     236             : #endif
     237             :     const boost::tokenizer< boost::char_separator< char > >
     238           0 :         tokens( envString, separator );
     239           0 :     BOOST_FOREACH( const std::string& token, tokens )
     240           0 :         paths.push_back( token );
     241             : 
     242           0 :     return paths;
     243             : }
     244             : 
     245           0 : bool saveBinary( const servus::Serializable& object, const std::string& file )
     246             : {
     247           0 :     const servus::Serializable::Data& data = object.toBinary();
     248           0 :     MemoryMap mmap( file, sizeof( uint128_t ) + data.size );
     249           0 :     if( !mmap.getAddress( ))
     250           0 :         return false;
     251           0 :     const uint128_t& id = object.getTypeIdentifier();
     252           0 :     ::memcpy( mmap.getAddress(), &id, sizeof( id ));
     253           0 :     ::memcpy( mmap.getAddress< uint8_t >() + sizeof( id ),
     254           0 :               data.ptr.get(), data.size );
     255           0 :     return true;
     256             : }
     257             : 
     258           0 : bool loadBinary( servus::Serializable& object, const std::string& file )
     259             : {
     260           0 :     const MemoryMap mmap( file );
     261           0 :     if( !mmap.getAddress() || mmap.getSize() < sizeof( uint128_t ) ||
     262           0 :         *mmap.getAddress< uint128_t >() != object.getTypeIdentifier( ))
     263             :     {
     264           0 :         return false;
     265             :     }
     266             : 
     267           0 :     object.fromBinary( mmap.getAddress< uint8_t >() + sizeof( uint128_t ),
     268           0 :                        mmap.getSize() - sizeof( uint128_t ));
     269           0 :     return true;
     270             : }
     271             : 
     272           0 : bool saveAscii( const servus::Serializable& object, const std::string& file )
     273             : {
     274           0 :     const std::string& data = object.toJSON();
     275           0 :     MemoryMap mmap( file, data.length( ));
     276           0 :     if( !mmap.getAddress( ))
     277           0 :         return false;
     278           0 :     ::memcpy( mmap.getAddress(), &data[0], data.length( ));
     279           0 :     return true;
     280             : }
     281             : 
     282           0 : bool loadAscii( servus::Serializable& object, const std::string& file )
     283             : {
     284           0 :     const MemoryMap mmap( file );
     285           0 :     if( !mmap.getAddress( ))
     286           0 :         return false;
     287           0 :     const uint8_t* ptr = mmap.getAddress< uint8_t >();
     288           0 :     object.fromJSON( std::string( ptr, ptr + mmap.getSize( )));
     289           0 :     return true;
     290             : }
     291             : 
     292             : 
     293          72 : }

Generated by: LCOV version 1.11