Skip to content

Commit 82ace0f

Browse files
marek-trtikpeterschrammel
authored andcommitted
Add basic file utilities
1 parent df36049 commit 82ace0f

File tree

2 files changed

+219
-0
lines changed

2 files changed

+219
-0
lines changed

src/util/file_util.cpp

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Date: January 2012
2020
#include <dirent.h>
2121
#include <cstdlib>
2222
#include <cstdio>
23+
#include <sys/stat.h>
2324
#endif
2425

2526
#ifdef _WIN32
@@ -33,6 +34,7 @@ Date: January 2012
3334

3435
#include "file_util.h"
3536

37+
3638
/*******************************************************************\
3739
3840
Function: get_current_working_directory
@@ -144,3 +146,191 @@ std::string concat_dir_file(
144146
file_name : directory+"/"+file_name;
145147
#endif
146148
}
149+
150+
151+
152+
153+
154+
#include <fstream>
155+
#include <cstdlib>
156+
#include <algorithm>
157+
#include <sstream>
158+
#include <vector>
159+
160+
#if defined(WIN32)
161+
# include <windows.h>
162+
#elif defined(__linux__) || defined(__APPLE__)
163+
# include <sys/stat.h>
164+
#endif
165+
166+
namespace fileutl { namespace {
167+
168+
169+
std::string::size_type parse_last_dir_pos(std::string const& file_pathname)
170+
{
171+
std::string::size_type const last_slash_pos = file_pathname.find_last_of('/');
172+
std::string::size_type const last_backslash_pos = file_pathname.find_last_of('\\');
173+
std::string::size_type const last_dir_pos =
174+
last_slash_pos == std::string::npos ?
175+
(last_backslash_pos == std::string::npos ? 0ULL :
176+
last_backslash_pos + 1ULL) :
177+
(last_backslash_pos == std::string::npos ? last_slash_pos + 1ULL :
178+
(last_slash_pos < last_backslash_pos ? last_backslash_pos :
179+
last_slash_pos))
180+
;
181+
return last_dir_pos;
182+
}
183+
184+
185+
}}
186+
187+
namespace fileutl {
188+
189+
190+
bool file_exists(std::string const& pathname)
191+
{
192+
std::ifstream f{pathname,std::ios::binary};
193+
return f.good();
194+
}
195+
196+
bool is_directory(std::string const& pathname)
197+
{
198+
if (!file_exists(pathname))
199+
return false;
200+
# if defined(WIN32)
201+
return PathIsDirectory(pathname.c_str());
202+
# elif defined(__linux__) || defined(__APPLE__)
203+
struct stat buf;
204+
stat(pathname.c_str(), &buf);
205+
return S_ISDIR(buf.st_mode);
206+
//return S_ISREG(buf.st_mode); // is file ?
207+
# else
208+
# error "Unsuported platform."
209+
# endif
210+
}
211+
212+
uint64_t file_size(std::string const& file_pathname)
213+
{
214+
std::ifstream f{file_pathname,std::ios::binary};
215+
std::streampos const begin = f.tellg();
216+
f.seekg(0ULL,std::ios::end);
217+
std::streampos const end = f.tellg();
218+
return end - begin;
219+
}
220+
221+
std::string parse_name_in_pathname(std::string const& file_pathname)
222+
{
223+
return file_pathname.substr(parse_last_dir_pos(file_pathname));
224+
}
225+
226+
std::string parse_path_in_pathname(std::string const& file_pathname)
227+
{
228+
return file_pathname.substr(0U,parse_last_dir_pos(file_pathname));
229+
}
230+
231+
std::string remove_extension(std::string const& filename)
232+
{
233+
return filename.substr(0U,filename.find_last_of('.'));
234+
}
235+
236+
void create_directory(std::string const& pathname)
237+
{
238+
# if defined(WIN32)
239+
std::system((std::string("mkdir \"") + pathname + "\"").c_str());
240+
# elif defined(__linux__) || defined(__APPLE__)
241+
auto ignore = std::system((std::string("mkdir -p \"") + pathname + "\"").c_str());
242+
(void)ignore;
243+
# else
244+
# error "Unsuported platform."
245+
# endif
246+
}
247+
248+
std::string concatenate_file_paths(std::string const& left_path, std::string const& right_path)
249+
{
250+
if (left_path.empty())
251+
return right_path;
252+
if (right_path.empty())
253+
return left_path;
254+
return left_path + "/" + right_path;
255+
}
256+
257+
std::string absolute_path(std::string const& path)
258+
{
259+
// TODO: portability - this implementation won't probably work on Windows...
260+
std::vector<char> buffer(10000,0);
261+
return realpath(path.c_str(),&buffer.at(0));
262+
}
263+
264+
std::string normalise_path(std::string const& path)
265+
{
266+
std::string result = path;
267+
std::replace(result.begin(),result.end(),'\\','/');
268+
std::string::size_type pos = 0;
269+
while((pos = result.find("/./",0)) != std::string::npos)
270+
result.replace(pos,3,"/");
271+
// TODO: more fixes should be applied (e.g. /../, //, etc.)
272+
return result;
273+
}
274+
275+
void split_pathname(std::string const& pathname, std::vector<std::string>& output)
276+
{
277+
std::istringstream istr(normalise_path(pathname));
278+
std::string token;
279+
while (std::getline(istr,token,'/'))
280+
output.push_back(token);
281+
}
282+
283+
std::string join_path_parts(std::vector<std::string> const& parts)
284+
{
285+
if (parts.empty())
286+
return "";
287+
std::string result = parts.at(0);
288+
for (uint64_t i = 1ULL; i < parts.size(); ++i)
289+
{
290+
result.push_back('/');
291+
result.append(parts.at(i));
292+
}
293+
return result;
294+
}
295+
296+
std::string get_common_preffix(std::string const& pathname1, std::string const& pathname2)
297+
{
298+
std::vector<std::string> split1;
299+
split_pathname(pathname1,split1);
300+
301+
std::vector<std::string> split2;
302+
split_pathname(pathname2,split2);
303+
304+
std::vector<std::string> common_split;
305+
for (uint64_t i = 0ULL, size = std::min(split1.size(),split2.size());
306+
i < size && split1.at(i) == split2.at(i);
307+
++i)
308+
common_split.push_back(split1.at(i));
309+
310+
std::string const result = join_path_parts(common_split);
311+
return result;
312+
}
313+
314+
std::string get_relative_path(std::string const& pathname, std::string const& directory)
315+
{
316+
std::vector<std::string> split1;
317+
split_pathname(pathname,split1);
318+
std::reverse(split1.begin(),split1.end());
319+
320+
std::vector<std::string> split2;
321+
split_pathname(directory,split2);
322+
std::reverse(split2.begin(),split2.end());
323+
324+
while (!split1.empty() && !split2.empty() && split1.back() == split2.back())
325+
{
326+
split1.pop_back();
327+
split2.pop_back();
328+
}
329+
330+
std::reverse(split1.begin(),split1.end());
331+
std::string const result = join_path_parts(split1);
332+
return result;
333+
}
334+
335+
336+
}

src/util/file_util.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_UTIL_FILE_UTIL_H
1111

1212
#include <string>
13+
#include <vector>
14+
#include <cstdint>
15+
#include <iosfwd>
1316

1417
void delete_directory(const std::string &path);
1518

@@ -18,4 +21,30 @@ std::string get_current_working_directory();
1821
std::string concat_dir_file(const std::string &directory,
1922
const std::string &file_name);
2023

24+
/**
25+
* This functions implement utility functions which provide us disc-related
26+
* functionality, like manipulation with disc paths (concatenation/splitting),
27+
* checking for existence of files, etc.
28+
*/
29+
namespace fileutl {
30+
31+
32+
bool file_exists(std::string const& pathname);
33+
bool is_directory(std::string const& pathname);
34+
uint64_t file_size(std::string const& file_pathname);
35+
std::string parse_name_in_pathname(std::string const& file_pathname);
36+
std::string parse_path_in_pathname(std::string const& file_pathname);
37+
std::string remove_extension(std::string const& filename);
38+
void create_directory(std::string const& pathname);
39+
std::string concatenate_file_paths(std::string const& left_path, std::string const& right_path);
40+
std::string absolute_path(std::string const& path);
41+
std::string normalise_path(std::string const& path);
42+
void split_pathname(std::string const& pathname, std::vector<std::string>& output);
43+
std::string join_path_parts(std::vector<std::string> const& parts);
44+
std::string get_common_preffix(std::string const& pathname1, std::string const& pathname2);
45+
std::string get_relative_path(std::string const& pathname, std::string const& directory);
46+
47+
48+
}
49+
2150
#endif // CPROVER_UTIL_FILE_UTIL_H

0 commit comments

Comments
 (0)