Mercurial > foo_out_sdl
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/SDK/filesystem.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,518 @@ +#pragma once + +#include "file.h" +#include "fsitem.h" +#include <functional> + +#ifndef _WIN32 +struct stat; +#endif + +//! Contains various I/O related structures and interfaces. +namespace foobar2000_io +{ + + //! Disk space info struct + struct drivespace_t { + //! Free space, in bytes + t_filesize m_free = filesize_invalid; + //! Total size, in bytes + t_filesize m_total = filesize_invalid; + //! Free space available to caller, in bytes \n + //! If not specifically supported by filesystem, same as m_free. + t_filesize m_avail = filesize_invalid; + }; + + + + class filesystem; + + class NOVTABLE directory_callback { + public: + //! @returns true to continue enumeration, false to abort. + 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; + }; + + class NOVTABLE directory_callback_v3 { + public: + virtual bool on_entry(filesystem* owner, const char* URL, t_filestats2 const& stats, abort_callback& abort) = 0; + }; + + //! Entrypoint service for all filesystem operations.\n + //! Implementation: standard implementations for local filesystem etc are provided by core.\n + //! Instantiation: use static helper functions rather than calling filesystem interface methods directly, e.g. filesystem::g_open() to open a file. + class NOVTABLE filesystem : public service_base { + FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(filesystem); + public: + //! Enumeration specifying how to open a file. See: filesystem::open(), filesystem::g_open(). + typedef uint32_t t_open_mode; + enum { + //! Opens an existing file for reading; if the file does not exist, the operation will fail. + open_mode_read, + //! Opens an existing file for writing; if the file does not exist, the operation will fail. + open_mode_write_existing, + //! Opens a new file for writing; if the file exists, its contents will be wiped. + open_mode_write_new, + + open_mode_mask = 0xFF, + open_shareable = 0x100, + }; + + virtual bool get_canonical_path(const char * p_path,pfc::string_base & p_out)=0; + virtual bool is_our_path(const char * p_path)=0; + virtual bool get_display_path(const char * p_path,pfc::string_base & p_out)=0; + + virtual void open(service_ptr_t<file> & p_out,const char * p_path, t_open_mode p_mode,abort_callback & p_abort)=0; + virtual void remove(const char * p_path,abort_callback & p_abort)=0; + //! Moves/renames a file. Will fail if the destination file already exists. \n + //! 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. + virtual void move(const char * p_src,const char * p_dst,abort_callback & p_abort)=0; + //! Queries whether a file at specified path belonging to this filesystem is a remote object or not. + virtual bool is_remote(const char * p_src) = 0; + + //! Retrieves stats of a file at specified path. + virtual void get_stats(const char * p_path,t_filestats & p_stats,bool & p_is_writeable,abort_callback & p_abort) = 0; + //! Helper + t_filestats get_stats( const char * path, abort_callback & abort ); + + 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; } + 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; } + + //! Creates a directory. + virtual void create_directory(const char * p_path,abort_callback & p_abort) = 0; + + virtual void list_directory(const char * p_path,directory_callback & p_out,abort_callback & p_abort)=0; + + //! Hint; returns whether this filesystem supports mime types. \n + //! 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. + virtual bool supports_content_types() = 0; + + static void g_get_canonical_path(const char * path,pfc::string_base & out); + static void g_get_display_path(const char * path,pfc::string_base & out); + static void g_get_display_path(const char* path, pfc::string_base& out, filesystem::ptr & reuseMe); + //! Retrieves a shortened display name for this file. By default this is implemented by returning filename.ext portion of the path. + static bool g_get_display_name_short( const char * path, pfc::string_base & out ); + //! Extracts the native filesystem path, sets out to the input path if native path cannot be extracted so the output is always set. + //! @returns True if native path was extracted successfully, false otherwise (but output is set anyway). + static bool g_get_native_path( const char * path, pfc::string_base & out, abort_callback & a = fb2k::noAbort); + static pfc::string8 g_get_native_path( const char * path, abort_callback & a = fb2k::noAbort ); + + static bool g_get_interface(service_ptr_t<filesystem> & p_out,const char * path);//path is AFTER get_canonical_path + static filesystem::ptr g_get_interface(const char * path);// throws exception_io_no_handler_for_path on failure + static filesystem::ptr get( const char * path ) { return g_get_interface(path); } // shortened; never returns null, throws on failure + static filesystem::ptr getLocalFS(); // returns local filesystem object + static filesystem::ptr tryGet(const char* path); // returns null if not found instead of throwing + static bool g_is_remote(const char * p_path);//path is AFTER get_canonical_path + static bool g_is_recognized_and_remote(const char * p_path);//path is AFTER get_canonical_path + static bool g_is_remote_safe(const char * p_path) {return g_is_recognized_and_remote(p_path);} + static bool g_is_remote_or_unrecognized(const char * p_path); + static bool g_is_recognized_path(const char * p_path); + + //! Opens file at specified path, with specified access privileges. + static void g_open(service_ptr_t<file> & p_out,const char * p_path,t_open_mode p_mode,abort_callback & p_abort); + //! 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. + 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); + static void g_open_write_new(service_ptr_t<file> & p_out,const char * p_path,abort_callback & p_abort); + 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);} + 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) + static bool g_exists(const char * p_path,abort_callback & p_abort); + static bool g_exists_writeable(const char * p_path,abort_callback & p_abort); + //! Removes file at specified path. + static void g_remove(const char * p_path,abort_callback & p_abort); + //! 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. + static void g_remove_timeout(const char * p_path,double p_timeout,abort_callback & p_abort); + //! Moves file from one path to another. + //! 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. + static void g_move(const char * p_src,const char * p_dst,abort_callback & p_abort); + //! 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. + static void g_move_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort); + + static void g_link(const char * p_src,const char * p_dst,abort_callback & p_abort); + static void g_link_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort); + + static void g_copy(const char * p_src,const char * p_dst,abort_callback & p_abort);//needs canonical path + static void g_copy_timeout(const char * p_src,const char * p_dst,double p_timeout,abort_callback & p_abort);//needs canonical path + static void g_copy_directory(const char * p_src,const char * p_dst,abort_callback & p_abort);//needs canonical path + static void g_get_stats(const char * p_path,t_filestats & p_stats,bool & p_is_writeable,abort_callback & p_abort); + static bool g_relative_path_create(const char * p_file_path,const char * p_playlist_path,pfc::string_base & out); + static bool g_relative_path_parse(const char * p_relative_path,const char * p_playlist_path,pfc::string_base & out); + + static void g_create_directory(const char * p_path,abort_callback & p_abort); + + static void g_open_temp(service_ptr_t<file> & p_out,abort_callback & p_abort); + static void g_open_tempmem(service_ptr_t<file> & p_out,abort_callback & p_abort); + static file::ptr g_open_tempmem(); + + static void g_list_directory(const char * p_path,directory_callback & p_out,abort_callback & p_abort);// path must be canonical + + static bool g_is_valid_directory(const char * path,abort_callback & p_abort); + static bool g_is_empty_directory(const char * path,abort_callback & p_abort); + + void remove_object_recur(const char * path, abort_callback & abort); + void remove_directory_content(const char * path, abort_callback & abort); + static void g_remove_object_recur(const char * path, abort_callback & abort); + static void g_remove_object_recur_timeout(const char * path, double timeout, abort_callback & abort); + + // Presumes both source and destination belong to this filesystem. + void copy_directory(const char * p_src, const char * p_dst, abort_callback & p_abort); + void copy_directory_contents(const char* p_src, const char* p_dst, abort_callback& p_abort); + + //! Moves/renames a file, overwriting the destination atomically if exists. \n + //! 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. + void move_overwrite( const char * src, const char * dst, abort_callback & abort); + //! Moves/renames a file, overwriting the destination atomically if exists. \n + //! Meant to retain destination attributes if feasible. Otherwise identical to move_overwrite(). \n + //! 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. + void replace_file(const char * src, const char * dst, abort_callback & abort); + //! Create a directory, without throwing an exception if it already exists. + //! @param didCreate bool flag indicating whether a new directory was created or not. \n + //! 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,. + void make_directory( const char * path, abort_callback & abort, bool * didCreate = nullptr ); + //! Bool retval version of make_directory(). + bool make_directory_check( const char * path, abort_callback & abort ); + + //! Returns whether a directory exists at path, false if doesn't exist or not a directory. + bool directory_exists(const char * path, abort_callback & abort); + //! Returns whether a file exists at path, false if doesn't exist or not a file. + bool file_exists( const char * path, abort_callback & abort ); + //! Returns whether either a file or a directory exists at path. Effectively directory_exists() || file_exists(), but somewhat more efficient. + bool exists(const char* path, abort_callback& a); + + char pathSeparator(); + //! Extracts the filename.ext portion of the path. \n + //! The filename is ready to be presented to the user - URL decoding and such (similar to get_display_path()) is applied. + void extract_filename_ext(const char * path, pfc::string_base & outFN); + pfc::string8 extract_filename_ext(const char* path); + pfc::string8 get_extension(const char* path); + static pfc::string8 g_get_extension(const char* path); + //! Retrieves the parent path. + bool get_parent_path(const char * path, pfc::string_base & out); + //! Retrieves the parent path, alternate version. + fb2k::stringRef parentPath(const char* path); + + file::ptr openWriteNew( const char * path, abort_callback & abort, double timeout ); + file::ptr openWriteExisting(const char * path, abort_callback & abort, double timeout); + file::ptr openRead( const char * path, abort_callback & abort, double timeout); + file::ptr openEx( const char * path, t_open_mode mode, abort_callback & abort, double timeout); + void remove_(const char* path, abort_callback& a, double timeout); + + //! Read whole file into a mem_block_container + void read_whole_file(const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort ); + //! Alternate read whole file, fb2k mobile style + fb2k::memBlockRef readWholeFile(const char* path, size_t maxBytes, abort_callback& abort); + static fb2k::memBlockRef g_readWholeFile(const char * path, size_t sizeSanity, abort_callback & aborter); + + bool is_transacted(); + bool commit_if_transacted(abort_callback &abort); + + //! Full file rewrite helper that automatically does the right thing to ensure atomic update. \n + //! If this is a transacted filesystem, a simple in-place rewrite is performed. \n + //! If this is not a transacted filesystem, your content first goes to a temporary file, which then replaces the original. \n + //! See also: filesystem_transacted. \n + //! 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). + void rewrite_file( const char * path, abort_callback & abort, double opTimeout, std::function<void (file::ptr) > worker ); + void rewrite_file(const char* path, abort_callback& abort, double opTimeout, const void* payload, size_t bytes); + //! Full directory rewrite helper that automatically does the right thing to ensure atomic update. \n + //! If this is a transacted filesystem, a simple in-place rewrite is performed. \n + //! If this is not a transacted filesystem, your content first goes to a temporary folder, which then replaces the original. \n + //! It is encouraged to perform flushFileBuffers on all files accessed from within. \n + //! See also: filesystem_transacted. \n + //! 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). + void rewrite_directory(const char * path, abort_callback & abort, double opTimeout, std::function<void(const char *) > worker); + + t_filestats2 get_stats2_(const char* p_path, uint32_t s2flags, abort_callback& p_abort); + static t_filestats2 g_get_stats2(const char* p_path, uint32_t s2flags, abort_callback& p_abort); + + bool get_display_name_short_(const char* path, pfc::string_base& out); + + fsItemFolder::ptr makeItemFolderStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); + fsItemFile::ptr makeItemFileStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); + fsItemBase::ptr findItem_(const char* path, abort_callback& p_abort); + fsItemFile::ptr findItemFile_(const char* path, abort_callback& p_abort); + fsItemFolder::ptr findItemFolder_(const char* path, abort_callback& p_abort); + + + typedef std::function<void(const char*, t_filestats2 const&) > list_callback_t; + void list_directory_(const char* path, list_callback_t cb, unsigned listMode,abort_callback& a); + + //! Compares two paths determining if one is a subpath of another, + //! Returns false if the paths are unrelated. + //! 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 + static bool g_compare_paths(const char* p1, const char* p2, int& result); + + //! Batch file stats read. Some filesystems provide an optimized implementation of this. + static void g_readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort); + + //! See filesystem_v3::fileNameSanity(). Throws pfc::exception_not_implemented() if not available. + fb2k::stringRef fileNameSanity_(const char* fn); + + //! See filesystem_v3::getDriveSpace(). Throws pfc::exception_not_implemented() if not available. + drivespace_t getDriveSpace_(const char* pathAt, abort_callback& abort); + + protected: + static bool get_parent_helper(const char * path, char separator, pfc::string_base & out); + void read_whole_file_fallback( const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort ); + }; + + class filesystem_v2 : public filesystem { + FB2K_MAKE_SERVICE_INTERFACE( filesystem_v2, filesystem ) + public: + //! Moves/renames a file, overwriting the destination atomically if exists. \n + //! 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. + virtual void move_overwrite(const char * src, const char * dst, abort_callback & abort) = 0; + //! Moves/renames a file, overwriting the destination atomically if exists. \n + //! Meant to retain destination attributes if feasible. Otherwise identical to move_overwrite(). \n + //! 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. + virtual void replace_file(const char * src, const char * dst, abort_callback & abort); + //! Create a directory, without throwing an exception if it already exists. + //! @param didCreate bool flag indicating whether a new directory was created or not. \n + //! 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,. + virtual void make_directory(const char * path, abort_callback & abort, bool * didCreate = nullptr) = 0; + virtual bool directory_exists(const char * path, abort_callback & abort) = 0; + virtual bool file_exists(const char * path, abort_callback & abort) = 0; + virtual char pathSeparator() = 0; + virtual void extract_filename_ext(const char * path, pfc::string_base & outFN); + virtual bool get_parent_path( const char * path, pfc::string_base & out); + virtual void list_directory_ex(const char * p_path, directory_callback & p_out, unsigned listMode, abort_callback & p_abort) = 0; + virtual void read_whole_file(const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort); + + //! Wrapper to list_directory_ex + void list_directory( const char * p_path, directory_callback & p_out, abort_callback & p_abort ); + + bool make_directory_check(const char * path, abort_callback & abort); + }; + + //! \since 2.0 + class filesystem_v3 : public filesystem_v2 { + FB2K_MAKE_SERVICE_INTERFACE(filesystem_v3, filesystem_v2); + public: + //! Retrieves free space on the volume at the specified path. + //! Optional functionality, throws pfc::exception_not_implemented if n/a. + virtual drivespace_t getDriveSpace(const char* pathAt, abort_callback& abort); + + //! Retrieves stats of a file at specified path. + virtual t_filestats2 get_stats2(const char* p_path, uint32_t s2flags, abort_callback& p_abort) = 0; + + virtual bool get_display_name_short(const char* in, pfc::string_base& out); + + virtual void list_directory_v3(const char* path, directory_callback_v3& callback, unsigned listMode, abort_callback& p_abort) = 0; + + virtual fsItemBase::ptr findItem(const char* path, abort_callback& p_abort); + virtual fsItemFile::ptr findItemFile(const char* path, abort_callback& p_abort); + virtual fsItemFolder::ptr findItemFolder(const char* path, abort_callback& p_abort); + virtual fsItemFolder::ptr findParentFolder(const char* path, abort_callback& p_abort); + virtual fb2k::stringRef fileNameSanity(const char* fn); + virtual void readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort); + + //! Optional method to return a native filesystem path to this item, null if N/A. + //! Aborter provided for corner cases, normally not needed. + virtual fb2k::stringRef getNativePath(const char* in, abort_callback& a) { (void)in; (void)a; return nullptr; } + + // Old method wrapped to get_stats2() + void get_stats(const char* p_path, t_filestats& p_stats, bool& p_is_writeable, abort_callback& p_abort) override; + // Old method wrapped to list_directory_v3() + void list_directory_ex(const char* p_path, directory_callback& p_out, unsigned listMode, abort_callback& p_abort) override; + + // Old method wrapped to get_stats2() + bool directory_exists(const char* path, abort_callback& abort) override; + // Old method wrapped to get_stats2() + bool file_exists(const char* path, abort_callback& abort) override; + }; + + class directory_callback_impl : public directory_callback + { + struct t_entry + { + pfc::string_simple m_path; + t_filestats m_stats; + t_entry(const char * p_path, const t_filestats & p_stats) : m_path(p_path), m_stats(p_stats) {} + }; + + + pfc::list_t<pfc::rcptr_t<t_entry> > m_data; + bool m_recur; + + 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);} + public: + bool on_entry(filesystem * owner,abort_callback & p_abort,const char * url,bool is_subdirectory,const t_filestats & p_stats); + + directory_callback_impl(bool p_recur) : m_recur(p_recur) {} + t_size get_count() {return m_data.get_count();} + const char * operator[](t_size n) const {return m_data[n]->m_path;} + const char * get_item(t_size n) const {return m_data[n]->m_path;} + const t_filestats & get_item_stats(t_size n) const {return m_data[n]->m_stats;} + void sort() {m_data.sort_t(sortfunc);} + }; + + + t_filetimestamp filetimestamp_from_system_timer(); + +#ifdef _WIN32 + inline t_filetimestamp import_filetimestamp(FILETIME ft) { + return *reinterpret_cast<t_filetimestamp*>(&ft); + } +#endif + + void generate_temp_location_for_file(pfc::string_base & p_out, const char * p_origpath,const char * p_extension,const char * p_magic); + + + inline file_ptr fileOpen(const char * p_path,filesystem::t_open_mode p_mode,abort_callback & p_abort,double p_timeout) { + file_ptr temp; filesystem::g_open_timeout(temp,p_path,p_mode,p_timeout,p_abort); PFC_ASSERT(temp.is_valid()); return temp; + } + + inline file_ptr fileOpenReadExisting(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { + return fileOpen(p_path,filesystem::open_mode_read,p_abort,p_timeout); + } + inline file_ptr fileOpenWriteExisting(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { + return fileOpen(p_path,filesystem::open_mode_write_existing,p_abort,p_timeout); + } + inline file_ptr fileOpenWriteNew(const char * p_path,abort_callback & p_abort,double p_timeout = 0) { + return fileOpen(p_path,filesystem::open_mode_write_new,p_abort,p_timeout); + } + + template<typename t_list> + class directory_callback_retrieveList : public directory_callback { + public: + 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) {} + bool on_entry(filesystem * p_owner,abort_callback & p_abort,const char * p_url,bool p_is_subdirectory,const t_filestats & p_stats) { + p_abort.check(); + if (p_is_subdirectory ? m_getSubDirectories : m_getFiles) { + m_list.add_item(p_url); + } + return true; + } + private: + const bool m_getSubDirectories; + const bool m_getFiles; + t_list & m_list; + }; + template<typename t_list> + class directory_callback_retrieveListEx : public directory_callback { + public: + directory_callback_retrieveListEx(t_list & p_files, t_list & p_directories) : m_files(p_files), m_directories(p_directories) {} + bool on_entry(filesystem * p_owner,abort_callback & p_abort,const char * p_url,bool p_is_subdirectory,const t_filestats & p_stats) { + p_abort.check(); + if (p_is_subdirectory) m_directories += p_url; + else m_files += p_url; + return true; + } + private: + t_list & m_files; + t_list & m_directories; + }; + template<typename t_list> class directory_callback_retrieveListRecur : public directory_callback { + public: + directory_callback_retrieveListRecur(t_list & p_list) : m_list(p_list) {} + bool on_entry(filesystem * owner,abort_callback & p_abort,const char * path, bool isSubdir, const t_filestats&) { + if (isSubdir) { + try { owner->list_directory(path,*this,p_abort); } catch(exception_io const &) {} + } else { + m_list.add_item(path); + } + return true; + } + private: + t_list & m_list; + }; + + template<typename t_list> + static void listFiles(const char * p_path,t_list & p_out,abort_callback & p_abort) { + directory_callback_retrieveList<t_list> callback(p_out,true,false); + filesystem::g_list_directory(p_path,callback,p_abort); + } + template<typename t_list> + static void listDirectories(const char * p_path,t_list & p_out,abort_callback & p_abort) { + directory_callback_retrieveList<t_list> callback(p_out,false,true); + filesystem::g_list_directory(p_path,callback,p_abort); + } + template<typename t_list> + static void listFilesAndDirectories(const char * p_path,t_list & p_files,t_list & p_directories,abort_callback & p_abort) { + directory_callback_retrieveListEx<t_list> callback(p_files,p_directories); + filesystem::g_list_directory(p_path,callback,p_abort); + } + template<typename t_list> + static void listFilesRecur(const char * p_path,t_list & p_out,abort_callback & p_abort) { + directory_callback_retrieveListRecur<t_list> callback(p_out); + filesystem::g_list_directory(p_path,callback,p_abort); + } + + bool extract_native_path(const char * p_fspath,pfc::string_base & p_native); + bool _extract_native_path_ptr(const char * & p_fspath); + bool is_native_filesystem( const char * p_fspath ); + bool extract_native_path_ex(const char * p_fspath, pfc::string_base & p_native);//prepends \\?\ where needed + + bool extract_native_path_archive_aware( const char * fspatch, pfc::string_base & out ); + bool extract_native_path_archive_aware_ex( const char * fspatch, pfc::string_base & out, abort_callback & a ); + + template<typename T> + pfc::string getPathDisplay(const T& source) { + const char * c = pfc::stringToPtr(source); + if ( *c == 0 ) return c; + pfc::string_formatter temp; + filesystem::g_get_display_path(c,temp); + return temp.toString(); + } + template<typename T> + pfc::string getPathCanonical(const T& source) { + const char * c = pfc::stringToPtr(source); + if ( *c == 0 ) return c; + pfc::string_formatter temp; + filesystem::g_get_canonical_path(c,temp); + return temp.toString(); + } + + + bool matchContentType(const char * fullString, const char * ourType); + bool matchProtocol(const char * fullString, const char * protocolName); + bool testIfHasProtocol( const char * fullString ); + const char * afterProtocol( const char * fullString ); + pfc::string8 getProtocol(const char* fullString); + void substituteProtocol(pfc::string_base & out, const char * fullString, const char * protocolName); + + bool matchContentType_MP3( const char * fullString); + bool matchContentType_MP4audio( const char * fullString); + bool matchContentType_MP4( const char * fullString); + bool matchContentType_Ogg( const char * fullString); + bool matchContentType_Opus( const char * fullString); + bool matchContentType_FLAC( const char * fullString); + bool matchContentType_WavPack( const char * fullString); + bool matchContentType_WAV( const char * fullString); + bool matchContentType_Musepack( const char * fullString); + const char * extensionFromContentType( const char * contentType ); + const char * contentTypeFromExtension( const char * ext ); + + void purgeOldFiles(const char * directory, t_filetimestamp period, abort_callback & abort); + +#ifndef _WIN32 + // Struct stat to fb2k filestats converter + t_filestats nixMakeFileStats(const struct stat & st); + t_filestats2 nixMakeFileStats2(const struct stat & st); + bool nixQueryReadonly( const struct stat & st ); + bool nixQueryDirectory( const struct stat & st ); + bool compactHomeDir(pfc::string_base & str); + bool expandHomeDir(pfc::string_base & str); + + +#endif + + //! \since 1.6 + class read_ahead_tools : public service_base { + FB2K_MAKE_SERVICE_COREAPI(read_ahead_tools); + public: + //! Turn any file object into asynchronous read-ahead-buffered file. + //! @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. + //! @param size Requested read-ahead bytes. Pass 0 to use user settings for local/remote playback. + virtual file::ptr add_read_ahead(file::ptr f, size_t size, abort_callback & aborter) = 0; + + //! A helper method to use prior to opening decoders. \n + //! May open the file if needed or leave it blank for the decoder to open. + //! @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. + //! @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. + virtual void open_file_helper(file::ptr & f, const char * path, abort_callback & aborter) = 0; + }; + +} + +using namespace foobar2000_io; + +#include "filesystem_helper.h"
