10 #if __cplusplus >= 201703L && (!__GNUG__ || __GNUC__ > 7)
14 #ifndef CTRL_UTILS_FILESYSTEM_H_
15 #define CTRL_UTILS_FILESYSTEM_H_
30 namespace filesystem {
41 path(
const char* source) : str_(normalize(source)) {}
43 path(
const std::string& source) : str_(normalize(source)) {}
45 const char* c_str()
const {
return str_.c_str(); }
47 const std::string& string()
const {
return str_; }
49 bool empty()
const {
return str_.empty(); }
51 path parent_path()
const {
return str_.substr(0, str_.find_last_of(
"/\\") + 1); };
54 const size_t idx_start = str_.find_last_of(
"/\\") + 1;
55 const size_t idx_end = str_.find_last_of(
".");
56 if (idx_start == idx_end) {
57 return str_.substr(idx_start);
59 return str_.substr(idx_start, idx_end - idx_start);
63 path filename()
const {
64 const size_t idx_start = str_.find_last_of(
"/\\") + 1;
65 return str_.substr(idx_start);
68 bool operator==(
const path& other)
const {
return str_ == other.str_; }
72 static std::string normalize(
const std::string& source) {
73 std::string result = std::regex_replace(source, std::regex(
"/+"),
"/");
74 if (!result.empty() && result.back() ==
'.') {
77 result = std::regex_replace(result, std::regex(
"/\\./"),
"/");
78 result = std::regex_replace(result, std::regex(
"^\\./"),
"");
79 std::string result_new = std::regex_replace(result, std::regex(
"[^/\\.]+/\\.\\./"),
"");
80 while (result_new != result) {
82 result_new = std::regex_replace(result, std::regex(
"[^/\\.]+/\\.\\./"),
"");
84 result = std::regex_replace(result, std::regex(
"^/\\.\\."),
"/");
85 result = std::regex_replace(result, std::regex(
"^\\.\\./$"),
"..");
97 return a.string() +
"/" + b.string();
100 template<
class CharT,
class Traits>
101 basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os,
const path& p) {
117 bool operator==(
const directory_entry& other)
const {
return path_ == other.path_; }
130 using difference_type = ptrdiff_t;
133 using iterator_category = std::input_iterator_tag;
138 : path_(other.path_), entry_(other.entry_), dp_(other.dp_), dirp_(other.dirp_) {}
142 dp_ = std::shared_ptr<DIR>(opendir(path_.c_str()), closedir);
144 throw runtime_error(
"directory_iterator: invalid path " + path_.string());
146 dirp_ = readdir(dp_.get());
147 while ((dirp_ !=
nullptr &&
148 strcmp(dirp_->d_name,
".") == 0) || strcmp(dirp_->d_name,
"..") == 0) {
149 dirp_ = readdir(dp_.get());
151 if (dirp_ !=
nullptr) {
152 entry_.assign(
path(path_.string() +
"/" + std::string(dirp_->d_name)));
157 dirp_ = readdir(dp_.get());
158 entry_ = dirp_ ==
nullptr ?
path() :
path(path_.string() +
"/" + std::string(dirp_->d_name));
163 if (entry_.path().empty() && other.entry_.path().empty())
return true;
164 return path_ == other.path_ && entry_ == other.entry_;
168 reference operator*()
const {
return entry_; }
169 pointer operator->()
const {
return &entry_; }
176 std::shared_ptr<DIR> dp_;
177 struct dirent* dirp_ =
nullptr;
185 inline directory_iterator end(
const directory_iterator& it) {
186 return directory_iterator();
189 inline bool exists(
const path& p) {
190 return access(p.c_str(), F_OK) == 0;
193 inline path current_path() {
194 char* c_path = getcwd(
nullptr, 0);
200 inline path absolute_path(
const path& p) {
201 char* c_path = realpath(p.c_str(),
nullptr);
Definition: filesystem.h:105
Definition: filesystem.h:125
Definition: filesystem.h:32
Definition: filesystem.h:35