LCOV - code coverage report
Current view: top level - lunchbox - file.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 29 93 31.2 %
Date: 2017-08-03 05:21:41 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 <boost/algorithm/string/predicate.hpp>
      26             : #include <boost/filesystem/path.hpp>
      27             : #include <boost/foreach.hpp>
      28             : #include <boost/regex.hpp>
      29             : #include <boost/tokenizer.hpp>
      30             : #include <servus/serializable.h>
      31             : #include <servus/uint128_t.h>
      32             : #include <sys/stat.h>
      33             : #ifdef _MSC_VER
      34             : #include <direct.h>
      35             : #include <windows.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,
     126             :                                GetModuleFileName(NULL, result, 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 path.parent_path()
     151             :             .parent_path()
     152             :             .parent_path()
     153             :             .parent_path()
     154             :             .string();
     155             :     }
     156             : #endif
     157           3 :     return path.parent_path().string();
     158             : }
     159             : 
     160           1 : std::string getWorkDir()
     161             : {
     162             :     char cwd[MAXPATHLEN];
     163           1 :     return ::getcwd(cwd, MAXPATHLEN);
     164             : }
     165             : 
     166           1 : std::string getRootDir()
     167             : {
     168           2 :     const std::string& exeDir = getExecutableDir();
     169           1 :     if (exeDir.empty())
     170           0 :         return exeDir;
     171             : 
     172           2 :     const boost::filesystem::path path(exeDir);
     173             : #ifdef _MSC_VER
     174             :     const Strings buildTypes{"debug", "relwithdebinfo", "release",
     175             :                              "minsizerel"};
     176             :     std::string buildType(path.stem().string());
     177             :     std::transform(buildType.begin(), buildType.end(), buildType.begin(),
     178             :                    ::tolower);
     179             :     if (std::find(buildTypes.begin(), buildTypes.end(), buildType) !=
     180             :         buildTypes.end())
     181             :     {
     182             :         return path.parent_path().parent_path().string();
     183             :     }
     184             : #endif
     185           1 :     return path.parent_path().string();
     186             : }
     187             : 
     188           0 : std::string getLibraryPath()
     189             : {
     190           0 :     const std::string& exeDir = getExecutableDir();
     191           0 :     if (exeDir.empty())
     192           0 :         return exeDir;
     193             : 
     194             : #ifdef _MSC_VER
     195             :     return exeDir;
     196             : #elif __APPLE__
     197             :     const boost::filesystem::path path(exeDir);
     198             : 
     199             :     // foo.app/Contents/MacOS/foo
     200             :     if (boost::algorithm::ends_with(exeDir, ".app/Contents/MacOS"))
     201             :         return path.parent_path()
     202             :                    .parent_path()
     203             :                    .parent_path()
     204             :                    .parent_path()
     205             :                    .string() +
     206             :                "/lib";
     207             :     return path.parent_path().string() + "/lib";
     208             : #else
     209           0 :     const boost::filesystem::path path(exeDir);
     210           0 :     return path.parent_path().string() + "/lib";
     211             : #endif
     212             : }
     213             : 
     214             : #define STDSTRING(macro) std::string(STRINGIFY(macro))
     215             : #define STRINGIFY(foo) #foo
     216             : 
     217           0 : Strings getLibraryPaths()
     218             : {
     219           0 :     Strings paths;
     220           0 :     const std::string& appPath = getLibraryPath();
     221           0 :     if (!appPath.empty())
     222           0 :         paths.push_back(appPath);
     223             : 
     224             : #ifdef _MSC_VER
     225             :     paths.push_back(STDSTRING(CMAKE_INSTALL_PREFIX) + "/bin");
     226             :     const char* env = ::getenv("PATH");
     227             : #elif __APPLE__
     228             :     paths.push_back(STDSTRING(CMAKE_INSTALL_PREFIX) + "/lib");
     229             :     const char* env = ::getenv("DYLD_LIBRARY_PATH");
     230             : #else
     231           0 :     paths.push_back(STDSTRING(CMAKE_INSTALL_PREFIX) + "/lib");
     232           0 :     const char* env = ::getenv("LD_LIBRARY_PATH");
     233             : #endif
     234             : 
     235           0 :     if (!env)
     236           0 :         return paths;
     237             : 
     238           0 :     const std::string envString(env);
     239             : #ifdef _MSC_VER
     240             :     boost::char_separator<char> separator(";");
     241             : #else
     242           0 :     boost::char_separator<char> separator(":");
     243             : #endif
     244             :     const boost::tokenizer<boost::char_separator<char> > tokens(envString,
     245           0 :                                                                 separator);
     246           0 :     BOOST_FOREACH (const std::string& token, tokens)
     247           0 :         paths.push_back(token);
     248             : 
     249           0 :     return paths;
     250             : }
     251             : 
     252           0 : bool saveBinary(const servus::Serializable& object, const std::string& file)
     253             : {
     254           0 :     const servus::Serializable::Data& data = object.toBinary();
     255           0 :     MemoryMap mmap(file, sizeof(uint128_t) + data.size);
     256           0 :     if (!mmap.getAddress())
     257           0 :         return false;
     258           0 :     const uint128_t& id = object.getTypeIdentifier();
     259           0 :     ::memcpy(mmap.getAddress(), &id, sizeof(id));
     260           0 :     ::memcpy(mmap.getAddress<uint8_t>() + sizeof(id), data.ptr.get(),
     261           0 :              data.size);
     262           0 :     return true;
     263             : }
     264             : 
     265           0 : bool loadBinary(servus::Serializable& object, const std::string& file)
     266             : {
     267           0 :     const MemoryMap mmap(file);
     268           0 :     if (!mmap.getAddress() || mmap.getSize() < sizeof(uint128_t) ||
     269           0 :         *mmap.getAddress<uint128_t>() != object.getTypeIdentifier())
     270             :     {
     271           0 :         return false;
     272             :     }
     273             : 
     274           0 :     object.fromBinary(mmap.getAddress<uint8_t>() + sizeof(uint128_t),
     275           0 :                       mmap.getSize() - sizeof(uint128_t));
     276           0 :     return true;
     277             : }
     278             : 
     279           0 : bool saveAscii(const servus::Serializable& object, const std::string& file)
     280             : {
     281           0 :     const std::string& data = object.toJSON();
     282           0 :     MemoryMap mmap(file, data.length());
     283           0 :     if (!mmap.getAddress())
     284           0 :         return false;
     285           0 :     ::memcpy(mmap.getAddress(), &data[0], data.length());
     286           0 :     return true;
     287             : }
     288             : 
     289           0 : bool loadAscii(servus::Serializable& object, const std::string& file)
     290             : {
     291           0 :     const MemoryMap mmap(file);
     292           0 :     if (!mmap.getAddress())
     293           0 :         return false;
     294           0 :     const uint8_t* ptr = mmap.getAddress<uint8_t>();
     295           0 :     object.fromJSON(std::string(ptr, ptr + mmap.getSize()));
     296           0 :     return true;
     297             : }
     298          75 : }

Generated by: LCOV version 1.11