Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
FileManagementFunctions.cpp
Go to the documentation of this file.
1
2
6
7#include <filesystem>
8
9namespace Divide {
10
12{
13 return ResourcePath { std::filesystem::current_path().lexically_normal().string() };
14}
15
16FileError readFile(const ResourcePath& filePath, std::string_view fileName, FileType fileType, std::ifstream& sreamOut)
17{
18 if (filePath.empty() || fileName.empty() || !pathExists(filePath))
19 {
20 return FileError::FILE_NOT_FOUND;
21 }
22
23 sreamOut = std::ifstream((filePath / fileName).fileSystemPath(),
24 fileType == FileType::BINARY
25 ? std::ios::in | std::ios::binary
26 : std::ios::in);
27
28
29 return (sreamOut.eof() || sreamOut.fail())
30 ? FileError::FILE_READ_ERROR
31 : FileError::NONE;
32}
33
34FileError readFile(const ResourcePath& filePath, std::string_view fileName, FileType fileType, string& contentOut)
35{
36 std::ifstream streamIn;
37 const FileError ret = readFile(filePath, fileName, fileType, streamIn);
38 if ( ret != FileError::NONE)
39 {
40 return ret;
41 }
42
43 std::stringstream buffer;
44 buffer << streamIn.rdbuf();
45 contentOut = buffer.str();
46
47 return contentOut.empty() ? FileError::FILE_EMPTY : FileError::NONE;
48}
49
50FileError readFile(const ResourcePath& filePath, std::string_view fileName, FileType fileType, std::string& contentOut)
51{
52 std::ifstream streamIn;
53 const FileError ret = readFile(filePath, fileName, fileType, streamIn);
54 if ( ret != FileError::NONE)
55 {
56 return ret;
57 }
58
59 std::stringstream buffer;
60 buffer << streamIn.rdbuf();
61 contentOut = buffer.str();
62
63 return contentOut.empty() ? FileError::FILE_EMPTY : FileError::NONE;
64}
65
66FileError readFile(const ResourcePath& filePath, std::string_view fileName, FileType fileType, Byte* contentOut, size_t& sizeInOut)
67{
68 if (contentOut == nullptr || sizeInOut == 0u)
69 {
70 return FileError::FILE_TARGET_BUFFER_ERROR;
71 }
72
73 std::ifstream streamIn;
74 const FileError ret = readFile(filePath, fileName, fileType, streamIn);
75 if ( ret != FileError::NONE)
76 {
77 return ret;
78 }
79
80 streamIn.seekg(0, std::ios::end);
81 const size_t fileSize = to_size(streamIn.tellg());
82 streamIn.seekg(0);
83 if (fileSize == 0u)
84 {
85 return FileError::FILE_EMPTY;
86 }
87
88 std::memset(contentOut, 0, sizeInOut * sizeof(Byte));
89 sizeInOut = std::min(sizeInOut, fileSize);
90 streamIn.read(reinterpret_cast<char*>(contentOut), sizeInOut);
91
92 return FileError::NONE;
93}
94
95FileError writeFile(const ResourcePath& filePath, const std::string_view fileName, const char* content, const size_t length, const FileType fileType)
96{
97 if (!filePath.empty() && content != nullptr && length > 0)
98 {
99 if (!pathExists(filePath) && createDirectory(filePath) != FileError::NONE)
100 {
101 return FileError::FILE_NOT_FOUND;
102 }
103
104 std::ofstream outputFile((filePath / fileName).fileSystemPath(),
105 fileType == FileType::BINARY
106 ? std::ios::out | std::ios::binary
107 : std::ios::out);
108
109 outputFile.write(content, length);
110 outputFile.close();
111 if (!outputFile)
112 {
113 return FileError::FILE_WRITE_ERROR;
114 }
115
116 return FileError::NONE;
117 }
118
119 return FileError::FILE_NOT_FOUND;
120}
121
122string stripQuotes( const std::string_view input)
123{
124
125 if (input.empty())
126 {
127 return "";
128 }
129
130 string ret { input };
131 ret.erase(std::remove(std::begin(ret), std::end(ret), '\"'), std::end(ret));
132 return ret;
133}
134
136{
137 return FileNameAndPath
138 {
139 input.fileSystemPath().filename().generic_string().c_str(),
140 ResourcePath( input.fileSystemPath().parent_path().generic_string().c_str() )
141 };
142}
143
144bool pathExists(const ResourcePath& filePath)
145{
146 std::error_code ec;
147 const bool ret = is_directory(filePath.fileSystemPath(), ec);
148 return ec ? false : ret;
149}
150
151FileError createDirectory(const ResourcePath& path)
152{
153 NO_DESTROY static Mutex s_DirectoryLock;
154 LockGuard<Mutex> w_lock( s_DirectoryLock );
155
156 if (!pathExists(path))
157 {
158 std::error_code ec;
159 const bool ret = create_directories(path.fileSystemPath(), ec);
160 if (ec)
161 {
162 return FileError::FILE_CREATE_ERROR;
163 }
164
165 if (!ret)
166 {
167 return pathExists(path) ? FileError::NONE : FileError::FILE_CREATE_ERROR;
168 }
169 }
170
171 return FileError::NONE;
172}
173
174FileError removeDirectory( const ResourcePath& path )
175{
176 if ( pathExists(path) )
177 {
178 std::error_code ec;
179 if (std::filesystem::remove_all(path.fileSystemPath(), ec) == 0)
180 {
181 NOP();
182 }
183
184 if (ec)
185 {
186 return FileError::FILE_DELETE_ERROR;
187 }
188 }
189
190 return FileError::NONE;
191}
192
193bool fileExists(const ResourcePath& filePathAndName)
194{
195 std::error_code ec;
196 const bool result = is_regular_file(filePathAndName.fileSystemPath(), ec);
197 return ec ? false : result;
198}
199
200bool fileIsEmpty(const ResourcePath& filePathAndName)
201{
202 std::error_code ec;
203 const bool result = std::filesystem::is_empty(filePathAndName.fileSystemPath(), ec);
204 return ec ? false : result;
205}
206
207FileError fileLastWriteTime(const ResourcePath& filePathAndName, U64& timeOutSec)
208{
209 if (filePathAndName.empty() || !fileExists(filePathAndName))
210 {
211 return FileError::FILE_NOT_FOUND;
212 }
213
214 std::error_code ec;
215 const auto timeStamp = std::filesystem::last_write_time(filePathAndName.fileSystemPath(), ec).time_since_epoch();
216 if (ec)
217 {
218 return FileError::FILE_READ_ERROR;
219 }
220
221 timeOutSec = to_U64(std::chrono::duration_cast<std::chrono::seconds>(timeStamp).count());
222
223 return FileError::NONE;
224}
225
227{
228 return std::count_if( std::filesystem::directory_iterator( path.fileSystemPath() ),
229 std::filesystem::directory_iterator{},
230 [](const std::filesystem::path& p){ return std::filesystem::is_regular_file( p ); });
231}
232
233bool createFile(const ResourcePath& filePathAndName, const bool overwriteExisting)
234{
235 if (overwriteExisting && fileExists(filePathAndName))
236 {
237 return std::ofstream(filePathAndName.string().c_str(), std::fstream::in | std::fstream::trunc).good();
238 }
239
240 if (createDirectory(const_sysInfo()._workingDirectory / splitPathToNameAndLocation(filePathAndName)._path) != FileError::NONE )
241 {
243 }
244
245 return std::ifstream(filePathAndName.string().c_str(), std::fstream::in).good();
246}
247
248FileError openFile(const std::string_view cmd, const ResourcePath& filePath, const std::string_view fileName)
249{
250 if (fileName.empty() || !fileExists(filePath, fileName))
251 {
252 return FileError::FILE_NOT_FOUND;
253 }
254
255 const ResourcePath file = const_sysInfo()._workingDirectory / filePath / fileName;
256
257 bool ret = false;
258 if (cmd.empty())
259 {
260 ret = CallSystemCmd(file.string(), "");
261 }
262 else
263 {
264 ret = CallSystemCmd( cmd, file.string() );
265 }
266
267 return ret ? FileError::NONE : FileError::FILE_OPEN_ERROR;
268}
269
270FileError deleteFile(const ResourcePath& filePath, const std::string_view fileName)
271{
272 if ( fileName.empty() )
273 {
274 return FileError::FILE_NOT_FOUND;
275 }
276
277 const ResourcePath fullPath{ filePath / fileName };
278 if (!fileExists(fullPath))
279 {
280 return FileError::FILE_NOT_FOUND;
281 }
282
283 std::error_code ec;
284 if (std::filesystem::remove(fullPath.fileSystemPath(), ec))
285 {
286 return FileError::NONE;
287 }
288
289 return FileError::FILE_DELETE_ERROR;
290}
291
292FileError copyFile(const ResourcePath& sourcePath, const std::string_view sourceName, const ResourcePath& targetPath, const std::string_view targetName, const bool overwrite)
293{
294 if (sourceName.empty() || targetName.empty())
295 {
296 return FileError::FILE_NOT_FOUND;
297 }
298
299 const ResourcePath source{ sourcePath / sourceName };
300
301 if (!fileExists(source))
302 {
303 return FileError::FILE_NOT_FOUND;
304 }
305
306 const ResourcePath target{ targetPath / targetName };
307
308 if (!overwrite && fileExists(target))
309 {
310 return FileError::FILE_OVERWRITE_ERROR;
311 }
312
313 std::error_code ec;
314 if (copy_file(source.fileSystemPath(),
315 target.fileSystemPath(),
316 std::filesystem::copy_options::overwrite_existing,
317 ec) && !ec)
318 {
319 return FileError::NONE;
320 }
321
322 return FileError::FILE_COPY_ERROR;
323}
324
325FileError copyDirectory( const ResourcePath& sourcePath, const ResourcePath& targetPath, bool recursively, bool overwrite )
326{
327 if (!pathExists(sourcePath))
328 {
329 return FileError::FILE_NOT_FOUND;
330 }
331
332 if (!overwrite && pathExists(targetPath))
333 {
334 return FileError::FILE_OVERWRITE_ERROR;
335 }
336
337 std::error_code ec;
338 if ( !std::filesystem::exists( targetPath.fileSystemPath(), ec ) )
339 {
340 std::filesystem::create_directories( targetPath.fileSystemPath(), ec );
341 }
342
343 if ( !ec )
344 {
345 std::filesystem::copy(sourcePath.fileSystemPath(),
346 targetPath.fileSystemPath(),
347 (overwrite ? std::filesystem::copy_options::overwrite_existing : std::filesystem::copy_options::none) |
348 (recursively ? std::filesystem::copy_options::recursive : std::filesystem::copy_options::none),
349 ec);
350 }
351
352 return ec ? FileError::FILE_COPY_ERROR: FileError::NONE;
353}
354
355FileError findFile(const ResourcePath& filePath, const std::string_view fileName, string& foundPath)
356{
357 const std::filesystem::path file_name(fileName);
358
359 const std::filesystem::recursive_directory_iterator end;
360 const auto it = std::find_if(std::filesystem::recursive_directory_iterator( filePath.fileSystemPath()),
361 end,
362 [&file_name](const std::filesystem::directory_entry& e)
363 {
364 const bool ret = e.path().filename() == file_name;
365 return ret;
366 });
367 if (it == end)
368 {
369 return FileError::FILE_NOT_FOUND;
370 }
371
372 foundPath = it->path().string();
373 return FileError::NONE;
374}
375
376string getExtension(const std::string_view fileName)
377{
378 return getExtension(ResourcePath{ fileName });
379}
380
381string getExtension(const ResourcePath& fileName )
382{
383 return string { fileName.fileSystemPath().extension().string().c_str() };
384}
385
387{
388 return ResourcePath { filePath.fileSystemPath().filename().string() };
389}
390
391string stripExtension( const std::string_view fileName ) noexcept
392{
393 return stripExtension(ResourcePath{fileName}).string();
394}
395
396ResourcePath stripExtension( const ResourcePath& filePath ) noexcept
397{
398 return ResourcePath{ filePath.fileSystemPath().stem().string() };
399}
400
401bool hasExtension(const ResourcePath& filePath, const std::string_view extensionNoDot)
402{
403 return hasExtension(filePath.string(), extensionNoDot);
404}
405
406bool hasExtension(const std::string_view filePath, const std::string_view extensionNoDot)
407{
408 const string targetExt = getExtension(filePath);
409 if (extensionNoDot.empty())
410 {
411 return targetExt.empty();
412 }
413
414 if (targetExt.empty())
415 {
416 return false;
417 }
418
419 return Util::CompareIgnoreCase(targetExt.substr(1), extensionNoDot);
420}
421
422bool deleteAllFiles(const ResourcePath& filePath, const char* extension, const char* extensionToSkip)
423{
424 bool ret = false;
425
426 if (pathExists(filePath))
427 {
428 for (const auto& p : std::filesystem::directory_iterator(filePath.fileSystemPath()))
429 {
430 try
431 {
432 if (is_regular_file(p.status()))
433 {
434 const auto extensionString = p.path().extension().string().substr( 1 );
435 if (extensionToSkip && Util::CompareIgnoreCase( extensionString.c_str(), extensionToSkip) )
436 {
437 continue;
438 }
439
440 if (!extension || Util::CompareIgnoreCase( extensionString.c_str(), extension ))
441 {
442 if (std::filesystem::remove(p.path()))
443 {
444 ret = true;
445 }
446 }
447 }
448 else
449 {
450 //ToDo: check if this recurse in subfolders actually works
451 if (!deleteAllFiles(ResourcePath{ p.path().string() }, extension , extensionToSkip))
452 {
453 NOP();
454 }
455 }
456 }
457 catch ([[maybe_unused]] const std::exception &ex)
458 {
459 NOP();
460 }
461 }
462 }
463
464 return ret;
465}
466
467bool getAllFilesInDirectory( const ResourcePath& filePath, FileList& listInOut, const char* extensionNoDot )
468{
469 bool ret = false;
470 if (pathExists(filePath))
471 {
472 for (const auto& p : std::filesystem::directory_iterator( filePath.fileSystemPath() ))
473 {
474 try
475 {
476 if (is_regular_file(p.status()))
477 {
478 const auto extensionString = p.path().extension().string().substr( 1 );
479
480 if (!extensionNoDot || Util::CompareIgnoreCase(extensionString.c_str(), extensionNoDot))
481 {
482 const U64 timeOutSec = to_U64(std::chrono::duration_cast<std::chrono::seconds>(p.last_write_time().time_since_epoch()).count());
483
484 listInOut.emplace_back(FileEntry
485 {
486 ._name = ResourcePath{ p.path().filename().string() },
487 ._lastWriteTime = timeOutSec
488 });
489 ret = true;
490 }
491 }
492 else
493 {
494 if (!getAllFilesInDirectory(ResourcePath{ p.path().string() }, listInOut, extensionNoDot))
495 {
496 NOP();
497 }
498 }
499 }
500 catch ([[maybe_unused]] const std::exception& ex)
501 {
502 NOP();
503 }
504 }
505 }
506
507 return ret;
508}
509
510string extractFilePathAndName(char* argv0)
511{
512 auto currentPath = std::filesystem::current_path();
513 currentPath.append(argv0);
514
515 std::error_code ec;
516 std::filesystem::path p(canonical(currentPath, ec));
517
518 return p.make_preferred().string().c_str();
519}
520
521}; //namespace Divide
#define NO_DESTROY
#define DIVIDE_UNEXPECTED_CALL()
#define NOP()
bool CompareIgnoreCase(const char *a, const char *b) noexcept
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
FileError removeDirectory(const ResourcePath &path)
FileError openFile(const std::string_view cmd, const ResourcePath &filePath, const std::string_view fileName)
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
std::byte Byte
ResourcePath getTopLevelFolderName(const ResourcePath &filePath)
bool hasExtension(const ResourcePath &filePath, const std::string_view extensionNoDot)
FileError writeFile(const ResourcePath &filePath, const std::string_view fileName, const char *content, const size_t length, const FileType fileType)
std::mutex Mutex
Definition: SharedMutex.h:40
FileError readFile(const ResourcePath &filePath, std::string_view fileName, FileType fileType, std::ifstream &sreamOut)
constexpr U64 to_U64(const T value)
size_t numberOfFilesInDirectory(const ResourcePath &path)
bool CallSystemCmd(std::string_view cmd, std::string_view args)
ResourcePath getWorkingDirectory()
bool deleteAllFiles(const ResourcePath &filePath, const char *extension, const char *extensionToSkip)
string getExtension(const std::string_view fileName)
FileError createDirectory(const ResourcePath &path)
FileError copyFile(const ResourcePath &sourcePath, const std::string_view sourceName, const ResourcePath &targetPath, const std::string_view targetName, const bool overwrite)
const SysInfo & const_sysInfo() noexcept
bool fileIsEmpty(const ResourcePath &filePathAndName)
bool getAllFilesInDirectory(const ResourcePath &filePath, FileList &listInOut, const char *extensionNoDot)
FileError findFile(const ResourcePath &filePath, const std::string_view fileName, string &foundPath)
string stripExtension(const std::string_view fileName) noexcept
constexpr size_t to_size(const T value)
FileError copyDirectory(const ResourcePath &sourcePath, const ResourcePath &targetPath, bool recursively, bool overwrite)
FileError deleteFile(const ResourcePath &filePath, const std::string_view fileName)
bool fileExists(const ResourcePath &filePathAndName)
bool pathExists(const ResourcePath &filePath)
string extractFilePathAndName(char *argv0)
uint64_t U64
FileError fileLastWriteTime(const ResourcePath &filePathAndName, U64 &timeOutSec)
FileNameAndPath splitPathToNameAndLocation(const ResourcePath &input)
bool createFile(const ResourcePath &filePathAndName, const bool overwriteExisting)
string stripQuotes(const std::string_view input)
StringReturnType< N > string() const noexcept
Definition: ResourcePath.h:64
bool empty() const noexcept
ResourcePath _workingDirectory