Jlm
Loading...
Searching...
No Matches
file.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_UTIL_FILE_HPP
7#define JLM_UTIL_FILE_HPP
8
9#include <jlm/util/common.hpp>
10#include <jlm/util/strfmt.hpp>
11
12#include <filesystem>
13#include <string>
14
15namespace jlm::util
16{
17
18class FilePath final
19{
20public:
21 explicit FilePath(const std::string & path)
22 : path_(path)
23 {}
24
25 FilePath(const FilePath & other)
26 : path_(other.path_)
27 {}
28
29 FilePath(FilePath && other) noexcept
30 : path_(std::move(other.path_))
31 {}
32
33 FilePath &
34 operator=(const FilePath & other)
35 {
36 if (this == &other)
37 return *this;
38
39 path_ = other.path_;
40 return *this;
41 }
42
43 FilePath &
44 operator=(FilePath && other) noexcept
45 {
46 if (this == &other)
47 return *this;
48
49 path_ = std::move(other.path_);
50 return *this;
51 }
52
60 [[nodiscard]] std::string
61 base() const noexcept
62 {
63 auto fn = name();
64 auto pos = fn.find_first_of(".");
65 if (pos == std::string::npos)
66 return fn;
67
68 return fn.substr(0, pos);
69 }
70
80 [[nodiscard]] std::string
81 name() const noexcept
82 {
83 auto pos = path_.find_last_of("/");
84 if (pos == std::string::npos)
85 return path_;
86
87 return path_.substr(pos + 1, path_.size() - pos);
88 }
89
97 [[nodiscard]] std::string
98 complete_suffix() const noexcept
99 {
100 auto fn = name();
101 auto pos = fn.find_first_of(".");
102 if (pos == std::string::npos)
103 return fn;
104
105 return fn.substr(pos + 1, fn.size() - pos);
106 }
107
115 [[nodiscard]] std::string
116 suffix() const noexcept
117 {
118 auto fn = name();
119 auto pos = fn.find_last_of(".");
120 if (pos == std::string::npos)
121 return fn;
122
123 return fn.substr(pos + 1, fn.size() - pos);
124 }
125
147 [[nodiscard]] FilePath
148 Dirname() const noexcept
149 {
150 if (path_.empty())
151 return FilePath(".");
152 if (path_ == "/")
153 return FilePath("/");
154
155 // Find the last '/' char, ignoring a trailing '/'
156 size_t lastSlash = std::string::npos;
157 if (path_.size() >= 1)
158 lastSlash = path_.find_last_of('/', path_.size() - 2);
159
160 // If no '/' was found, path_ is a file in the current working directory, or is "." itself
161 if (lastSlash == std::string::npos)
162 return FilePath(".");
163
164 // The only '/' was at the very beginning of the path. We must keep it.
165 if (lastSlash == 0)
166 return FilePath("/");
167
168 // Return the path of the parent directory, without a trailing '/'
169 return FilePath(path_.substr(0, lastSlash));
170 }
171
192 [[nodiscard]] FilePath
193 Join(const std::string & other) const
194 {
195 std::filesystem::path t(path_ == "." ? "" : path_.c_str());
196 t.append(other);
197 return FilePath(t.string());
198 }
199
200 [[nodiscard]] FilePath
201 Join(const FilePath & other) const
202 {
203 return Join(other.to_str());
204 }
205
210 [[nodiscard]] FilePath
211 WithSuffix(const std::string & suffix) const
212 {
213 return FilePath(path_ + suffix);
214 }
215
221 [[nodiscard]] bool
222 Exists() const noexcept
223 {
224 auto fileStatus = std::filesystem::status(path_);
225 return std::filesystem::exists(fileStatus);
226 }
227
232 [[nodiscard]] bool
233 IsDirectory() const noexcept
234 {
235 auto fileStatus = std::filesystem::status(path_);
236 return std::filesystem::is_directory(fileStatus);
237 }
238
243 [[nodiscard]] bool
244 isFile() const noexcept
245 {
246 auto fileStatus = std::filesystem::status(path_);
247 return std::filesystem::is_regular_file(fileStatus);
248 }
249
257 void
259 {
260 if (isFile())
261 throw Error("file already exists: " + path_);
262
263 FilePath baseDir(Dirname());
264 if (!baseDir.IsDirectory())
265 throw Error("parent directory is not a directory: " + baseDir.to_str());
266
267 std::error_code ec;
268 std::filesystem::create_directory(path_, ec);
269
270 if (ec.value() != 0)
271 throw Error("could not create directory '" + path_ + "': " + ec.message());
272 }
273
274 [[nodiscard]] const std::string &
275 to_str() const noexcept
276 {
277 return path_;
278 }
279
280 [[nodiscard]] bool
281 operator==(const FilePath & other) const noexcept
282 {
283 return path_ == other.path_;
284 }
285
286 [[nodiscard]] bool
287 operator==(const std::string & f) const noexcept
288 {
289 return path_ == f;
290 }
291
300 static FilePath
302 const FilePath & directory,
303 const std::string & fileNamePrefix,
304 const std::string & fileNameSuffix)
305 {
306 auto randomString = CreateRandomAlphanumericString(6);
307 FilePath filePath(directory.to_str() + "/" + fileNamePrefix + randomString + fileNameSuffix);
308
309 JLM_ASSERT(!filePath.Exists());
310 return filePath;
311 }
312
316 [[nodiscard]] static FilePath
318 {
319 return FilePath(std::filesystem::temp_directory_path().string());
320 }
321
322private:
323 std::string path_;
324};
325
326class File final
327{
328public:
329 explicit File(const FilePath & path)
330 : fd_(NULL),
331 path_(path)
332 {}
333
335 {
336 close();
337 }
338
339 File(const File &) = delete;
340
341 File(File && other) noexcept
342 : fd_(other.fd_),
343 path_(std::move(other.path_))
344 {
345 other.fd_ = NULL;
346 }
347
348 File &
349 operator=(const File &) = delete;
350
351 File &
352 operator=(File && other) noexcept
353 {
354 if (this == &other)
355 return *this;
356
357 fd_ = other.fd_;
358 path_ = std::move(other.path_);
359 other.fd_ = NULL;
360
361 return *this;
362 }
363
364 void
365 close() noexcept
366 {
367 if (fd_)
368 fclose(fd_);
369
370 fd_ = NULL;
371 }
372
373 void
374 open(const char * mode)
375 {
376 fd_ = fopen(path_.to_str().c_str(), mode);
377 if (!fd_)
378 throw Error("Cannot open file " + path_.to_str());
379 }
380
381 bool
382 is_open() const noexcept
383 {
384 return fd_ != NULL;
385 }
386
387 FILE *
388 fd() const noexcept
389 {
390 return fd_;
391 }
392
393 const FilePath &
394 path() const noexcept
395 {
396 return path_;
397 }
398
399private:
400 FILE * fd_;
402};
403
404}
405
406#endif
static FilePath createUniqueFileName(const FilePath &directory, const std::string &fileNamePrefix, const std::string &fileNameSuffix)
Generates a unique file in a given directory with a prefix and suffix.
Definition file.hpp:301
FilePath Join(const FilePath &other) const
Definition file.hpp:201
FilePath & operator=(FilePath &&other) noexcept
Definition file.hpp:44
FilePath & operator=(const FilePath &other)
Definition file.hpp:34
std::string name() const noexcept
Returns the name of the file, excluding the path.
Definition file.hpp:81
void CreateDirectory() const
Definition file.hpp:258
bool IsDirectory() const noexcept
Determines whether file path is a directory.
Definition file.hpp:233
static FilePath TempDirectoryPath()
Definition file.hpp:317
std::string complete_suffix() const noexcept
Returns the complete suffix (extension) of the file.
Definition file.hpp:98
FilePath(const FilePath &other)
Definition file.hpp:25
FilePath(const std::string &path)
Definition file.hpp:21
FilePath Join(const std::string &other) const
Definition file.hpp:193
bool operator==(const std::string &f) const noexcept
Definition file.hpp:287
bool Exists() const noexcept
Determines whether the file path exists.
Definition file.hpp:222
std::string base() const noexcept
Returns the base name of the file without the path.
Definition file.hpp:61
const std::string & to_str() const noexcept
Definition file.hpp:275
std::string path_
Definition file.hpp:323
FilePath(FilePath &&other) noexcept
Definition file.hpp:29
bool isFile() const noexcept
Determines whether file path is a file.
Definition file.hpp:244
FilePath Dirname() const noexcept
Returns the path to the file or directory's parent directory. Emulates the behavior of the GNU coreut...
Definition file.hpp:148
std::string suffix() const noexcept
Returns the suffix (extension) of the file.
Definition file.hpp:116
FilePath WithSuffix(const std::string &suffix) const
Definition file.hpp:211
bool operator==(const FilePath &other) const noexcept
Definition file.hpp:281
const FilePath & path() const noexcept
Definition file.hpp:394
File(const FilePath &path)
Definition file.hpp:329
void close() noexcept
Definition file.hpp:365
FilePath path_
Definition file.hpp:401
File(File &&other) noexcept
Definition file.hpp:341
FILE * fd() const noexcept
Definition file.hpp:388
bool is_open() const noexcept
Definition file.hpp:382
File & operator=(File &&other) noexcept
Definition file.hpp:352
void open(const char *mode)
Definition file.hpp:374
File(const File &)=delete
File & operator=(const File &)=delete
#define JLM_ASSERT(x)
Definition common.hpp:16
std::string CreateRandomAlphanumericString(std::size_t length)
Definition strfmt.cpp:15