DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
Directory.cpp
Go to the documentation of this file.
1#include "pch.h"
3#include "System/IO/Path.h"
6#include <filesystem>
7#include <vector>
8#include <regex>
9
10#if defined(_WIN32)
11#include "Win32Internal.h"
12using namespace DotNetDupe::System::Internal;
13#endif
14
15namespace fs = std::filesystem;
16
17namespace {
18 fs::path ToFsPath(const DotNetDupe::System::String& sPath) {
19#if defined(_WIN32)
21#else
22 return fs::path(sPath.GetRawString());
23#endif
24 }
25
26 std::regex PatternToRegex(const DotNetDupe::System::String& sPattern) {
27 std::string sPat = sPattern.GetRawString();
28 std::string sRegexStr;
29 for (char c : sPat) {
30 if (c == '*') sRegexStr += ".*";
31 else if (c == '?') sRegexStr += ".";
32 else if (c == '.' || c == '\\' || c == '/' || c == '(' || c == ')' || c == '[' || c == ']' || c == '^' || c == '$' || c == '+' || c == '|' || c == '{' || c == '}') {
33 sRegexStr += "\\";
34 sRegexStr += c;
35 } else {
36 sRegexStr += c;
37 }
38 }
39 return std::regex("^" + sRegexStr + "$", std::regex_constants::icase);
40 }
41
42 DotNetDupe::System::DateTimeOffset FileTimeToDateTimeOffset(fs::file_time_type ftime) {
43 auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
44 ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now()
45 );
46 auto durationSec = std::chrono::duration_cast<std::chrono::seconds>(sctp.time_since_epoch()).count();
47 // 62135596800ULL is seconds between 0001-01-01 and 1970-01-01
48 int64_t ticks = (durationSec + 62135596800LL) * 10000000LL;
49 return DotNetDupe::System::DateTimeOffset(ticks);
50 }
51}
52
53namespace DotNetDupe {
54 namespace System {
55 namespace IO {
56 bool Directory::Exists(const String& sPath) {
58 if (sPath.IsEmpty()) return false;
59 std::error_code ec;
61 return fs::is_directory(ToFsPath(sPath), ec);
62 }
63
66 CreateDirectory(sPath, true);
67 }
68
69 void Directory::CreateDirectory(const String& sPath, bool bRecursive) {
71 if (sPath.IsEmpty()) {
72 throw ArgumentException("Path cannot be empty.");
73 }
74 std::error_code ec;
76 if (bRecursive) {
77 fs::create_directories(ToFsPath(sPath), ec);
78 } else {
79 fs::create_directory(ToFsPath(sPath), ec);
80 }
81 if (ec) {
82 throw IO::IOException(ec.message().c_str());
83 }
84 }
85
86 void Directory::Delete(const String& sPath) {
88 Delete(sPath, false);
89 }
90
91 void Directory::Delete(const String& sPath, bool bRecursive) {
93 if (sPath.IsEmpty()) {
94 throw ArgumentException("Path cannot be empty.");
95 }
96 fs::path p = ToFsPath(sPath);
97 std::error_code ec;
98 if (!fs::exists(p, ec)) {
99 throw IO::IOException("Directory does not exist.");
100 }
101
103 if (bRecursive) {
104 fs::remove_all(p, ec);
105 } else {
106 fs::remove(p, ec);
107 }
108 if (ec) {
109 throw IO::IOException(ec.message().c_str());
110 }
111 }
112
113 void Directory::Move(const String& sSourceDirName, const String& sDestDirName) {
115 if (sSourceDirName.IsEmpty() || sDestDirName.IsEmpty()) {
116 throw ArgumentException("Source and destination paths cannot be empty.");
117 }
118 std::error_code ec;
120 fs::rename(ToFsPath(sSourceDirName), ToFsPath(sDestDirName), ec);
121 if (ec) {
122 throw IO::IOException(ec.message().c_str());
123 }
124 }
125
128 return GetFiles(sPath, "*");
129 }
130
131 Array<String> Directory::GetFiles(const String& sPath, const String& sSearchPattern) {
133 if (!Exists(sPath)) {
134 throw IO::IOException("Directory does not exist.");
135 }
136 std::vector<String> results;
137 std::regex reg = PatternToRegex(sSearchPattern);
138 std::error_code ec;
139
141 for (const auto& entry : fs::directory_iterator(ToFsPath(sPath), ec)) {
142 if (entry.is_regular_file(ec)) {
143 std::string filename = entry.path().filename().string();
144 if (std::regex_match(filename, reg)) {
145 results.push_back(String(entry.path().string().c_str()));
146 }
147 }
148 }
150 Array<String> arr((int)results.size());
151 for (int iIdx = 0; iIdx < (int)results.size(); iIdx++) arr[iIdx] = results[iIdx];
152 return arr;
153 }
154
157 return GetDirectories(sPath, "*");
158 }
159
160 Array<String> Directory::GetDirectories(const String& sPath, const String& sSearchPattern) {
162 if (!Exists(sPath)) {
163 throw IO::IOException("Directory does not exist.");
164 }
165 std::vector<String> results;
166 std::regex reg = PatternToRegex(sSearchPattern);
167 std::error_code ec;
168
170 for (const auto& entry : fs::directory_iterator(ToFsPath(sPath), ec)) {
171 if (entry.is_directory(ec)) {
172 std::string filename = entry.path().filename().string();
173 if (std::regex_match(filename, reg)) {
174 results.push_back(String(entry.path().string().c_str()));
175 }
176 }
177 }
179 Array<String> arr((int)results.size());
180 for (int iIdx = 0; iIdx < (int)results.size(); iIdx++) arr[iIdx] = results[iIdx];
181 return arr;
182 }
183
186 return GetFileSystemEntries(sPath, "*");
187 }
188
189 Array<String> Directory::GetFileSystemEntries(const String& sPath, const String& sSearchPattern) {
191 if (!Exists(sPath)) {
192 throw IO::IOException("Directory does not exist.");
193 }
194 std::vector<String> results;
195 std::regex reg = PatternToRegex(sSearchPattern);
196 std::error_code ec;
197
199 for (const auto& entry : fs::directory_iterator(ToFsPath(sPath), ec)) {
200 std::string filename = entry.path().filename().string();
201 if (std::regex_match(filename, reg)) {
202 results.push_back(String(entry.path().string().c_str()));
203 }
204 }
206 Array<String> arr((int)results.size());
207 for (int iIdx = 0; iIdx < (int)results.size(); iIdx++) arr[iIdx] = results[iIdx];
208 return arr;
209 }
210
213 std::error_code ec;
214 fs::path p = fs::current_path(ec);
215 if (ec) {
216 throw IO::IOException(ec.message().c_str());
217 }
218 return String(p.string().c_str());
219 }
220
223 if (sPath.IsEmpty()) {
224 throw ArgumentException("Path cannot be empty.");
225 }
226 std::error_code ec;
228 fs::current_path(ToFsPath(sPath), ec);
229 if (ec) {
230 throw IO::IOException(ec.message().c_str());
231 }
232 }
233
236 return Path::GetPathRoot(sPath);
237 }
238
241 return GetLastWriteTime(sPath);
242 }
243
246 std::error_code ec;
247 auto ftime = fs::last_write_time(ToFsPath(sPath), ec);
248 if (ec) {
249 throw IO::IOException(ec.message().c_str());
250 }
251 return FileTimeToDateTimeOffset(ftime);
252 }
253
256 return GetLastWriteTime(sPath);
257 }
258 }
259 }
260}
Defines the exception thrown when an invalid argument is provided to a method.
The exception that is thrown when an I/O error occurs.
ArgumentException(const String &sMessage)
Initializes a new instance of the ArgumentException class with a specified error message.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition Array.h:29
Represents a point in time, typically expressed as a date and time of day, relative to Coordinated Un...
static void CreateDirectory(const String &sPath)
Creates all directories and subdirectories in the specified path unless they already exist.
Definition Directory.cpp:64
static Array< String > GetDirectories(const String &sPath)
Returns the names of subdirectories (including their paths) in the specified directory.
static DateTimeOffset GetCreationTime(const String &sPath)
Gets the creation date and time of a directory.
static void SetCurrentDirectory(const String &sPath)
Sets the application's current working directory to the specified directory.
static DateTimeOffset GetLastWriteTime(const String &sPath)
Returns the date and time the specified file or directory was last written to.
static void Delete(const String &sPath)
Deletes an empty directory from a specified path.
Definition Directory.cpp:86
static String GetCurrentDirectory()
Gets the current working directory of the application.
static void Move(const String &sSourceDirName, const String &sDestDirName)
Moves a file or a directory and its contents to a new location.
static bool Exists(const String &sPath)
Determines whether the given path refers to an existing directory on disk.
Definition Directory.cpp:56
static DateTimeOffset GetLastAccessTime(const String &sPath)
Returns the date and time the specified file or directory was last accessed.
static Array< String > GetFiles(const String &sPath)
Returns the names of files (including their paths) in the specified directory.
static Array< String > GetFileSystemEntries(const String &sPath)
Returns the names of all files and subdirectories in the specified directory.
static String GetDirectoryRoot(const String &sPath)
Returns the volume information, root information, or both for the specified path.
The exception that is thrown when an I/O error occurs.
Definition IOException.h:17
static String GetPathRoot(const String &sPath)
Gets the root directory information from the path contained in the specified string.
Definition Path.cpp:187
static std::wstring Utf8ToWChar(const char *pUtf8Str)
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
String()
Initializes a new instance of the String class to an empty string.
Definition String.cpp:64
const char * GetRawString() const
Definition String.cpp:230