LCOV - code coverage report
Current view: top level - src/utils/common - FileHelpers.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 64 110 58.2 %
Date: 2024-05-02 15:31:40 Functions: 10 18 55.6 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    FileHelpers.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Michael Behrisch
      17             : /// @date    Mon, 17 Dec 2001
      18             : ///
      19             : // Functions for an easier usage of files
      20             : /****************************************************************************/
      21             : #include <config.h>
      22             : 
      23             : #include <string>
      24             : #ifdef WIN32
      25             : // this is how fox does it in xincs.h
      26             : #include <io.h>
      27             : #define access _access
      28             : #define R_OK    4       /* Test for read permission.  */
      29             : #include <direct.h>
      30             : #define getcwd _getcwd // stupid MSFT "deprecation" warning
      31             : #else
      32             : #include <unistd.h>
      33             : #endif
      34             : #include <fstream>
      35             : #include <sys/stat.h>
      36             : #include "FileHelpers.h"
      37             : #include "StringTokenizer.h"
      38             : #include "StringUtils.h"
      39             : #include "MsgHandler.h"
      40             : 
      41             : 
      42             : // ===========================================================================
      43             : // method definitions
      44             : // ===========================================================================
      45             : 
      46             : // ---------------------------------------------------------------------------
      47             : // file access functions
      48             : // ---------------------------------------------------------------------------
      49             : 
      50             : bool
      51      289858 : FileHelpers::isReadable(std::string path) {
      52      289858 :     if (path.length() == 0) {
      53             :         return false;
      54             :     }
      55      289858 :     while (path[path.length() - 1] == '/' || path[path.length() - 1] == '\\') {
      56             :         path.erase(path.end() - 1);
      57             :     }
      58      289858 :     if (path.length() == 0) {
      59             :         return false;
      60             :     }
      61      501409 :     return access(StringUtils::transcodeToLocal(path).c_str(), R_OK) == 0;
      62             : }
      63             : 
      64             : bool
      65      134747 : FileHelpers::isDirectory(std::string path) {
      66             : #ifdef _MSC_VER
      67             :     struct _stat64 fileInfo;
      68             :     if (_stat64(StringUtils::transcodeToLocal(path).c_str(), &fileInfo) != 0) {
      69             : #else
      70             :     struct stat fileInfo;
      71      269494 :     if (stat(StringUtils::transcodeToLocal(path).c_str(), &fileInfo) != 0) {
      72             : #endif
      73           0 :         throw ProcessError(TLF("Cannot get file attributes for file '%'!", path));
      74             :     }
      75      134747 :     return (fileInfo.st_mode & S_IFMT) == S_IFDIR;
      76             : }
      77             : 
      78             : // ---------------------------------------------------------------------------
      79             : // file path evaluating functions
      80             : // ---------------------------------------------------------------------------
      81             : 
      82             : std::string
      83      147048 : FileHelpers::getFilePath(const std::string& path) {
      84             :     const auto beg = path.find_last_of("\\/");
      85      147048 :     if (beg == std::string::npos) {
      86      129268 :         return "";
      87             :     }
      88       17780 :     return path.substr(0, beg + 1);
      89             : }
      90             : 
      91             : 
      92             : std::string
      93           0 : FileHelpers::getFileFromPath(std::string path, const bool removeExtension) {
      94             :     // first remove extension
      95           0 :     if (removeExtension) {
      96             :         const auto begExtension = path.find_last_of(".");
      97           0 :         if (begExtension != std::string::npos) {
      98           0 :             path = path.substr(0, begExtension);
      99             :         }
     100             :     }
     101             :     // now remove path
     102             :     const auto begPath = path.find_last_of("\\/");
     103           0 :     if (begPath != std::string::npos) {
     104           0 :         path = path.substr(begPath + 1, path.size());
     105             :     }
     106           0 :     return path;
     107             : }
     108             : 
     109             : 
     110             : std::string
     111           0 : FileHelpers::addExtension(const std::string& path, const std::string& extension) {
     112           0 :     if (path.empty()) {
     113           0 :         return "";
     114           0 :     } else if (extension.empty()) {
     115             :         return path;
     116           0 :     } else if (path == extension) {
     117           0 :         return "";
     118           0 :     } else if (path.size() < extension.size()) {
     119           0 :         return path + extension;
     120             :     } else {
     121             :         // declare two reverse iterator for every string
     122             :         std::string::const_reverse_iterator it_path = path.rbegin();
     123             :         std::string::const_reverse_iterator it_extension = extension.rbegin();
     124             :         // iterate over extension and compare both characters
     125           0 :         while (it_extension != extension.rend()) {
     126             :             // if both characters are different, then return path + extension
     127           0 :             if (*it_path != *it_extension) {
     128           0 :                 return path + extension;
     129             :             }
     130             :             it_path++;
     131             :             it_extension++;
     132             :         }
     133             :         // if comparison was successful, then the path has already the extension
     134             :         return path;
     135             :     }
     136             : }
     137             : 
     138             : 
     139             : std::string
     140      146209 : FileHelpers::getConfigurationRelative(const std::string& configPath, const std::string& path) {
     141      146209 :     std::string retPath = getFilePath(configPath);
     142      292418 :     return retPath + path;
     143             : }
     144             : 
     145             : 
     146             : bool
     147      204537 : FileHelpers::isSocket(const std::string& name) {
     148             :     const std::string::size_type colonPos = name.find(":");
     149      204537 :     return (colonPos != std::string::npos) && (colonPos > 1);
     150             : }
     151             : 
     152             : 
     153             : bool
     154      156731 : FileHelpers::isAbsolute(const std::string& path) {
     155      156731 :     if (isSocket(path)) {
     156             :         return true;
     157             :     }
     158             :     // check UNIX - absolute paths
     159      156719 :     if (path.length() > 0 && path[0] == '/') {
     160             :         return true;
     161             :     }
     162             :     // check Windows - absolute paths
     163      156489 :     if (path.length() > 0 && path[0] == '\\') {
     164             :         return true;
     165             :     }
     166      156489 :     if (path.length() > 1 && path[1] == ':') {
     167             :         return true;
     168             :     }
     169      312978 :     if (path == "nul" || path == "NUL") {
     170           0 :         return true;
     171             :     }
     172             :     return false;
     173             : }
     174             : 
     175             : 
     176             : std::string
     177      140947 : FileHelpers::checkForRelativity(const std::string& filename, const std::string& basePath) {
     178      422497 :     if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
     179         174 :         return "stdout";
     180             :     }
     181      281438 :     if (filename == "stderr" || filename == "STDERR") {
     182         108 :         return "stderr";
     183             :     }
     184      281318 :     if (filename == "nul" || filename == "NUL") {
     185         878 :         return "/dev/null";
     186             :     }
     187      139787 :     if (!isAbsolute(filename)) {
     188      139581 :         return getConfigurationRelative(basePath, filename);
     189             :     }
     190             :     return filename;
     191             : }
     192             : 
     193             : 
     194             : std::string
     195           0 : FileHelpers::getCurrentDir() {
     196             :     char buffer[1024];
     197             :     char* answer = getcwd(buffer, sizeof(buffer));
     198           0 :     if (answer) {
     199           0 :         return answer;
     200             :     }
     201           0 :     return "";
     202             : }
     203             : 
     204             : 
     205             : std::vector<std::string>
     206        6876 : FileHelpers::splitDirs(const std::string& filename) {
     207             :     std::vector<std::string> result;
     208       31462 :     for (const std::string& d : StringTokenizer(filename, "\\/", true).getVector()) {
     209       11486 :         if (d == ".." && !result.empty() && result.back() != "..") {
     210          10 :             result.pop_back();
     211       34338 :         } else if ((d == "" && result.empty()) || (d != "" && d != ".")) {
     212       11462 :             result.push_back(d);
     213             :         }
     214        6876 :     }
     215        6876 :     return result;
     216           0 : }
     217             : 
     218             : 
     219             : std::string
     220        3445 : FileHelpers::fixRelative(const std::string& filename, const std::string& basePath, const bool force, std::string curDir) {
     221       10331 :     if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
     222           2 :         return "stdout";
     223             :     }
     224        6886 :     if (filename == "stderr" || filename == "STDERR") {
     225           0 :         return "stderr";
     226             :     }
     227       10329 :     if (filename == "nul" || filename == "NUL" || filename == "/dev/null") {
     228           0 :         return "/dev/null";
     229             :     }
     230        3443 :     if (isSocket(filename) || (isAbsolute(filename) && !force)) {
     231             :         return filename;
     232             :     }
     233        3431 :     std::vector<std::string> filePathSplit = splitDirs(filename);
     234        3431 :     std::vector<std::string> basePathSplit = splitDirs(basePath);
     235        6854 :     if (isAbsolute(filename) || isAbsolute(basePath) || basePathSplit[0] == "..") {
     236             :         // if at least one is absolute we need to make the other absolute too
     237             :         // the same is true if the basePath refers to a parent dir
     238          12 :         if (curDir == "") {
     239           0 :             curDir = getCurrentDir();
     240             :         }
     241          12 :         if (!isAbsolute(filename)) {
     242          16 :             filePathSplit = splitDirs(curDir + "/" + filename);
     243             :         }
     244          12 :         if (!isAbsolute(basePath)) {
     245          12 :             basePathSplit = splitDirs(curDir + "/" + basePath);
     246             :         }
     247          12 :         if (filePathSplit[0] != basePathSplit[0]) {
     248             :             // don't try to make something relative on different windows disks
     249           0 :             return joinToString(filePathSplit, "/");
     250             :         }
     251             :     }
     252        4108 :     while (!filePathSplit.empty() && !basePathSplit.empty() && filePathSplit[0] == basePathSplit[0]) {
     253             :         filePathSplit.erase(filePathSplit.begin());
     254             :         basePathSplit.erase(basePathSplit.begin());
     255             :     }
     256        5991 :     for (int i = 0; i < (int)basePathSplit.size() - 1; i++) {
     257        5120 :         filePathSplit.insert(filePathSplit.begin(), "..");
     258             :     }
     259        3431 :     return joinToString(filePathSplit, "/");
     260        3431 : }
     261             : 
     262             : 
     263             : std::string
     264        1318 : FileHelpers::prependToLastPathComponent(const std::string& prefix, const std::string& path) {
     265             :     const std::string::size_type sep_index = path.find_last_of("\\/");
     266        1318 :     if (sep_index == std::string::npos) {
     267          84 :         return prefix + path;
     268             :     } else {
     269        3070 :         return path.substr(0, sep_index + 1) + prefix + path.substr(sep_index + 1);
     270             :     }
     271             : }
     272             : 
     273             : // ---------------------------------------------------------------------------
     274             : // binary reading/writing functions
     275             : // ---------------------------------------------------------------------------
     276             : 
     277             : std::ostream&
     278           0 : FileHelpers::writeInt(std::ostream& strm, int value) {
     279           0 :     strm.write((char*) &value, sizeof(int));
     280           0 :     return strm;
     281             : }
     282             : 
     283             : 
     284             : std::ostream&
     285           0 : FileHelpers::writeFloat(std::ostream& strm, double value) {
     286           0 :     strm.write((char*) &value, sizeof(double));
     287           0 :     return strm;
     288             : }
     289             : 
     290             : 
     291             : std::ostream&
     292           0 : FileHelpers::writeByte(std::ostream& strm, unsigned char value) {
     293           0 :     strm.write((char*) &value, sizeof(char));
     294           0 :     return strm;
     295             : }
     296             : 
     297             : 
     298             : std::ostream&
     299           0 : FileHelpers::writeString(std::ostream& strm, const std::string& value) {
     300           0 :     int size = (int)value.length();
     301             :     const char* cstr = value.c_str();
     302           0 :     writeInt(strm, size);
     303           0 :     strm.write((char*) cstr, (std::streamsize)(sizeof(char)*size));
     304           0 :     return strm;
     305             : }
     306             : 
     307             : 
     308             : std::ostream&
     309           0 : FileHelpers::writeTime(std::ostream& strm, SUMOTime value) {
     310           0 :     strm.write((char*) &value, sizeof(SUMOTime));
     311           0 :     return strm;
     312             : }
     313             : 
     314             : 
     315             : /****************************************************************************/

Generated by: LCOV version 1.14