diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/folder/path.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/folder/path.h')
-rw-r--r-- | util/folder/path.h | 231 |
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(); +} |