libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
filepath.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <filesystem>
14#include <promeki/namespace.h>
15#include <promeki/string.h>
16#include <promeki/result.h>
17#include <promeki/error.h>
18
19PROMEKI_NAMESPACE_BEGIN
20
34class FilePath {
35 public:
37 FilePath() = default;
38
43 FilePath(const String &path) : _path(path.str()) {}
44
49 FilePath(const char *path) : _path(path) {}
50
55 FilePath(const std::filesystem::path &path) : _path(path) {}
56
61 bool isEmpty() const { return _path.empty(); }
62
67 String fileName() const { return _path.filename().string(); }
68
73 String baseName() const { return _path.stem().string(); }
74
79 String suffix() const {
80 auto ext = _path.extension().string();
81 if (ext.size() > 1) return ext.substr(1);
82 return String();
83 }
84
91 String completeSuffix() const {
92 String fn = _path.filename().string();
93 auto pos = fn.find('.');
94 if (pos == String::npos || pos == 0) return String();
95 return fn.substr(pos + 1);
96 }
97
102 FilePath parent() const { return FilePath(_path.parent_path()); }
103
109 FilePath join(const FilePath &other) const { return FilePath(_path / other._path); }
110
116 FilePath operator/(const FilePath &other) const { return join(other); }
117
123 FilePath operator/(const String &other) const {
124 return FilePath(_path / std::filesystem::path(other.str()));
125 }
126
132 FilePath operator/(const char *other) const { return FilePath(_path / std::filesystem::path(other)); }
133
138 bool exists() const {
139 std::error_code ec;
140 return std::filesystem::exists(_path, ec);
141 }
142
147 bool isAbsolute() const { return _path.is_absolute(); }
148
153 bool isRelative() const { return _path.is_relative(); }
154
159 FilePath absolutePath() const {
160 std::error_code ec;
161 return FilePath(std::filesystem::absolute(_path, ec));
162 }
163
176 Result<FilePath> canonicalPath() const {
177 std::error_code ec;
178 auto r = std::filesystem::canonical(_path, ec);
179 if (ec) return Result<FilePath>(*this, Error::Invalid);
180 return Result<FilePath>(FilePath(r), Error::Ok);
181 }
182
196 Result<FilePath> relativeTo(const FilePath &base) const {
197 std::error_code ec;
198 auto r = std::filesystem::relative(_path, base._path, ec);
199 if (ec || r.empty()) return Result<FilePath>(*this, Error::Invalid);
200 return Result<FilePath>(FilePath(r), Error::Ok);
201 }
202
230
237 static constexpr size_t kPseudoSymlinkMaxBytes = 4096;
238
249 static constexpr const char *kPseudoSymlinkMagic = "#!/promeki/symlink";
250
260 bool isSymlink() const {
261 std::error_code ec;
262 auto st = std::filesystem::symlink_status(_path, ec);
263 if (ec) return false;
264 return std::filesystem::is_symlink(st);
265 }
266
283 bool isPseudoSymlink() const;
284
289 bool isLink() const { return isSymlink() || isPseudoSymlink(); }
290
305 Result<FilePath> readSymlink() const {
306 std::error_code ec;
307 auto t = std::filesystem::read_symlink(_path, ec);
308 if (ec) return Result<FilePath>(*this, Error::Invalid);
309 return Result<FilePath>(FilePath(t), Error::Ok);
310 }
311
327 Result<FilePath> readPseudoSymlink() const;
328
344 Error writePseudoSymlink(const FilePath &target) const;
345
357 Result<FilePath> readLink() const {
358 if (isSymlink()) return readSymlink();
359 if (isPseudoSymlink()) return readPseudoSymlink();
360 return Result<FilePath>(*this, Error::Invalid);
361 }
362
386 Result<FilePath> resolveLink(int maxHops = 16) const;
387
389
394 String toString() const { return _path.string(); }
395
400 const std::filesystem::path &toStdPath() const { return _path; }
401
403 bool operator==(const FilePath &other) const { return _path == other._path; }
404
406 bool operator!=(const FilePath &other) const { return _path != other._path; }
407
409 bool operator<(const FilePath &other) const { return _path < other._path; }
410
411 private:
412 std::filesystem::path _path;
413};
414
415PROMEKI_NAMESPACE_END
416
417PROMEKI_FORMAT_VIA_TOSTRING(promeki::FilePath);
418
419#endif // PROMEKI_ENABLE_CORE