LCOV - code coverage report
Current view: top level - lunchbox - file.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 28 96 29.2 %
Date: 2016-03-29 17:09:06 Functions: 6 13 46.2 %

          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             : #elif __APPLE__
      36             : #  include <dirent.h>
      37             : #  include <mach-o/dyld.h>
      38             : #else
      39             : #  include <dirent.h>
      40             : #  include <limits.h>
      41             : #  include <unistd.h>
      42             : #endif
      43             : 
      44             : namespace lunchbox
      45             : {
      46           1 : Strings searchDirectory( const std::string& directory,
      47             :                          const std::string& pattern )
      48             : {
      49           1 :     Strings files;
      50           2 :     const boost::regex regex( pattern );
      51             : 
      52             : #ifdef _MSC_VER
      53             :     WIN32_FIND_DATA file;
      54             :     const std::string search = directory.empty() ? "*.*" : directory + "\\*.*";
      55             :     HANDLE hSearch = FindFirstFile( search.c_str(), &file );
      56             : 
      57             :     if( hSearch == INVALID_HANDLE_VALUE )
      58             :     {
      59             :         LBVERB << "Error finding the first file to match " << pattern << " in "
      60             :                << directory << std::endl;
      61             :         FindClose( hSearch );
      62             :         return files;
      63             :     }
      64             : 
      65             :     if( boost::regex_match( file.cFileName, regex ))
      66             :         files.push_back( file.cFileName );
      67             :     while( FindNextFile( hSearch, &file ))
      68             :     {
      69             :         if( boost::regex_match( file.cFileName, regex ))
      70             :             files.push_back( file.cFileName );
      71             :     }
      72             :     FindClose( hSearch );
      73             : 
      74             : #else
      75             : 
      76           1 :     DIR* dir = opendir( directory.c_str() );
      77           1 :     if( !dir )
      78             :     {
      79           0 :         LBVERB << "Can't open directory " << directory << std::endl;
      80           0 :         return files;
      81             :     }
      82             : 
      83             :     struct dirent* entry;
      84             : 
      85          41 :     while(( entry = readdir( dir )) != 0 )
      86             :     {
      87          39 :         const std::string candidate( entry->d_name );
      88          39 :         if( boost::regex_match( candidate, regex ))
      89          39 :             files.push_back( entry->d_name );
      90          39 :     }
      91             : 
      92           1 :     closedir(dir);
      93             : #endif
      94           1 :     return files;
      95             : }
      96             : 
      97           1 : std::string getFilename( const std::string& filename )
      98             : {
      99             : #ifdef _MSC_VER
     100             :     const size_t lastSeparator = filename.find_last_of('\\');
     101             : #else
     102           1 :     const size_t lastSeparator = filename.find_last_of('/');
     103             : #endif
     104           1 :     if( lastSeparator == std::string::npos )
     105           0 :         return filename;
     106             :     // lastSeparator + 1 may be at most equal to filename.size(), which is good
     107           1 :     return filename.substr( lastSeparator + 1 );
     108             : }
     109             : 
     110           0 : std::string getDirname( const std::string& filename )
     111             : {
     112             : #ifdef _MSC_VER
     113             :     const size_t lastSeparator = filename.find_last_of('\\');
     114             : #else
     115           0 :     const size_t lastSeparator = filename.find_last_of('/');
     116             : #endif
     117           0 :     if( lastSeparator == std::string::npos )
     118           0 :         return "./"; // The final separator is always in the output.
     119             :     // The separator will be part of the output.
     120             :     // If lastSeparator == 0 (e.g. /file-or-dir) it will assume that the rest
     121             :     // of the path is a filename.
     122           0 :     return filename.substr( 0, lastSeparator + 1 );
     123             : }
     124             : 
     125           2 : std::string getExecutablePath()
     126             : {
     127             :     // http://stackoverflow.com/questions/933850
     128             : #ifdef _MSC_VER
     129             :     char result[MAX_PATH];
     130             :     const std::string execPath( result, GetModuleFileName( NULL, result,
     131             :                                                            MAX_PATH ));
     132             : #elif __APPLE__
     133             :     char result[PATH_MAX+1];
     134             :     uint32_t size = sizeof(result);
     135             :     if( _NSGetExecutablePath( result, &size ) != 0 )
     136             :         return std::string();
     137             :     const std::string execPath( result );
     138             : #else
     139             :     char result[PATH_MAX];
     140           2 :     const ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
     141           2 :     if( count < 0 )
     142             :     {
     143             :         // Not all UNIX have /proc/self/exe
     144           0 :         LBWARN << "Could not find absolute executable path" << std::endl;
     145           0 :         return "";
     146             :     }
     147           2 :     const std::string execPath( result, count );
     148             : #endif
     149             : 
     150           4 :     const boost::filesystem::path path( execPath );
     151             : #ifdef __APPLE__
     152             :     if( boost::algorithm::ends_with( path.parent_path().string(),
     153             :                                      "Contents/MacOS" ))
     154             :     {
     155             :         return
     156             :           path.parent_path().parent_path().parent_path().parent_path().string();
     157             :     }
     158             : #endif
     159           4 :     return path.parent_path().string();
     160             : }
     161             : 
     162           1 : std::string getRootPath()
     163             : {
     164           1 :     const std::string& exePath = getExecutablePath();
     165           1 :     if( exePath.empty( ))
     166           0 :         return exePath;
     167             : 
     168           2 :     const boost::filesystem::path path( exePath );
     169             : #ifdef _MSC_VER
     170             :     const Strings buildTypes { "debug", "relwithdebinfo", "release",
     171             :                                "minsizerel" };
     172             :     std::string buildType( path.stem().string( ));
     173             :     std::transform( buildType.begin(), buildType.end(), buildType.begin(),
     174             :                     ::tolower );
     175             :     if( std::find( buildTypes.begin(), buildTypes.end(),
     176             :                    buildType ) != buildTypes.end( ))
     177             :     {
     178             :         return path.parent_path().parent_path().string();
     179             :     }
     180             : #endif
     181           2 :     return path.parent_path().string();
     182             : }
     183             : 
     184           0 : std::string getLibraryPath()
     185             : {
     186           0 :     const std::string& exePath = getExecutablePath();
     187           0 :     if( exePath.empty( ))
     188           0 :         return exePath;
     189             : 
     190             : #ifdef _MSC_VER
     191             :     return exePath;
     192             : #elif __APPLE__
     193             :     const boost::filesystem::path path( exePath );
     194             : 
     195             :     // foo.app/Contents/MacOS/foo
     196             :     if( boost::algorithm::ends_with( exePath, ".app/Contents/MacOS" ))
     197             :         return path.parent_path().parent_path().parent_path().parent_path().
     198             :                    string() + "/lib";
     199             :     return path.parent_path().string() + "/lib";
     200             : #else
     201           0 :     const boost::filesystem::path path( exePath );
     202           0 :     return path.parent_path().string() + "/lib";
     203             : #endif
     204             : }
     205             : 
     206             : #define STDSTRING( macro ) std::string( STRINGIFY( macro ))
     207             : #define STRINGIFY( foo ) #foo
     208             : 
     209           0 : Strings getLibraryPaths()
     210             : {
     211           0 :     Strings paths;
     212           0 :     const std::string& appPath = getLibraryPath();
     213           0 :     if( !appPath.empty( ))
     214           0 :         paths.push_back( appPath );
     215             : 
     216             : #ifdef _MSC_VER
     217             :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/bin" );
     218             :     const char* env = ::getenv( "PATH" );
     219             : #elif __APPLE__
     220             :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/lib" );
     221             :     const char* env = ::getenv( "DYLD_LIBRARY_PATH" );
     222             : #else
     223           0 :     paths.push_back( STDSTRING( CMAKE_INSTALL_PREFIX ) + "/lib" );
     224           0 :     const char* env = ::getenv( "LD_LIBRARY_PATH" );
     225             : #endif
     226             : 
     227           0 :     if( !env )
     228           0 :         return paths;
     229             : 
     230           0 :     const std::string envString( env );
     231             : #ifdef _MSC_VER
     232             :     boost::char_separator< char > separator(";");
     233             : #else
     234           0 :     boost::char_separator< char > separator(":");
     235             : #endif
     236             :     const boost::tokenizer< boost::char_separator< char > >
     237           0 :         tokens( envString, separator );
     238           0 :     BOOST_FOREACH( const std::string& token, tokens )
     239           0 :         paths.push_back( token );
     240             : 
     241           0 :     return paths;
     242             : }
     243             : 
     244           0 : bool saveBinary( const servus::Serializable& object, const std::string& file )
     245             : {
     246           0 :     object.notifyRequested();
     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 :     object.notifyUpdated();
     270           0 :     return true;
     271             : }
     272             : 
     273           0 : bool saveAscii( const servus::Serializable& object, const std::string& file )
     274             : {
     275           0 :     object.notifyRequested();
     276           0 :     const std::string& data = object.toJSON();
     277           0 :     MemoryMap mmap( file, data.length( ));
     278           0 :     if( !mmap.getAddress( ))
     279           0 :         return false;
     280           0 :     ::memcpy( mmap.getAddress(), &data[0], data.length( ));
     281           0 :     return true;
     282             : }
     283             : 
     284           0 : bool loadAscii( servus::Serializable& object, const std::string& file )
     285             : {
     286           0 :     const MemoryMap mmap( file );
     287           0 :     if( !mmap.getAddress( ))
     288           0 :         return false;
     289           0 :     const uint8_t* ptr = mmap.getAddress< uint8_t >();
     290           0 :     object.fromJSON( std::string( ptr, ptr + mmap.getSize( )));
     291           0 :     object.notifyUpdated();
     292           0 :     return true;
     293             : }
     294             : 
     295             : 
     296          81 : }

Generated by: LCOV version 1.11