fileAPI.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2020 to 2022 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. /*
  24. TODO:
  25. * Test that overwriting a large file with a smaller file does not leave anything from the overwritten file on any system.
  26. * bool file_createFolder(const ReadableString& path);
  27. WINBASEAPI WINBOOL WINAPI CreateDirectoryW (LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
  28. mkdir on Posix
  29. * bool file_remove(const ReadableString& path);
  30. WINBASEAPI WINBOOL WINAPI DeleteFileW (LPCWSTR lpFileName);
  31. */
  32. #ifndef DFPSR_API_FILE
  33. #define DFPSR_API_FILE
  34. #include "../api/stringAPI.h"
  35. #include "bufferAPI.h"
  36. #if defined(WIN32) || defined(_WIN32)
  37. #define USE_MICROSOFT_WINDOWS
  38. #endif
  39. // TODO: Create regression tests for the file system.
  40. // A module for file access that exists to prevent cyclic dependencies between strings and buffers.
  41. // Buffers need a filename to be saved or loaded while strings use buffers to store their characters.
  42. namespace dsr {
  43. // Post-condition:
  44. // Returns the content of the readable file referred to by file_optimizePath(filename).
  45. // If mustExist is true, then failure to load will throw an exception.
  46. // If mustExist is false, then failure to load will return an empty handle (returning false for buffer_exists).
  47. Buffer file_loadBuffer(const ReadableString& filename, bool mustExist = true);
  48. // Side-effect: Saves buffer to file_optimizePath(filename) as a binary file.
  49. // Pre-condition: buffer exists
  50. void file_saveBuffer(const ReadableString& filename, Buffer buffer);
  51. // Get a path separator for the target operating system.
  52. // Can be used to construct a file path that works for both forward and backward slash separators.
  53. const char32_t* file_separator();
  54. // Turns / and \ into the local system's convention, so that loading and saving files can use either one of them automatically.
  55. // TODO: Remove redundant . and .. to reduce the risk of running out of buffer space.
  56. String file_optimizePath(const ReadableString &path);
  57. // Returns the local name of the file or folder after the last path separator, or the whole path if no separator was found.
  58. // Examples with / as the path separator:
  59. // file_getFolderPath(U"MyFolder/Cars.txt") == U"Cars.txt"
  60. // file_getFolderPath(U"MyFolder/") == U""
  61. // file_getFolderPath(U"MyFolder") == U"MyFolder"
  62. // file_getFolderPath(U"MyFolder/Folder2") == U"Folder2"
  63. ReadableString file_getPathlessName(const ReadableString &path);
  64. // Returns the parent folder path with anything after the last slash removed, or empty if there was no slash left.
  65. // Examples with / as the path separator:
  66. // file_getFolderPath(U"MyFolder/Documents/Cars.txt") == U"MyFolder/Documents"
  67. // file_getFolderPath(U"MyFolder/Documents/") == U"MyFolder/Documents"
  68. // file_getFolderPath(U"MyFolder/Documents") == U"MyFolder"
  69. // file_getFolderPath(U"MyFolder") == U""
  70. ReadableString file_getParentFolder(const ReadableString &path);
  71. // Combines two parts into a path and automatically adding a local separator when needed.
  72. // Can be used to get the full path of a file in a folder or add another folder to the path.
  73. // b may not begin with a separator, because only a is allowed to contain the root.
  74. // Examples with / as the path separator:
  75. // file_combinePaths(U"Folder", U"Document.txt") == U"Folder/Document.txt"
  76. // file_combinePaths(U"Folder/", U"Document.txt") == U"Folder/Document.txt"
  77. String file_combinePaths(const ReadableString &a, const ReadableString &b);
  78. // Returns true iff path contains a root, according to the local path syntax.
  79. // If treatHomeFolderAsRoot is true, starting from the home folder using the Posix ~ alias will be allowed.
  80. bool file_hasRoot(const ReadableString &path, bool treatHomeFolderAsRoot = true);
  81. // DSR_MAIN_CALLER is a convenient wrapper for getting input arguments as a list of portable Unicode strings.
  82. // The actual main function gets placed in DSR_MAIN_CALLER, which calls the given function.
  83. // Example:
  84. // DSR_MAIN_CALLER(dsrMain)
  85. // void dsrMain(List<String> args) {
  86. // printText("Input arguments:\n");
  87. // for (int a = 0; a < args.length(); a++) {
  88. // printText(" args[", a, "] = ", args[a], "\n");
  89. // }
  90. // }
  91. #ifdef USE_MICROSOFT_WINDOWS
  92. #define DSR_MAIN_CALLER(MAIN_NAME) \
  93. void MAIN_NAME(List<String> args); \
  94. int main() { MAIN_NAME(file_impl_getInputArguments()); return 0; }
  95. #else
  96. #define DSR_MAIN_CALLER(MAIN_NAME) \
  97. void MAIN_NAME(List<String> args); \
  98. int main(int argc, char **argv) { MAIN_NAME(file_impl_convertInputArguments(argc, (void**)argv)); return 0; }
  99. #endif
  100. // Helper functions have to be exposed for the macro handle your input arguments.
  101. // Do not call these yourself.
  102. List<String> file_impl_convertInputArguments(int argn, void **argv);
  103. List<String> file_impl_getInputArguments();
  104. // Get the current path, from where the application was called and relative paths start.
  105. String file_getCurrentPath();
  106. // Side-effects: Sets the current path to file_optimizePath(path).
  107. // Post-condition: Returns Returns true on success and false on failure.
  108. bool file_setCurrentPath(const ReadableString &path);
  109. // Post-condition: Returns the application's folder path, from where the application is stored.
  110. // If not implemented and allowFallback is true,
  111. // the current path is returned instead as a qualified guess instead of raising an exception.
  112. String file_getApplicationFolder(bool allowFallback = true);
  113. // Gets an absolute version of the path, quickly without removing redundancy.
  114. String file_getAbsolutePath(const ReadableString &path);
  115. // Pre-condition: filename must refer to a file so that file_getEntryType(filename) == EntryType::File.
  116. // Post-condition: Returns a structure with information about the file at file_optimizePath(filename), or -1 if no such file exists.
  117. int64_t file_getFileSize(const ReadableString& filename);
  118. // Entry types distinguish between files folders and other things in the file system.
  119. enum class EntryType { NotFound, UnhandledType, File, Folder, SymbolicLink };
  120. String& string_toStreamIndented(String& target, const EntryType& source, const ReadableString& indentation);
  121. // Post-condition: Returns what the file_optimizePath(path) points to in the filesystem.
  122. // Different comparisons on the result can be used to check if something exists.
  123. // Use file_getEntryType(filename) == EntryType::File to check if a file exists.
  124. // Use file_getEntryType(folderPath) == EntryType::Folder to check if a folder exists.
  125. // Use file_getEntryType(path) != EntryType::NotFound to check if the path leads to anything.
  126. EntryType file_getEntryType(const ReadableString &path);
  127. // Side-effects: Calls action with the entry's path, name and type for everything detected in folderPath.
  128. // entryPath equals file_combinePaths(folderPath, entryName), and is used for recursive calls when entryType == EntryType::Folder.
  129. // entryName equals file_getPathlessName(entryPath).
  130. // entryType equals file_getEntryType(entryPath).
  131. // Post-condition: Returns true iff the folder could be found.
  132. bool file_getFolderContent(const ReadableString& folderPath, std::function<void(const ReadableString& entryPath, const ReadableString& entryName, EntryType entryType)> action);
  133. }
  134. #endif