OGS
FileTools.cpp
Go to the documentation of this file.
1
15#include "FileTools.h"
16
17#include <spdlog/fmt/bundled/core.h>
18
19#include <boost/algorithm/string/predicate.hpp>
20#include <filesystem>
21#include <fstream>
22#include <typeindex>
23#include <unordered_map>
24
25#include "BaseLib/Logging.h"
26#include "Error.h"
27
28namespace
29{
32
35} // anonymous namespace
36
37namespace BaseLib
38{
40{
41 return project_directory_is_set;
42}
43
47bool IsFileExisting(const std::string& strFilename)
48{
49 return std::filesystem::exists(std::filesystem::path(strFilename));
50}
51
52std::tuple<std::string, std::string::size_type, std::string::size_type>
53getParenthesizedString(std::string const& in,
54 char const open_char,
55 char const close_char,
56 std::string::size_type pos)
57{
58 auto const pos_curly_brace_open = in.find_first_of(open_char, pos);
59 if (pos_curly_brace_open == std::string::npos)
60 {
61 return std::make_tuple("", std::string::npos, std::string::npos);
62 }
63 auto const pos_curly_brace_close =
64 in.find_first_of(close_char, pos_curly_brace_open);
65 if (pos_curly_brace_close == std::string::npos)
66 {
67 return std::make_tuple("", std::string::npos, std::string::npos);
68 }
69 return std::make_tuple(
70 in.substr(pos_curly_brace_open + 1,
71 pos_curly_brace_close - (pos_curly_brace_open + 1)),
72 pos_curly_brace_open, pos_curly_brace_close);
73}
74
75std::string containsKeyword(std::string const& str, std::string const& keyword)
76{
77 auto const position = str.find(keyword);
78 if (position != std::string::npos)
79 {
80 return str.substr(0, position);
81 }
82 return "";
83}
84
85template <typename T>
86bool substituteKeyword(std::string& result, std::string& parenthesized_string,
87 std::string::size_type begin, std::string::size_type end,
88 std::string const& keyword, T& data)
89{
90 std::string precision_specification =
91 containsKeyword(parenthesized_string, keyword);
92
93 if (precision_specification.empty())
94 {
95 return false;
96 }
97
98 std::unordered_map<std::type_index, char> type_specification;
99 type_specification[std::type_index(typeid(int))] = 'd';
100 type_specification[std::type_index(typeid(double))] = 'f'; // default
101 type_specification[std::type_index(typeid(std::string))] = 's';
102
103 auto const& b = precision_specification.back();
104 // see https://fmt.dev/latest/syntax.html#formatspec
105 if (b == 'e' || b == 'E' || b == 'f' || b == 'F' || b == 'g' || b == 'G')
106 {
107 type_specification[std::type_index(typeid(double))] = b;
108 precision_specification.pop_back();
109 }
110
111 std::string const generated_fmt_string =
112 "{" + precision_specification +
113 type_specification[std::type_index(typeid(data))] + "}";
114 result.replace(
115 begin, end - begin + 1,
116 fmt::vformat(generated_fmt_string, fmt::make_format_args(data)));
117
118 return true;
119}
120
121std::string constructFormattedFileName(std::string const& format_specification,
122 std::string const& mesh_name,
123 int const timestep,
124 double const t,
125 int const iteration)
126{
127 char const open_char = '{';
128 char const close_char = '}';
129 std::string::size_type begin = 0;
130 std::string::size_type end = std::string::npos;
131 std::string result = format_specification;
132
133 while (begin != std::string::npos)
134 {
135 auto length_before_substitution = result.length();
136 // find next parenthesized string
137 std::string str = "";
138 std::tie(str, begin, end) =
139 getParenthesizedString(result, open_char, close_char, begin);
140 if (!substituteKeyword(result, str, begin, end, "timestep", timestep) &&
141 !substituteKeyword(result, str, begin, end, "time", t) &&
142 !substituteKeyword(result, str, begin, end, "iteration", iteration))
143 {
144 substituteKeyword(result, str, begin, end, "meshname", mesh_name);
145 }
146 begin = end - (length_before_substitution - result.length());
147 }
148
149 return result;
150}
151
152double swapEndianness(double const& v)
153{
154 union
155 {
156 double v;
157 char c[sizeof(double)];
158 } a{}, b{};
159
160 a.v = v;
161 for (unsigned short i = 0; i < sizeof(double) / 2; i++)
162 {
163 b.c[i] = a.c[sizeof(double) / 2 - i - 1];
164 }
165
166 for (unsigned short i = sizeof(double) / 2; i < sizeof(double); i++)
167 {
168 b.c[i] = a.c[sizeof(double) + sizeof(double) / 2 - i - 1];
169 }
170
171 return b.v;
172}
173
174std::string dropFileExtension(std::string const& filename)
175{
176 auto const filename_path = std::filesystem::path(filename);
177 return (filename_path.parent_path() / filename_path.stem()).string();
178}
179
180std::string extractBaseName(std::string const& pathname)
181{
182 return std::filesystem::path(pathname).filename().string();
183}
184
185std::string extractBaseNameWithoutExtension(std::string const& pathname)
186{
187 std::string basename = extractBaseName(pathname);
188 return dropFileExtension(basename);
189}
190
191std::string getFileExtension(const std::string& path)
192{
193 return std::filesystem::path(path).extension().string();
194}
195
196bool hasFileExtension(std::string const& extension, std::string const& filename)
197{
198 return boost::iequals(extension, getFileExtension(filename));
199}
200
201std::string copyPathToFileName(const std::string& file_name,
202 const std::string& source)
203{
204 auto filePath = std::filesystem::path(file_name);
205 if (filePath.has_parent_path())
206 {
207 return filePath.string();
208 }
209 return (std::filesystem::path(source) /= filePath).string();
210}
211
212std::string extractPath(std::string const& pathname)
213{
214 return std::filesystem::path(pathname).parent_path().string();
215}
216
217std::string joinPaths(std::string const& pathA, std::string const& pathB)
218{
219 return (std::filesystem::path(pathA) /= std::filesystem::path(pathB))
220 .string();
221}
222
223std::string const& getProjectDirectory()
224{
225 if (!project_directory_is_set)
226 {
227 OGS_FATAL("The project directory has not yet been set.");
228 }
229 return project_directory;
230}
231
232void setProjectDirectory(std::string const& dir)
233{
234 if (project_directory_is_set)
235 {
236 OGS_FATAL("The project directory has already been set.");
237 }
238 // TODO Remove these global vars. They are a possible source of errors when
239 // invoking OGS from Python multiple times within a single session.
240 project_directory = dir;
241 project_directory_is_set = true;
242}
243
245{
246 project_directory.clear();
247 project_directory_is_set = false;
248}
249
250void removeFile(std::string const& filename)
251{
252 bool const success =
253 std::filesystem::remove(std::filesystem::path(filename));
254 if (success)
255 {
256 DBUG("Removed '{:s}'", filename);
257 }
258}
259
260void removeFiles(std::vector<std::string> const& files)
261{
262 for (auto const& file : files)
263 {
264 removeFile(file);
265 }
266}
267
268template <typename T>
269T readBinaryValue(std::istream& in)
270{
271 T v;
272 in.read(reinterpret_cast<char*>(&v), sizeof(T));
273 return v;
274}
275
276// explicit template instantiation
277template float readBinaryValue<float>(std::istream&);
278template double readBinaryValue<double>(std::istream&);
279
280template <typename T>
281std::vector<T> readBinaryArray(std::string const& filename, std::size_t const n)
282{
283 std::ifstream in(filename.c_str());
284 if (!in)
285 {
286 ERR("readBinaryArray(): Error while reading from file '{:s}'.",
287 filename);
288 ERR("Could not open file '{:s}' for input.", filename);
289 in.close();
290 return std::vector<T>();
291 }
292
293 std::vector<T> result;
294 result.reserve(n);
295
296 for (std::size_t p = 0; in && !in.eof() && p < n; ++p)
297 {
298 result.push_back(BaseLib::readBinaryValue<T>(in));
299 }
300
301 if (result.size() == n)
302 {
303 return result;
304 }
305
306 ERR("readBinaryArray(): Error while reading from file '{:s}'.", filename);
307 ERR("Read different number of values. Expected {:d}, got {:d}.",
308 n,
309 result.size());
310
311 if (!in.eof())
312 {
313 ERR("EOF reached.\n");
314 }
315
316 return std::vector<T>();
317}
318
319// explicit template instantiation
320template std::vector<float> readBinaryArray<float>(std::string const&,
321 std::size_t const);
322
323template <typename T>
324void writeValueBinary(std::ostream& out, T const& val)
325{
326 out.write(reinterpret_cast<const char*>(&val), sizeof(T));
327}
328
329// explicit template instantiation
330template void writeValueBinary<std::size_t>(std::ostream&, std::size_t const&);
331
332} // end namespace BaseLib
#define OGS_FATAL(...)
Definition: Error.h:26
Filename manipulation routines.
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition: Logging.h:30
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition: Logging.h:45
std::vector< T > readBinaryArray(std::string const &filename, std::size_t const n)
Definition: FileTools.cpp:281
std::string containsKeyword(std::string const &str, std::string const &keyword)
Definition: FileTools.cpp:75
std::string constructFormattedFileName(std::string const &format_specification, std::string const &mesh_name, int const timestep, double const t, int const iteration)
Definition: FileTools.cpp:121
void removeFile(std::string const &filename)
Definition: FileTools.cpp:250
std::string const & getProjectDirectory()
Returns the directory where the prj file resides.
Definition: FileTools.cpp:223
std::string getFileExtension(const std::string &path)
Definition: FileTools.cpp:191
void writeValueBinary(std::ostream &out, T const &val)
write value as binary into the given output stream
Definition: FileTools.cpp:324
std::string extractPath(std::string const &pathname)
Definition: FileTools.cpp:212
bool substituteKeyword(std::string &result, std::string &parenthesized_string, std::string::size_type begin, std::string::size_type end, std::string const &keyword, T &data)
Definition: FileTools.cpp:86
std::tuple< std::string, std::string::size_type, std::string::size_type > getParenthesizedString(std::string const &in, char const open_char, char const close_char, std::string::size_type pos)
Definition: FileTools.cpp:53
T readBinaryValue(std::istream &in)
Definition: FileTools.cpp:269
bool IsFileExisting(const std::string &strFilename)
Returns true if given file exists.
Definition: FileTools.cpp:47
std::string copyPathToFileName(const std::string &file_name, const std::string &source)
Definition: FileTools.cpp:201
template void writeValueBinary< std::size_t >(std::ostream &, std::size_t const &)
template float readBinaryValue< float >(std::istream &)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:185
std::string dropFileExtension(std::string const &filename)
Definition: FileTools.cpp:174
bool isProjectDirectorySet()
Returns true if the project directory is set.
Definition: FileTools.cpp:39
std::string joinPaths(std::string const &pathA, std::string const &pathB)
Definition: FileTools.cpp:217
void unsetProjectDirectory()
Unsets the project directory.
Definition: FileTools.cpp:244
template double readBinaryValue< double >(std::istream &)
std::string extractBaseName(std::string const &pathname)
Definition: FileTools.cpp:180
double swapEndianness(double const &v)
Definition: FileTools.cpp:152
void setProjectDirectory(std::string const &dir)
Sets the project directory.
Definition: FileTools.cpp:232
template std::vector< float > readBinaryArray< float >(std::string const &, std::size_t const)
bool hasFileExtension(std::string const &extension, std::string const &filename)
Definition: FileTools.cpp:196
void removeFiles(std::vector< std::string > const &files)
Definition: FileTools.cpp:260
std::string project_directory
The directory where the prj file resides.
Definition: FileTools.cpp:31
bool project_directory_is_set
Whether the project directory has already been set.
Definition: FileTools.cpp:34