Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/filesystem.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include "file.h" | |
| 4 #include "fsitem.h" | |
| 5 #include <functional> | |
| 6 | |
| 7 #ifndef _WIN32 | |
| 8 struct stat; | |
| 9 #endif | |
| 10 | |
| 11 //! Contains various I/O related structures and interfaces. | |
| 12 namespace foobar2000_io | |
| 13 { | |
| 14 | |
| 15 //! Disk space info struct | |
| 16 struct drivespace_t { | |
| 17 //! Free space, in bytes | |
| 18 t_filesize m_free = filesize_invalid; | |
| 19 //! Total size, in bytes | |
| 20 t_filesize m_total = filesize_invalid; | |
| 21 //! Free space available to caller, in bytes \n | |
| 22 //! If not specifically supported by filesystem, same as m_free. | |
| 23 t_filesize m_avail = filesize_invalid; | |
| 24 }; | |
| 25 | |
| 26 | |
| 27 | |
| 28 class filesystem; | |
| 29 | |
| 30 class NOVTABLE directory_callback { | |
| 31 public: | |
| 32 //! @returns true to continue enumeration, false to abort. | |
| 33 virtual bool on_entry(filesystem * p_owner,abort_callback & p_abort,const char * p_url,bool p_is_subdirectory,const t_filestats & p_stats)=0; | |
| 34 }; | |
| 35 | |
| 36 class NOVTABLE directory_callback_v3 { | |
| 37 public: | |
| 38 virtual bool on_entry(filesystem* owner, const char* URL, t_filestats2 const& stats, abort_callback& abort) = 0; | |
| 39 }; | |
| 40 | |
| 41 //! Entrypoint service for all filesystem operations.\n | |
| 42 //! Implementation: standard implementations for local filesystem etc are provided by core.\n | |
| 43 //! Instantiation: use static helper functions rather than calling filesystem interface methods directly, e.g. filesystem::g_open() to open a file. | |
| 44 class NOVTABLE filesystem : public service_base { | |
| 45 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(filesystem); | |
| 46 public: | |
| 47 //! Enumeration specifying how to open a file. See: filesystem::open(), filesystem::g_open(). | |
| 48 typedef uint32_t t_open_mode; | |
| 49 enum { | |
| 50 //! Opens an existing file for reading; if the file does not exist, the operation will fail. | |
| 51 open_mode_read, | |
| 52 //! Opens an existing file for writing; if the file does not exist, the operation will fail. | |
| 53 open_mode_write_existing, | |
| 54 //! Opens a new file for writing; if the file exists, its contents will be wiped. | |
| 55 open_mode_write_new, | |
| 56 | |
| 57 open_mode_mask = 0xFF, | |
| 58 open_shareable = 0x100, | |
| 59 }; | |
| 60 | |
| 61 virtual bool get_canonical_path(const char * p_path,pfc::string_base & p_out)=0; | |
| 62 virtual bool is_our_path(const char * p_path)=0; | |
| 63 virtual bool get_display_path(const char * p_path,pfc::string_base & p_out)=0; | |
| 64 | |
| 65 virtual void open(service_ptr_t<file> & p_out,const char * p_path, t_open_mode p_mode,abort_callback & p_abort)=0; | |
| 66 virtual void remove(const char * p_path,abort_callback & p_abort)=0; | |
| 67 //! Moves/renames a file. Will fail if the destination file already exists. \n | |
| 68 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 69 virtual void move(const char * p_src,const char * p_dst,abort_callback & p_abort)=0; | |
| 70 //! Queries whether a file at specified path belonging to this filesystem is a remote object or not. | |
| 71 virtual bool is_remote(const char * p_src) = 0; | |
| 72 | |
| 73 //! Retrieves stats of a file at specified path. | |
| 74 virtual void get_stats(const char * p_path,t_filestats & p_stats,bool & p_is_writeable,abort_callback & p_abort) = 0; | |
| 75 //! Helper | |
| 76 t_filestats get_stats( const char * path, abort_callback & abort ); | |
| 77 | |
| 78 virtual bool relative_path_create(const char* file_path, const char* playlist_path, pfc::string_base& out) { (void)file_path; (void)playlist_path; (void)out; return false; } | |
| 79 virtual bool relative_path_parse(const char* relative_path, const char* playlist_path, pfc::string_base& out) { (void)relative_path; (void)playlist_path; (void)out; return false; } | |
| 80 | |
| 81 //! Creates a directory. | |
| 82 virtual void create_directory(const char * p_path,abort_callback & p_abort) = 0; | |
| 83 | |
| 84 virtual void list_directory(const char * p_path,directory_callback & p_out,abort_callback & p_abort)=0; | |
| 85 | |
| 86 //! Hint; returns whether this filesystem supports mime types. \n | |
| 87 //! When this returns false, all file::get_content_type() calls on files opened thru this filesystem implementation will return false; otherwise, file::get_content_type() calls may return true depending on the file. | |
| 88 virtual bool supports_content_types() = 0; | |
| 89 | |
| 90 static void g_get_canonical_path(const char * path,pfc::string_base & out); | |
| 91 static void g_get_display_path(const char * path,pfc::string_base & out); | |
| 92 static void g_get_display_path(const char* path, pfc::string_base& out, filesystem::ptr & reuseMe); | |
| 93 //! Retrieves a shortened display name for this file. By default this is implemented by returning filename.ext portion of the path. | |
| 94 static bool g_get_display_name_short( const char * path, pfc::string_base & out ); | |
| 95 //! Extracts the native filesystem path, sets out to the input path if native path cannot be extracted so the output is always set. | |
| 96 //! @returns True if native path was extracted successfully, false otherwise (but output is set anyway). | |
| 97 static bool g_get_native_path( const char * path, pfc::string_base & out, abort_callback & a = fb2k::noAbort); | |
| 98 static pfc::string8 g_get_native_path( const char * path, abort_callback & a = fb2k::noAbort ); | |
| 99 | |
| 100 static bool g_get_interface(service_ptr_t<filesystem> & p_out,const char * path);//path is AFTER get_canonical_path | |
| 101 static filesystem::ptr g_get_interface(const char * path);// throws exception_io_no_handler_for_path on failure | |
| 102 static filesystem::ptr get( const char * path ) { return g_get_interface(path); } // shortened; never returns null, throws on failure | |
| 103 static filesystem::ptr getLocalFS(); // returns local filesystem object | |
| 104 static filesystem::ptr tryGet(const char* path); // returns null if not found instead of throwing | |
| 105 static bool g_is_remote(const char * p_path);//path is AFTER get_canonical_path | |
| 106 static bool g_is_recognized_and_remote(const char * p_path);//path is AFTER get_canonical_path | |
| 107 static bool g_is_remote_safe(const char * p_path) {return g_is_recognized_and_remote(p_path);} | |
| 108 static bool g_is_remote_or_unrecognized(const char * p_path); | |
| 109 static bool g_is_recognized_path(const char * p_path); | |
| 110 | |
| 111 //! Opens file at specified path, with specified access privileges. | |
| 112 static void g_open(service_ptr_t<file> & p_out,const char * p_path,t_open_mode p_mode,abort_callback & p_abort); | |
| 113 //! Attempts to open file at specified path; if the operation fails with sharing violation error, keeps retrying (with short sleep period between retries) for specified amount of time. | |
| 114 static void g_open_timeout(service_ptr_t<file> & p_out,const char * p_path,t_open_mode p_mode,double p_timeout,abort_callback & p_abort); | |
| 115 static void g_open_write_new(service_ptr_t<file> & p_out,const char * p_path,abort_callback & p_abort); | |
| 116 static void g_open_read(service_ptr_t<file> & p_out,const char * path,abort_callback & p_abort) {return g_open(p_out,path,open_mode_read,p_abort);} | |
| 117 static void g_open_precache(service_ptr_t<file> & p_out,const char * path,abort_callback & p_abort);//open only for precaching data (eg. will fail on http etc) | |
| 118 static bool g_exists(const char * p_path,abort_callback & p_abort); | |
| 119 static bool g_exists_writeable(const char * p_path,abort_callback & p_abort); | |
| 120 //! Removes file at specified path. | |
| 121 static void g_remove(const char * p_path,abort_callback & p_abort); | |
| 122 //! Attempts to remove file at specified path; if the operation fails with a sharing violation error, keeps retrying (with short sleep period between retries) for specified amount of time. | |
| 123 static void g_remove_timeout(const char * p_path,double p_timeout,abort_callback & p_abort); | |
| 124 //! Moves file from one path to another. | |
| 125 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 126 static void g_move(const char * p_src,const char * p_dst,abort_callback & p_abort); | |
| 127 //! Attempts to move file from one path to another; if the operation fails with a sharing violation error, keeps retrying (with short sleep period between retries) for specified amount of time. | |
| 128 static void g_move_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort); | |
| 129 | |
| 130 static void g_link(const char * p_src,const char * p_dst,abort_callback & p_abort); | |
| 131 static void g_link_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort); | |
| 132 | |
| 133 static void g_copy(const char * p_src,const char * p_dst,abort_callback & p_abort);//needs canonical path | |
| 134 static void g_copy_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort);//needs canonical path | |
| 135 static void g_copy_directory(const char * p_src,const char * p_dst,abort_callback & p_abort);//needs canonical path | |
| 136 static void g_get_stats(const char * p_path,t_filestats & p_stats,bool & p_is_writeable,abort_callback & p_abort); | |
| 137 static bool g_relative_path_create(const char * p_file_path,const char * p_playlist_path,pfc::string_base & out); | |
| 138 static bool g_relative_path_parse(const char * p_relative_path,const char * p_playlist_path,pfc::string_base & out); | |
| 139 | |
| 140 static void g_create_directory(const char * p_path,abort_callback & p_abort); | |
| 141 | |
| 142 static void g_open_temp(service_ptr_t<file> & p_out,abort_callback & p_abort); | |
| 143 static void g_open_tempmem(service_ptr_t<file> & p_out,abort_callback & p_abort); | |
| 144 static file::ptr g_open_tempmem(); | |
| 145 | |
| 146 static void g_list_directory(const char * p_path,directory_callback & p_out,abort_callback & p_abort);// path must be canonical | |
| 147 | |
| 148 static bool g_is_valid_directory(const char * path,abort_callback & p_abort); | |
| 149 static bool g_is_empty_directory(const char * path,abort_callback & p_abort); | |
| 150 | |
| 151 void remove_object_recur(const char * path, abort_callback & abort); | |
| 152 void remove_directory_content(const char * path, abort_callback & abort); | |
| 153 static void g_remove_object_recur(const char * path, abort_callback & abort); | |
| 154 static void g_remove_object_recur_timeout(const char * path, double timeout, abort_callback & abort); | |
| 155 | |
| 156 // Presumes both source and destination belong to this filesystem. | |
| 157 void copy_directory(const char * p_src, const char * p_dst, abort_callback & p_abort); | |
| 158 void copy_directory_contents(const char* p_src, const char* p_dst, abort_callback& p_abort); | |
| 159 | |
| 160 //! Moves/renames a file, overwriting the destination atomically if exists. \n | |
| 161 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 162 void move_overwrite( const char * src, const char * dst, abort_callback & abort); | |
| 163 //! Moves/renames a file, overwriting the destination atomically if exists. \n | |
| 164 //! Meant to retain destination attributes if feasible. Otherwise identical to move_overwrite(). \n | |
| 165 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 166 void replace_file(const char * src, const char * dst, abort_callback & abort); | |
| 167 //! Create a directory, without throwing an exception if it already exists. | |
| 168 //! @param didCreate bool flag indicating whether a new directory was created or not. \n | |
| 169 //! This should be a retval, but because it's messy to obtain this information with certain APIs, the caller can opt out of receiving this information,. | |
| 170 void make_directory( const char * path, abort_callback & abort, bool * didCreate = nullptr ); | |
| 171 //! Bool retval version of make_directory(). | |
| 172 bool make_directory_check( const char * path, abort_callback & abort ); | |
| 173 | |
| 174 //! Returns whether a directory exists at path, false if doesn't exist or not a directory. | |
| 175 bool directory_exists(const char * path, abort_callback & abort); | |
| 176 //! Returns whether a file exists at path, false if doesn't exist or not a file. | |
| 177 bool file_exists( const char * path, abort_callback & abort ); | |
| 178 //! Returns whether either a file or a directory exists at path. Effectively directory_exists() || file_exists(), but somewhat more efficient. | |
| 179 bool exists(const char* path, abort_callback& a); | |
| 180 | |
| 181 char pathSeparator(); | |
| 182 //! Extracts the filename.ext portion of the path. \n | |
| 183 //! The filename is ready to be presented to the user - URL decoding and such (similar to get_display_path()) is applied. | |
| 184 void extract_filename_ext(const char * path, pfc::string_base & outFN); | |
| 185 pfc::string8 extract_filename_ext(const char* path); | |
| 186 pfc::string8 get_extension(const char* path); | |
| 187 static pfc::string8 g_get_extension(const char* path); | |
| 188 //! Retrieves the parent path. | |
| 189 bool get_parent_path(const char * path, pfc::string_base & out); | |
| 190 //! Retrieves the parent path, alternate version. | |
| 191 fb2k::stringRef parentPath(const char* path); | |
| 192 | |
| 193 file::ptr openWriteNew( const char * path, abort_callback & abort, double timeout ); | |
| 194 file::ptr openWriteExisting(const char * path, abort_callback & abort, double timeout); | |
| 195 file::ptr openRead( const char * path, abort_callback & abort, double timeout); | |
| 196 file::ptr openEx( const char * path, t_open_mode mode, abort_callback & abort, double timeout); | |
| 197 void remove_(const char* path, abort_callback& a, double timeout); | |
| 198 | |
| 199 //! Read whole file into a mem_block_container | |
| 200 void read_whole_file(const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort ); | |
| 201 //! Alternate read whole file, fb2k mobile style | |
| 202 fb2k::memBlockRef readWholeFile(const char* path, size_t maxBytes, abort_callback& abort); | |
| 203 static fb2k::memBlockRef g_readWholeFile(const char * path, size_t sizeSanity, abort_callback & aborter); | |
| 204 | |
| 205 bool is_transacted(); | |
| 206 bool commit_if_transacted(abort_callback &abort); | |
| 207 | |
| 208 //! Full file rewrite helper that automatically does the right thing to ensure atomic update. \n | |
| 209 //! If this is a transacted filesystem, a simple in-place rewrite is performed. \n | |
| 210 //! If this is not a transacted filesystem, your content first goes to a temporary file, which then replaces the original. \n | |
| 211 //! See also: filesystem_transacted. \n | |
| 212 //! In order to perform transacted operations, you must obtain a transacted filesystem explicitly, or get one passed down from a higher level context (example: in config_io_callback_v3). | |
| 213 void rewrite_file( const char * path, abort_callback & abort, double opTimeout, std::function<void (file::ptr) > worker ); | |
| 214 void rewrite_file(const char* path, abort_callback& abort, double opTimeout, const void* payload, size_t bytes); | |
| 215 //! Full directory rewrite helper that automatically does the right thing to ensure atomic update. \n | |
| 216 //! If this is a transacted filesystem, a simple in-place rewrite is performed. \n | |
| 217 //! If this is not a transacted filesystem, your content first goes to a temporary folder, which then replaces the original. \n | |
| 218 //! It is encouraged to perform flushFileBuffers on all files accessed from within. \n | |
| 219 //! See also: filesystem_transacted. \n | |
| 220 //! In order to perform transacted operations, you must obtain a transacted filesystem explicitly, or get one passed down from a higher level context (example: in config_io_callback_v3). | |
| 221 void rewrite_directory(const char * path, abort_callback & abort, double opTimeout, std::function<void(const char *) > worker); | |
| 222 | |
| 223 t_filestats2 get_stats2_(const char* p_path, uint32_t s2flags, abort_callback& p_abort); | |
| 224 static t_filestats2 g_get_stats2(const char* p_path, uint32_t s2flags, abort_callback& p_abort); | |
| 225 | |
| 226 bool get_display_name_short_(const char* path, pfc::string_base& out); | |
| 227 | |
| 228 fsItemFolder::ptr makeItemFolderStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); | |
| 229 fsItemFile::ptr makeItemFileStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); | |
| 230 fsItemBase::ptr findItem_(const char* path, abort_callback& p_abort); | |
| 231 fsItemFile::ptr findItemFile_(const char* path, abort_callback& p_abort); | |
| 232 fsItemFolder::ptr findItemFolder_(const char* path, abort_callback& p_abort); | |
| 233 | |
| 234 | |
| 235 typedef std::function<void(const char*, t_filestats2 const&) > list_callback_t; | |
| 236 void list_directory_(const char* path, list_callback_t cb, unsigned listMode,abort_callback& a); | |
| 237 | |
| 238 //! Compares two paths determining if one is a subpath of another, | |
| 239 //! Returns false if the paths are unrelated. | |
| 240 //! Returns true if the paths are related, and then: result is set 0 if they are equal, 1 if p2 is a subpath of p1, -1 if p1 is a subpath of p2 | |
| 241 static bool g_compare_paths(const char* p1, const char* p2, int& result); | |
| 242 | |
| 243 //! Batch file stats read. Some filesystems provide an optimized implementation of this. | |
| 244 static void g_readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort); | |
| 245 | |
| 246 //! See filesystem_v3::fileNameSanity(). Throws pfc::exception_not_implemented() if not available. | |
| 247 fb2k::stringRef fileNameSanity_(const char* fn); | |
| 248 | |
| 249 //! See filesystem_v3::getDriveSpace(). Throws pfc::exception_not_implemented() if not available. | |
| 250 drivespace_t getDriveSpace_(const char* pathAt, abort_callback& abort); | |
| 251 | |
| 252 protected: | |
| 253 static bool get_parent_helper(const char * path, char separator, pfc::string_base & out); | |
| 254 void read_whole_file_fallback( const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort ); | |
| 255 }; | |
| 256 | |
| 257 class filesystem_v2 : public filesystem { | |
| 258 FB2K_MAKE_SERVICE_INTERFACE( filesystem_v2, filesystem ) | |
| 259 public: | |
| 260 //! Moves/renames a file, overwriting the destination atomically if exists. \n | |
| 261 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 262 virtual void move_overwrite(const char * src, const char * dst, abort_callback & abort) = 0; | |
| 263 //! Moves/renames a file, overwriting the destination atomically if exists. \n | |
| 264 //! Meant to retain destination attributes if feasible. Otherwise identical to move_overwrite(). \n | |
| 265 //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios. | |
| 266 virtual void replace_file(const char * src, const char * dst, abort_callback & abort); | |
| 267 //! Create a directory, without throwing an exception if it already exists. | |
| 268 //! @param didCreate bool flag indicating whether a new directory was created or not. \n | |
| 269 //! This should be a retval, but because it's messy to obtain this information with certain APIs, the caller can opt out of receiving this information,. | |
| 270 virtual void make_directory(const char * path, abort_callback & abort, bool * didCreate = nullptr) = 0; | |
| 271 virtual bool directory_exists(const char * path, abort_callback & abort) = 0; | |
| 272 virtual bool file_exists(const char * path, abort_callback & abort) = 0; | |
| 273 virtual char pathSeparator() = 0; | |
| 274 virtual void extract_filename_ext(const char * path, pfc::string_base & outFN); | |
| 275 virtual bool get_parent_path( const char * path, pfc::string_base & out); | |
| 276 virtual void list_directory_ex(const char * p_path, directory_callback & p_out, unsigned listMode, abort_callback & p_abort) = 0; | |
| 277 virtual void read_whole_file(const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort); | |
| 278 | |
| 279 //! Wrapper to list_directory_ex | |
| 280 void list_directory( const char * p_path, directory_callback & p_out, abort_callback & p_abort ); | |
| 281 | |
| 282 bool make_directory_check(const char * path, abort_callback & abort); | |
| 283 }; | |
| 284 | |
| 285 //! \since 2.0 | |
| 286 class filesystem_v3 : public filesystem_v2 { | |
| 287 FB2K_MAKE_SERVICE_INTERFACE(filesystem_v3, filesystem_v2); | |
| 288 public: | |
| 289 //! Retrieves free space on the volume at the specified path. | |
| 290 //! Optional functionality, throws pfc::exception_not_implemented if n/a. | |
| 291 virtual drivespace_t getDriveSpace(const char* pathAt, abort_callback& abort); | |
| 292 | |
| 293 //! Retrieves stats of a file at specified path. | |
| 294 virtual t_filestats2 get_stats2(const char* p_path, uint32_t s2flags, abort_callback& p_abort) = 0; | |
| 295 | |
| 296 virtual bool get_display_name_short(const char* in, pfc::string_base& out); | |
| 297 | |
| 298 virtual void list_directory_v3(const char* path, directory_callback_v3& callback, unsigned listMode, abort_callback& p_abort) = 0; | |
| 299 | |
| 300 virtual fsItemBase::ptr findItem(const char* path, abort_callback& p_abort); | |
| 301 virtual fsItemFile::ptr findItemFile(const char* path, abort_callback& p_abort); | |
| 302 virtual fsItemFolder::ptr findItemFolder(const char* path, abort_callback& p_abort); | |
| 303 virtual fsItemFolder::ptr findParentFolder(const char* path, abort_callback& p_abort); | |
| 304 virtual fb2k::stringRef fileNameSanity(const char* fn); | |
| 305 virtual void readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort); | |
| 306 | |
| 307 //! Optional method to return a native filesystem path to this item, null if N/A. | |
| 308 //! Aborter provided for corner cases, normally not needed. | |
| 309 virtual fb2k::stringRef getNativePath(const char* in, abort_callback& a) { (void)in; (void)a; return nullptr; } | |
| 310 | |
| 311 // Old method wrapped to get_stats2() | |
| 312 void get_stats(const char* p_path, t_filestats& p_stats, bool& p_is_writeable, abort_callback& p_abort) override; | |
| 313 // Old method wrapped to list_directory_v3() | |
| 314 void list_directory_ex(const char* p_path, directory_callback& p_out, unsigned listMode, abort_callback& p_abort) override; | |
| 315 | |
| 316 // Old method wrapped to get_stats2() | |
| 317 bool directory_exists(const char* path, abort_callback& abort) override; | |
| 318 // Old method wrapped to get_stats2() | |
| 319 bool file_exists(const char* path, abort_callback& abort) override; | |
| 320 }; | |
| 321 | |
| 322 class directory_callback_impl : public directory_callback | |
| 323 { | |
| 324 struct t_entry | |
| 325 { | |
| 326 pfc::string_simple m_path; | |
| 327 t_filestats m_stats; | |
| 328 t_entry(const char * p_path, const t_filestats & p_stats) : m_path(p_path), m_stats(p_stats) {} | |
| 329 }; | |
| 330 | |
| 331 | |
| 332 pfc::list_t<pfc::rcptr_t<t_entry> > m_data; | |
| 333 bool m_recur; | |
| 334 | |
| 335 static int sortfunc(const pfc::rcptr_t<const t_entry> & p1, const pfc::rcptr_t<const t_entry> & p2) {return pfc::io::path::compare(p1->m_path,p2->m_path);} | |
| 336 public: | |
| 337 bool on_entry(filesystem * owner,abort_callback & p_abort,const char * url,bool is_subdirectory,const t_filestats & p_stats); | |
| 338 | |
| 339 directory_callback_impl(bool p_recur) : m_recur(p_recur) {} | |
| 340 t_size get_count() {return m_data.get_count();} | |
| 341 const char * operator[](t_size n) const {return m_data[n]->m_path;} | |
| 342 const char * get_item(t_size n) const {return m_data[n]->m_path;} | |
| 343 const t_filestats & get_item_stats(t_size n) const {return m_data[n]->m_stats;} | |
| 344 void sort() {m_data.sort_t(sortfunc);} | |
| 345 }; | |
| 346 | |
| 347 | |
| 348 t_filetimestamp filetimestamp_from_system_timer(); | |
| 349 | |
| 350 #ifdef _WIN32 | |
| 351 inline t_filetimestamp import_filetimestamp(FILETIME ft) { | |
| 352 return *reinterpret_cast<t_filetimestamp*>(&ft); | |
| 353 } | |
| 354 #endif | |
| 355 | |
| 356 void generate_temp_location_for_file(pfc::string_base & p_out, const char * p_origpath,const char * p_extension,const char * p_magic); | |
| 357 | |
| 358 | |
| 359 inline file_ptr fileOpen(const char * p_path,filesystem::t_open_mode p_mode,abort_callback & p_abort,double p_timeout) { | |
| 360 file_ptr temp; filesystem::g_open_timeout(temp,p_path,p_mode,p_timeout,p_abort); PFC_ASSERT(temp.is_valid()); return temp; | |
| 361 } | |
| 362 | |
| 363 inline file_ptr fileOpenReadExisting(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { | |
| 364 return fileOpen(p_path,filesystem::open_mode_read,p_abort,p_timeout); | |
| 365 } | |
| 366 inline file_ptr fileOpenWriteExisting(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { | |
| 367 return fileOpen(p_path,filesystem::open_mode_write_existing,p_abort,p_timeout); | |
| 368 } | |
| 369 inline file_ptr fileOpenWriteNew(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { | |
| 370 return fileOpen(p_path,filesystem::open_mode_write_new,p_abort,p_timeout); | |
| 371 } | |
| 372 | |
| 373 template<typename t_list> | |
| 374 class directory_callback_retrieveList : public directory_callback { | |
| 375 public: | |
| 376 directory_callback_retrieveList(t_list & p_list,bool p_getFiles,bool p_getSubDirectories) : m_list(p_list), m_getFiles(p_getFiles), m_getSubDirectories(p_getSubDirectories) {} | |
| 377 bool on_entry(filesystem * p_owner,abort_callback & p_abort,const char * p_url,bool p_is_subdirectory,const t_filestats & p_stats) { | |
| 378 p_abort.check(); | |
| 379 if (p_is_subdirectory ? m_getSubDirectories : m_getFiles) { | |
| 380 m_list.add_item(p_url); | |
| 381 } | |
| 382 return true; | |
| 383 } | |
| 384 private: | |
| 385 const bool m_getSubDirectories; | |
| 386 const bool m_getFiles; | |
| 387 t_list & m_list; | |
| 388 }; | |
| 389 template<typename t_list> | |
| 390 class directory_callback_retrieveListEx : public directory_callback { | |
| 391 public: | |
| 392 directory_callback_retrieveListEx(t_list & p_files, t_list & p_directories) : m_files(p_files), m_directories(p_directories) {} | |
| 393 bool on_entry(filesystem * p_owner,abort_callback & p_abort,const char * p_url,bool p_is_subdirectory,const t_filestats & p_stats) { | |
| 394 p_abort.check(); | |
| 395 if (p_is_subdirectory) m_directories += p_url; | |
| 396 else m_files += p_url; | |
| 397 return true; | |
| 398 } | |
| 399 private: | |
| 400 t_list & m_files; | |
| 401 t_list & m_directories; | |
| 402 }; | |
| 403 template<typename t_list> class directory_callback_retrieveListRecur : public directory_callback { | |
| 404 public: | |
| 405 directory_callback_retrieveListRecur(t_list & p_list) : m_list(p_list) {} | |
| 406 bool on_entry(filesystem * owner,abort_callback & p_abort,const char * path, bool isSubdir, const t_filestats&) { | |
| 407 if (isSubdir) { | |
| 408 try { owner->list_directory(path,*this,p_abort); } catch(exception_io const &) {} | |
| 409 } else { | |
| 410 m_list.add_item(path); | |
| 411 } | |
| 412 return true; | |
| 413 } | |
| 414 private: | |
| 415 t_list & m_list; | |
| 416 }; | |
| 417 | |
| 418 template<typename t_list> | |
| 419 static void listFiles(const char * p_path,t_list & p_out,abort_callback & p_abort) { | |
| 420 directory_callback_retrieveList<t_list> callback(p_out,true,false); | |
| 421 filesystem::g_list_directory(p_path,callback,p_abort); | |
| 422 } | |
| 423 template<typename t_list> | |
| 424 static void listDirectories(const char * p_path,t_list & p_out,abort_callback & p_abort) { | |
| 425 directory_callback_retrieveList<t_list> callback(p_out,false,true); | |
| 426 filesystem::g_list_directory(p_path,callback,p_abort); | |
| 427 } | |
| 428 template<typename t_list> | |
| 429 static void listFilesAndDirectories(const char * p_path,t_list & p_files,t_list & p_directories,abort_callback & p_abort) { | |
| 430 directory_callback_retrieveListEx<t_list> callback(p_files,p_directories); | |
| 431 filesystem::g_list_directory(p_path,callback,p_abort); | |
| 432 } | |
| 433 template<typename t_list> | |
| 434 static void listFilesRecur(const char * p_path,t_list & p_out,abort_callback & p_abort) { | |
| 435 directory_callback_retrieveListRecur<t_list> callback(p_out); | |
| 436 filesystem::g_list_directory(p_path,callback,p_abort); | |
| 437 } | |
| 438 | |
| 439 bool extract_native_path(const char * p_fspath,pfc::string_base & p_native); | |
| 440 bool _extract_native_path_ptr(const char * & p_fspath); | |
| 441 bool is_native_filesystem( const char * p_fspath ); | |
| 442 bool extract_native_path_ex(const char * p_fspath, pfc::string_base & p_native);//prepends \\?\ where needed | |
| 443 | |
| 444 bool extract_native_path_archive_aware( const char * fspatch, pfc::string_base & out ); | |
| 445 bool extract_native_path_archive_aware_ex( const char * fspatch, pfc::string_base & out, abort_callback & a ); | |
| 446 | |
| 447 template<typename T> | |
| 448 pfc::string getPathDisplay(const T& source) { | |
| 449 const char * c = pfc::stringToPtr(source); | |
| 450 if ( *c == 0 ) return c; | |
| 451 pfc::string_formatter temp; | |
| 452 filesystem::g_get_display_path(c,temp); | |
| 453 return temp.toString(); | |
| 454 } | |
| 455 template<typename T> | |
| 456 pfc::string getPathCanonical(const T& source) { | |
| 457 const char * c = pfc::stringToPtr(source); | |
| 458 if ( *c == 0 ) return c; | |
| 459 pfc::string_formatter temp; | |
| 460 filesystem::g_get_canonical_path(c,temp); | |
| 461 return temp.toString(); | |
| 462 } | |
| 463 | |
| 464 | |
| 465 bool matchContentType(const char * fullString, const char * ourType); | |
| 466 bool matchProtocol(const char * fullString, const char * protocolName); | |
| 467 bool testIfHasProtocol( const char * fullString ); | |
| 468 const char * afterProtocol( const char * fullString ); | |
| 469 pfc::string8 getProtocol(const char* fullString); | |
| 470 void substituteProtocol(pfc::string_base & out, const char * fullString, const char * protocolName); | |
| 471 | |
| 472 bool matchContentType_MP3( const char * fullString); | |
| 473 bool matchContentType_MP4audio( const char * fullString); | |
| 474 bool matchContentType_MP4( const char * fullString); | |
| 475 bool matchContentType_Ogg( const char * fullString); | |
| 476 bool matchContentType_Opus( const char * fullString); | |
| 477 bool matchContentType_FLAC( const char * fullString); | |
| 478 bool matchContentType_WavPack( const char * fullString); | |
| 479 bool matchContentType_WAV( const char * fullString); | |
| 480 bool matchContentType_Musepack( const char * fullString); | |
| 481 const char * extensionFromContentType( const char * contentType ); | |
| 482 const char * contentTypeFromExtension( const char * ext ); | |
| 483 | |
| 484 void purgeOldFiles(const char * directory, t_filetimestamp period, abort_callback & abort); | |
| 485 | |
| 486 #ifndef _WIN32 | |
| 487 // Struct stat to fb2k filestats converter | |
| 488 t_filestats nixMakeFileStats(const struct stat & st); | |
| 489 t_filestats2 nixMakeFileStats2(const struct stat & st); | |
| 490 bool nixQueryReadonly( const struct stat & st ); | |
| 491 bool nixQueryDirectory( const struct stat & st ); | |
| 492 bool compactHomeDir(pfc::string_base & str); | |
| 493 bool expandHomeDir(pfc::string_base & str); | |
| 494 | |
| 495 | |
| 496 #endif | |
| 497 | |
| 498 //! \since 1.6 | |
| 499 class read_ahead_tools : public service_base { | |
| 500 FB2K_MAKE_SERVICE_COREAPI(read_ahead_tools); | |
| 501 public: | |
| 502 //! Turn any file object into asynchronous read-ahead-buffered file. | |
| 503 //! @param f File object to wrap. Do not call this object's method after a successful call to add_read_ahead; new file object takes over the ownership of it. | |
| 504 //! @param size Requested read-ahead bytes. Pass 0 to use user settings for local/remote playback. | |
| 505 virtual file::ptr add_read_ahead(file::ptr f, size_t size, abort_callback & aborter) = 0; | |
| 506 | |
| 507 //! A helper method to use prior to opening decoders. \n | |
| 508 //! May open the file if needed or leave it blank for the decoder to open. | |
| 509 //! @param f File object to open if needed (buffering mandated by user settings). May be valid or null prior to call. May be valid or null (no buffering) after call. | |
| 510 //! @param path Path to open. May be null if f is not null. At least one of f and path must be valid prior to call. | |
| 511 virtual void open_file_helper(file::ptr & f, const char * path, abort_callback & aborter) = 0; | |
| 512 }; | |
| 513 | |
| 514 } | |
| 515 | |
| 516 using namespace foobar2000_io; | |
| 517 | |
| 518 #include "filesystem_helper.h" |
