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
|