aboutsummaryrefslogtreecommitdiffstats
path: root/util/folder/path.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/folder/path.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/folder/path.h')
-rw-r--r--util/folder/path.h231
1 files changed, 231 insertions, 0 deletions
diff --git a/util/folder/path.h b/util/folder/path.h
new file mode 100644
index 0000000000..2fb4d6b4ef
--- /dev/null
+++ b/util/folder/path.h
@@ -0,0 +1,231 @@
+#pragma once
+
+#include "fwd.h"
+#include "pathsplit.h"
+
+#include <util/generic/ptr.h>
+#include <util/generic/strbuf.h>
+#include <util/generic/string.h>
+#include <util/generic/vector.h>
+#include <util/string/cast.h>
+#include <util/system/fstat.h>
+#include <util/system/platform.h>
+#include <util/system/sysstat.h>
+#include <util/system/yassert.h>
+
+#include <utility>
+
+/**
+ * Class behaviour is platform-dependent.
+ * It uses platform-dependent separators for path-reconstructing operations.
+ */
+class TFsPath {
+private:
+ struct TSplit;
+
+public:
+ TFsPath();
+ TFsPath(const TString& path);
+ TFsPath(const TStringBuf path);
+ TFsPath(const char* path);
+
+ TFsPath(const std::string& path)
+ : TFsPath(TStringBuf(path))
+ {
+ }
+
+ void CheckDefined() const;
+
+ inline bool IsDefined() const {
+ return Path_.length() > 0;
+ }
+
+ inline explicit operator bool() const {
+ return IsDefined();
+ }
+
+ inline const char* c_str() const {
+ return Path_.c_str();
+ }
+
+ inline operator const TString&() const {
+ return Path_;
+ }
+
+ inline bool operator==(const TFsPath& that) const {
+ return Path_ == that.Path_;
+ }
+
+ inline bool operator!=(const TFsPath& that) const {
+ return Path_ != that.Path_;
+ }
+
+ TFsPath& operator/=(const TFsPath& that);
+
+ friend TFsPath operator/(const TFsPath& s, const TFsPath& p) {
+ TFsPath ret(s);
+ return ret /= p;
+ }
+
+ const TPathSplit& PathSplit() const;
+
+ TFsPath& Fix();
+
+ inline const TString& GetPath() const {
+ return Path_;
+ }
+
+ /// last component of path, or "/" if root
+ TString GetName() const;
+
+ /**
+ * "a.b.tmp" -> "tmp"
+ * "a.tmp" -> "tmp"
+ * ".tmp" -> ""
+ */
+ TString GetExtension() const;
+
+ bool IsAbsolute() const;
+ bool IsRelative() const;
+
+ /**
+ * TFsPath("/a/b").IsSubpathOf("/a") -> true
+ *
+ * TFsPath("/a").IsSubpathOf("/a") -> false
+ *
+ * TFsPath("/a").IsSubpathOf("/other/path") -> false
+ * @param that - presumable parent path of this
+ * @return True if this is a subpath of that and false otherwise.
+ */
+ bool IsSubpathOf(const TFsPath& that) const;
+
+ /**
+ * TFsPath("/a/b").IsNonStrictSubpathOf("/a") -> true
+ *
+ * TFsPath("/a").IsNonStrictSubpathOf("/a") -> true
+ *
+ * TFsPath("/a").IsNonStrictSubpathOf("/other/path") -> false
+ * @param that - presumable parent path of this
+ * @return True if this is a subpath of that or they are equivalent and false otherwise.
+ */
+ bool IsNonStrictSubpathOf(const TFsPath& that) const;
+
+ bool IsContainerOf(const TFsPath& that) const {
+ return that.IsSubpathOf(*this);
+ }
+
+ TFsPath RelativeTo(const TFsPath& root) const; //must be subpath of root
+
+ /**
+ * @returns relative path or empty path if root equals to this.
+ */
+ TFsPath RelativePath(const TFsPath& root) const; //..; for relative paths 1st component must be the same
+
+ /**
+ * Never fails. Returns this if already a root.
+ */
+ TFsPath Parent() const;
+
+ TString Basename() const {
+ return GetName();
+ }
+ TString Dirname() const {
+ return Parent();
+ }
+
+ TFsPath Child(const TString& name) const;
+
+ /**
+ * @brief create this directory
+ *
+ * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
+ *
+ * Nothing to do if dir exists.
+ */
+ void MkDir(const int mode = MODE0777) const;
+
+ /**
+ * @brief create this directory and all parent directories as needed
+ *
+ * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
+ */
+ void MkDirs(const int mode = MODE0777) const;
+
+ // XXX: rewrite to return iterator
+ void List(TVector<TFsPath>& children) const;
+ void ListNames(TVector<TString>& children) const;
+
+ // Check, if path contains at least one component with a specific name.
+ bool Contains(const TString& component) const;
+
+ // fails to delete non-empty directory
+ void DeleteIfExists() const;
+ // delete recursively. Does nothing if not exists
+ void ForceDelete() const;
+
+ // XXX: ino
+
+ inline bool Stat(TFileStat& stat) const {
+ stat = TFileStat(Path_.data());
+
+ return stat.Mode;
+ }
+
+ bool Exists() const;
+ /// false if not exists
+ bool IsDirectory() const;
+ /// false if not exists
+ bool IsFile() const;
+ /// false if not exists
+ bool IsSymlink() const;
+ /// throw TIoException if not exists
+ void CheckExists() const;
+
+ void RenameTo(const TString& newPath) const;
+ void RenameTo(const char* newPath) const;
+ void RenameTo(const TFsPath& newFile) const;
+ void ForceRenameTo(const TString& newPath) const;
+
+ void CopyTo(const TString& newPath, bool force) const;
+
+ void Touch() const;
+
+ TFsPath RealPath() const;
+ TFsPath RealLocation() const;
+ TFsPath ReadLink() const;
+
+ /// always absolute
+ static TFsPath Cwd();
+
+ inline void Swap(TFsPath& p) noexcept {
+ DoSwap(Path_, p.Path_);
+ Split_.Swap(p.Split_);
+ }
+
+private:
+ void InitSplit() const;
+ TSplit& GetSplit() const;
+
+private:
+ TString Path_;
+ /// cache
+ mutable TSimpleIntrusivePtr<TSplit> Split_;
+};
+
+namespace NPrivate {
+ inline void AppendToFsPath(TFsPath&) {
+ }
+
+ template <class T, class... Ts>
+ void AppendToFsPath(TFsPath& fsPath, const T& arg, Ts&&... args) {
+ fsPath /= TFsPath(arg);
+ AppendToFsPath(fsPath, std::forward<Ts>(args)...);
+ }
+}
+
+template <class... Ts>
+TString JoinFsPaths(Ts&&... args) {
+ TFsPath fsPath;
+ ::NPrivate::AppendToFsPath(fsPath, std::forward<Ts>(args)...);
+ return fsPath.GetPath();
+}