LCOV - code coverage report
Current view: top level - source/ioutils - fileUtils.cpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 88.2 % 68 60
Test Date: 2026-08-30 22:23:37 Functions: 85.7 % 14 12

            Line data    Source code
       1              : /** \file fileUtils.cpp
       2              :  * \brief Definitions of utilities for working with files
       3              :  *
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  * \ingroup fileutils
       7              :  *
       8              :  */
       9              : 
      10              : //***********************************************************************//
      11              : // Copyright 2020 Jared R. Males (jaredmales@gmail.com)
      12              : //
      13              : // This file is part of mxlib.
      14              : //
      15              : // mxlib is free software: you can redistribute it and/or modify
      16              : // it under the terms of the GNU General Public License as published by
      17              : // the Free Software Foundation, either version 3 of the License, or
      18              : // (at your option) any later version.
      19              : //
      20              : // mxlib is distributed in the hope that it will be useful,
      21              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      22              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      23              : // GNU General Public License for more details.
      24              : //
      25              : // You should have received a copy of the GNU General Public License
      26              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      27              : //***********************************************************************//
      28              : 
      29              : #include "ioutils/fileUtils.hpp"
      30              : 
      31              : #include <iostream>
      32              : #include <string>
      33              : #include <vector>
      34              : #include <sstream>
      35              : #include <libgen.h>
      36              : #include <cmath>
      37              : 
      38              : #include <sys/types.h>
      39              : #include <sys/stat.h>
      40              : #include <unistd.h>
      41              : 
      42              : #include <filesystem>
      43              : 
      44              : namespace mx
      45              : {
      46              : namespace ioutils
      47              : {
      48              : 
      49              : namespace fileUtilsDetail
      50              : {
      51              : 
      52              : namespace
      53              : {
      54              : 
      55           38 : void noOperationFailure( operation )
      56              : {
      57           38 : }
      58              : 
      59            9 : void noErrorCodeFailure( operation, std::error_code & )
      60              : {
      61            9 : }
      62              : 
      63              : } // namespace
      64              : 
      65           88 : operationHookT &operationHook()
      66              : {
      67              :     static operationHookT hook = noOperationFailure;
      68           88 :     return hook;
      69              : }
      70              : 
      71           42 : errorCodeHookT &errorCodeHook()
      72              : {
      73              :     static errorCodeHookT hook = noErrorCodeFailure;
      74           42 :     return hook;
      75              : }
      76              : 
      77              : } // namespace fileUtilsDetail
      78              : 
      79              : template bool exists<verbose::d>( const std::string &, error_t & );
      80              : 
      81              : template bool dir_exists_is<verbose::d>( const std::string &, error_t & );
      82              : 
      83           12 : error_t createDirectories( const std::string &path )
      84              : {
      85              :     // Use the non throwing version and silently ignore EEXIST errors
      86           12 :     std::error_code ec;
      87           12 :     std::filesystem::create_directories( path, ec );
      88           12 :     fileUtilsDetail::errorCodeHook()( fileUtilsDetail::operation::createDirectories, ec );
      89           12 :     if( ec.value() != 0 && ec.value() != EEXIST )
      90              :     {
      91            2 :         mx::error_t errc = errno2error_t( ec.value() );
      92            2 :         if( errc == error_t::error )
      93              :         {
      94            1 :             errc = error_t::filesystem;
      95              :         }
      96            2 :         return errc;
      97              :     }
      98              : 
      99           10 :     return error_t::noerror;
     100              : }
     101              : 
     102            1 : std::string pathStem( const std::string &fname )
     103              : {
     104            1 :     std::filesystem::path p( fname );
     105            2 :     return p.stem().string();
     106            1 : }
     107              : 
     108            1 : std::string pathFilename( const std::string &fname )
     109              : {
     110            1 :     std::filesystem::path p( fname );
     111            2 :     return p.filename().string();
     112            1 : }
     113              : 
     114            2 : std::string parentPath( const std::string &fname )
     115              : {
     116            2 :     std::filesystem::path p( fname );
     117            4 :     return p.parent_path().string();
     118            2 : }
     119              : 
     120              : template error_t getFileNames<verbose::d>( std::vector<std::string> &fileNames,
     121              :                                            const std::string &directory,
     122              :                                            const std::string &prefix,
     123              :                                            const std::string &substr,
     124              :                                            const std::string &extension );
     125              : 
     126            3 : std::string fileNamePrependAppend( const std::string &fname, const std::string &prepend, const std::string &append )
     127              : {
     128            3 :     std::string dir, base, ext;
     129              : 
     130            3 :     std::filesystem::path p = fname;
     131            3 :     dir = p.parent_path().string();
     132            3 :     base = p.stem().string();
     133            3 :     ext = p.extension().string();
     134              : 
     135            6 :     return dir + '/' + prepend + base + append + ext;
     136            3 : }
     137              : 
     138            1 : std::string fileNameAppend( const std::string &fname, const std::string &append )
     139              : {
     140            2 :     return fileNamePrependAppend( fname, "", append );
     141              : }
     142              : 
     143            1 : std::string fileNamePrepend( const std::string &fname, const std::string &prepend )
     144              : {
     145            2 :     return fileNamePrependAppend( fname, prepend, "" );
     146              : }
     147              : 
     148              : std::string
     149            7 : getSequentialFilename( const std::string &basename, const std::string &extension, const int startat, const int ndigit )
     150              : {
     151              :     // int maxdig = 1;
     152              :     // for(int j=0;j<ndigit;++j) maxdig *= 10;
     153            7 :     int maxdig = pow( 10, ndigit );
     154              : 
     155              :     char formstr[64];
     156            7 :     snprintf( formstr, sizeof( formstr ), "%%0%dd", ndigit );
     157              : 
     158              :     char digstr[64];
     159            7 :     int i = startat;
     160              : 
     161            7 :     std::stringstream outn;
     162              : 
     163            7 :     snprintf( digstr, sizeof( digstr ), formstr, i );
     164              : 
     165            7 :     outn << basename;
     166            7 :     outn << digstr;
     167            7 :     outn << extension;
     168              : 
     169            9 :     while( std::filesystem::exists( outn.str() ) && i < maxdig )
     170              :     {
     171            2 :         ++i;
     172            2 :         outn.str( "" );
     173              : 
     174            2 :         snprintf( digstr, sizeof( digstr ), formstr, i );
     175              : 
     176            2 :         outn << basename;
     177            2 :         outn << digstr;
     178              : 
     179            2 :         outn << extension;
     180              :     }
     181              : 
     182           14 :     return outn.str();
     183            7 : }
     184              : 
     185            0 : off_t fileSize( int fd )
     186              : {
     187            0 :     if( fd == -1 )
     188              :     {
     189            0 :         return -1;
     190              :     }
     191              : 
     192              :     struct stat stbuf;
     193              : 
     194            0 :     if( ( fstat( fd, &stbuf ) != 0 ) || ( !S_ISREG( stbuf.st_mode ) ) )
     195              :     {
     196            0 :         return -1;
     197              :     }
     198              : 
     199            0 :     return stbuf.st_size;
     200              : }
     201              : 
     202            0 : off_t fileSize( FILE *f )
     203              : {
     204            0 :     return fileSize( fileno( f ) );
     205              : }
     206              : 
     207              : } // namespace ioutils
     208              : } // namespace mx
        

Generated by: LCOV version 2.0-1