diff options
Diffstat (limited to 'src/common/file_util.h')
| -rw-r--r-- | src/common/file_util.h | 298 |
1 files changed, 0 insertions, 298 deletions
diff --git a/src/common/file_util.h b/src/common/file_util.h deleted file mode 100644 index 840cde2a6..000000000 --- a/src/common/file_util.h +++ /dev/null | |||
| @@ -1,298 +0,0 @@ | |||
| 1 | // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstdio> | ||
| 9 | #include <fstream> | ||
| 10 | #include <functional> | ||
| 11 | #include <limits> | ||
| 12 | #include <optional> | ||
| 13 | #include <string> | ||
| 14 | #include <string_view> | ||
| 15 | #include <type_traits> | ||
| 16 | #include <vector> | ||
| 17 | #include "common/common_types.h" | ||
| 18 | #ifdef _MSC_VER | ||
| 19 | #include "common/string_util.h" | ||
| 20 | #endif | ||
| 21 | |||
| 22 | namespace Common::FS { | ||
| 23 | |||
| 24 | // User paths for GetUserPath | ||
| 25 | enum class UserPath { | ||
| 26 | CacheDir, | ||
| 27 | ConfigDir, | ||
| 28 | KeysDir, | ||
| 29 | LogDir, | ||
| 30 | NANDDir, | ||
| 31 | RootDir, | ||
| 32 | SDMCDir, | ||
| 33 | LoadDir, | ||
| 34 | DumpDir, | ||
| 35 | ScreenshotsDir, | ||
| 36 | ShaderDir, | ||
| 37 | SysDataDir, | ||
| 38 | UserDir, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // FileSystem tree node/ | ||
| 42 | struct FSTEntry { | ||
| 43 | bool isDirectory; | ||
| 44 | u64 size; // file length or number of entries from children | ||
| 45 | std::string physicalName; // name on disk | ||
| 46 | std::string virtualName; // name in FST names table | ||
| 47 | std::vector<FSTEntry> children; | ||
| 48 | }; | ||
| 49 | |||
| 50 | // Returns true if file filename exists | ||
| 51 | [[nodiscard]] bool Exists(const std::string& filename); | ||
| 52 | |||
| 53 | // Returns true if filename is a directory | ||
| 54 | [[nodiscard]] bool IsDirectory(const std::string& filename); | ||
| 55 | |||
| 56 | // Returns the size of filename (64bit) | ||
| 57 | [[nodiscard]] u64 GetSize(const std::string& filename); | ||
| 58 | |||
| 59 | // Overloaded GetSize, accepts file descriptor | ||
| 60 | [[nodiscard]] u64 GetSize(int fd); | ||
| 61 | |||
| 62 | // Overloaded GetSize, accepts FILE* | ||
| 63 | [[nodiscard]] u64 GetSize(FILE* f); | ||
| 64 | |||
| 65 | // Returns true if successful, or path already exists. | ||
| 66 | bool CreateDir(const std::string& filename); | ||
| 67 | |||
| 68 | // Creates the full path of fullPath returns true on success | ||
| 69 | bool CreateFullPath(const std::string& fullPath); | ||
| 70 | |||
| 71 | // Deletes a given filename, return true on success | ||
| 72 | // Doesn't supports deleting a directory | ||
| 73 | bool Delete(const std::string& filename); | ||
| 74 | |||
| 75 | // Deletes a directory filename, returns true on success | ||
| 76 | bool DeleteDir(const std::string& filename); | ||
| 77 | |||
| 78 | // renames file srcFilename to destFilename, returns true on success | ||
| 79 | bool Rename(const std::string& srcFilename, const std::string& destFilename); | ||
| 80 | |||
| 81 | // copies file srcFilename to destFilename, returns true on success | ||
| 82 | bool Copy(const std::string& srcFilename, const std::string& destFilename); | ||
| 83 | |||
| 84 | // creates an empty file filename, returns true on success | ||
| 85 | bool CreateEmptyFile(const std::string& filename); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * @param num_entries_out to be assigned by the callable with the number of iterated directory | ||
| 89 | * entries, never null | ||
| 90 | * @param directory the path to the enclosing directory | ||
| 91 | * @param virtual_name the entry name, without any preceding directory info | ||
| 92 | * @return whether handling the entry succeeded | ||
| 93 | */ | ||
| 94 | using DirectoryEntryCallable = std::function<bool( | ||
| 95 | u64* num_entries_out, const std::string& directory, const std::string& virtual_name)>; | ||
| 96 | |||
| 97 | /** | ||
| 98 | * Scans a directory, calling the callback for each file/directory contained within. | ||
| 99 | * If the callback returns failure, scanning halts and this function returns failure as well | ||
| 100 | * @param num_entries_out assigned by the function with the number of iterated directory entries, | ||
| 101 | * can be null | ||
| 102 | * @param directory the directory to scan | ||
| 103 | * @param callback The callback which will be called for each entry | ||
| 104 | * @return whether scanning the directory succeeded | ||
| 105 | */ | ||
| 106 | bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, | ||
| 107 | DirectoryEntryCallable callback); | ||
| 108 | |||
| 109 | /** | ||
| 110 | * Scans the directory tree, storing the results. | ||
| 111 | * @param directory the parent directory to start scanning from | ||
| 112 | * @param parent_entry FSTEntry where the filesystem tree results will be stored. | ||
| 113 | * @param recursion Number of children directories to read before giving up. | ||
| 114 | * @return the total number of files/directories found | ||
| 115 | */ | ||
| 116 | u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | ||
| 117 | unsigned int recursion = 0); | ||
| 118 | |||
| 119 | // deletes the given directory and anything under it. Returns true on success. | ||
| 120 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); | ||
| 121 | |||
| 122 | // Returns the current directory | ||
| 123 | [[nodiscard]] std::optional<std::string> GetCurrentDir(); | ||
| 124 | |||
| 125 | // Create directory and copy contents (does not overwrite existing files) | ||
| 126 | void CopyDir(const std::string& source_path, const std::string& dest_path); | ||
| 127 | |||
| 128 | // Set the current directory to given directory | ||
| 129 | bool SetCurrentDir(const std::string& directory); | ||
| 130 | |||
| 131 | // Returns a pointer to a string with a yuzu data dir in the user's home | ||
| 132 | // directory. To be used in "multi-user" mode (that is, installed). | ||
| 133 | const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); | ||
| 134 | |||
| 135 | [[nodiscard]] std::string GetHactoolConfigurationPath(); | ||
| 136 | |||
| 137 | [[nodiscard]] std::string GetNANDRegistrationDir(bool system = false); | ||
| 138 | |||
| 139 | // Returns the path to where the sys file are | ||
| 140 | [[nodiscard]] std::string GetSysDirectory(); | ||
| 141 | |||
| 142 | #ifdef __APPLE__ | ||
| 143 | [[nodiscard]] std::string GetBundleDirectory(); | ||
| 144 | #endif | ||
| 145 | |||
| 146 | #ifdef _WIN32 | ||
| 147 | [[nodiscard]] const std::string& GetExeDirectory(); | ||
| 148 | [[nodiscard]] std::string AppDataRoamingDirectory(); | ||
| 149 | #endif | ||
| 150 | |||
| 151 | std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str); | ||
| 152 | |||
| 153 | std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str); | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Splits the filename into 8.3 format | ||
| 157 | * Loosely implemented following https://en.wikipedia.org/wiki/8.3_filename | ||
| 158 | * @param filename The normal filename to use | ||
| 159 | * @param short_name A 9-char array in which the short name will be written | ||
| 160 | * @param extension A 4-char array in which the extension will be written | ||
| 161 | */ | ||
| 162 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, | ||
| 163 | std::array<char, 4>& extension); | ||
| 164 | |||
| 165 | // Splits the path on '/' or '\' and put the components into a vector | ||
| 166 | // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } | ||
| 167 | [[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); | ||
| 168 | |||
| 169 | // Gets all of the text up to the last '/' or '\' in the path. | ||
| 170 | [[nodiscard]] std::string_view GetParentPath(std::string_view path); | ||
| 171 | |||
| 172 | // Gets all of the text after the first '/' or '\' in the path. | ||
| 173 | [[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path); | ||
| 174 | |||
| 175 | // Gets the filename of the path | ||
| 176 | [[nodiscard]] std::string_view GetFilename(std::string_view path); | ||
| 177 | |||
| 178 | // Gets the extension of the filename | ||
| 179 | [[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name); | ||
| 180 | |||
| 181 | // Removes the final '/' or '\' if one exists | ||
| 182 | [[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path); | ||
| 183 | |||
| 184 | // Creates a new vector containing indices [first, last) from the original. | ||
| 185 | template <typename T> | ||
| 186 | [[nodiscard]] std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, | ||
| 187 | std::size_t last) { | ||
| 188 | if (first >= last) { | ||
| 189 | return {}; | ||
| 190 | } | ||
| 191 | last = std::min<std::size_t>(last, vector.size()); | ||
| 192 | return std::vector<T>(vector.begin() + first, vector.begin() + first + last); | ||
| 193 | } | ||
| 194 | |||
| 195 | enum class DirectorySeparator { | ||
| 196 | ForwardSlash, | ||
| 197 | BackwardSlash, | ||
| 198 | PlatformDefault, | ||
| 199 | }; | ||
| 200 | |||
| 201 | // Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' | ||
| 202 | // depending if directory_separator is BackwardSlash or PlatformDefault and running on windows | ||
| 203 | [[nodiscard]] std::string SanitizePath( | ||
| 204 | std::string_view path, | ||
| 205 | DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash); | ||
| 206 | |||
| 207 | // To deal with Windows being dumb at Unicode | ||
| 208 | template <typename T> | ||
| 209 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { | ||
| 210 | #ifdef _MSC_VER | ||
| 211 | fstream.open(Common::UTF8ToUTF16W(filename), openmode); | ||
| 212 | #else | ||
| 213 | fstream.open(filename, openmode); | ||
| 214 | #endif | ||
| 215 | } | ||
| 216 | |||
| 217 | // simple wrapper for cstdlib file functions to | ||
| 218 | // hopefully will make error checking easier | ||
| 219 | // and make forgetting an fclose() harder | ||
| 220 | class IOFile : public NonCopyable { | ||
| 221 | public: | ||
| 222 | IOFile(); | ||
| 223 | // flags is used for windows specific file open mode flags, which | ||
| 224 | // allows yuzu to open the logs in shared write mode, so that the file | ||
| 225 | // isn't considered "locked" while yuzu is open and people can open the log file and view it | ||
| 226 | IOFile(const std::string& filename, const char openmode[], int flags = 0); | ||
| 227 | |||
| 228 | ~IOFile(); | ||
| 229 | |||
| 230 | IOFile(IOFile&& other) noexcept; | ||
| 231 | IOFile& operator=(IOFile&& other) noexcept; | ||
| 232 | |||
| 233 | void Swap(IOFile& other) noexcept; | ||
| 234 | |||
| 235 | bool Open(const std::string& filename, const char openmode[], int flags = 0); | ||
| 236 | bool Close(); | ||
| 237 | |||
| 238 | template <typename T> | ||
| 239 | std::size_t ReadArray(T* data, std::size_t length) const { | ||
| 240 | static_assert(std::is_trivially_copyable_v<T>, | ||
| 241 | "Given array does not consist of trivially copyable objects"); | ||
| 242 | |||
| 243 | return ReadImpl(data, length, sizeof(T)); | ||
| 244 | } | ||
| 245 | |||
| 246 | template <typename T> | ||
| 247 | std::size_t WriteArray(const T* data, std::size_t length) { | ||
| 248 | static_assert(std::is_trivially_copyable_v<T>, | ||
| 249 | "Given array does not consist of trivially copyable objects"); | ||
| 250 | |||
| 251 | return WriteImpl(data, length, sizeof(T)); | ||
| 252 | } | ||
| 253 | |||
| 254 | template <typename T> | ||
| 255 | std::size_t ReadBytes(T* data, std::size_t length) const { | ||
| 256 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); | ||
| 257 | return ReadArray(reinterpret_cast<char*>(data), length); | ||
| 258 | } | ||
| 259 | |||
| 260 | template <typename T> | ||
| 261 | std::size_t WriteBytes(const T* data, std::size_t length) { | ||
| 262 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); | ||
| 263 | return WriteArray(reinterpret_cast<const char*>(data), length); | ||
| 264 | } | ||
| 265 | |||
| 266 | template <typename T> | ||
| 267 | std::size_t WriteObject(const T& object) { | ||
| 268 | static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer"); | ||
| 269 | return WriteArray(&object, 1); | ||
| 270 | } | ||
| 271 | |||
| 272 | std::size_t WriteString(std::string_view str) { | ||
| 273 | return WriteArray(str.data(), str.length()); | ||
| 274 | } | ||
| 275 | |||
| 276 | [[nodiscard]] bool IsOpen() const { | ||
| 277 | return nullptr != m_file; | ||
| 278 | } | ||
| 279 | |||
| 280 | bool Seek(s64 off, int origin) const; | ||
| 281 | [[nodiscard]] u64 Tell() const; | ||
| 282 | [[nodiscard]] u64 GetSize() const; | ||
| 283 | bool Resize(u64 size); | ||
| 284 | bool Flush(); | ||
| 285 | |||
| 286 | // clear error state | ||
| 287 | void Clear() { | ||
| 288 | std::clearerr(m_file); | ||
| 289 | } | ||
| 290 | |||
| 291 | private: | ||
| 292 | std::size_t ReadImpl(void* data, std::size_t length, std::size_t data_size) const; | ||
| 293 | std::size_t WriteImpl(const void* data, std::size_t length, std::size_t data_size); | ||
| 294 | |||
| 295 | std::FILE* m_file = nullptr; | ||
| 296 | }; | ||
| 297 | |||
| 298 | } // namespace Common::FS | ||