Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/file.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 "exception_io.h" | |
| 4 | |
| 5 class file_info; | |
| 6 class mem_block_container; | |
| 7 | |
| 8 //! Contains various I/O related structures and interfaces. | |
| 9 namespace foobar2000_io | |
| 10 { | |
| 11 //! Type used for file size related variables. | |
| 12 typedef t_uint64 t_filesize; | |
| 13 //! Type used for file size related variables when a signed value is needed. | |
| 14 typedef t_int64 t_sfilesize; | |
| 15 //! Type used for file timestamp related variables. 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601; 0 for invalid/unknown time. | |
| 16 typedef t_uint64 t_filetimestamp; | |
| 17 //! Invalid/unknown file timestamp constant. Also see: t_filetimestamp. | |
| 18 const t_filetimestamp filetimestamp_invalid = 0; | |
| 19 //! Invalid/unknown file size constant. Also see: t_filesize. | |
| 20 static constexpr t_filesize filesize_invalid = (t_filesize)(UINT64_MAX); | |
| 21 | |
| 22 static constexpr t_filetimestamp filetimestamp_1second_increment = 10000000; | |
| 23 | |
| 24 //! Stores file stats (size and timestamp). | |
| 25 struct t_filestats { | |
| 26 //! Size of the file. | |
| 27 t_filesize m_size = filesize_invalid; | |
| 28 //! Time of last file modification. | |
| 29 t_filetimestamp m_timestamp = filetimestamp_invalid; | |
| 30 | |
| 31 inline bool operator==(const t_filestats& param) const { return m_size == param.m_size && m_timestamp == param.m_timestamp; } | |
| 32 inline bool operator!=(const t_filestats& param) const { return m_size != param.m_size || m_timestamp != param.m_timestamp; } | |
| 33 | |
| 34 pfc::string8 describe() const; | |
| 35 pfc::string8 debug() const { return describe(); } | |
| 36 }; | |
| 37 | |
| 38 struct t_filestats2 { | |
| 39 //! Size of the file. | |
| 40 t_filesize m_size = filesize_invalid; | |
| 41 //! Time of last file modification. | |
| 42 t_filetimestamp m_timestamp = filetimestamp_invalid; | |
| 43 t_filetimestamp m_timestampCreate = filetimestamp_invalid; | |
| 44 uint32_t m_attribs = 0; | |
| 45 uint32_t m_attribsValid = 0; | |
| 46 | |
| 47 t_filestats const& as_legacy() const { return *reinterpret_cast<const t_filestats*>(this); } | |
| 48 t_filestats to_legacy() const { return { m_size, m_timestamp }; } | |
| 49 static t_filestats2 from_legacy(t_filestats const& in) { return { in.m_size, in.m_timestamp }; } | |
| 50 | |
| 51 enum { | |
| 52 attr_readonly = 1 << 0, | |
| 53 attr_folder = 1 << 1, | |
| 54 attr_hidden = 1 << 2, | |
| 55 attr_system = 1 << 3, | |
| 56 attr_remote = 1 << 4, | |
| 57 }; | |
| 58 bool is_set(uint32_t attr) const { | |
| 59 PFC_ASSERT(m_attribsValid & attr); | |
| 60 return (m_attribs & attr) != 0; | |
| 61 } | |
| 62 bool is_readonly() const { return is_set(attr_readonly); } | |
| 63 bool is_folder() const { return is_set(attr_folder); } | |
| 64 bool is_file() const { return !is_folder(); } | |
| 65 bool is_hidden() const { return is_set(attr_hidden); } | |
| 66 bool can_write() const { return !is_readonly(); } | |
| 67 bool is_system() const { return is_set(attr_system); } | |
| 68 bool is_remote() const { return is_set(attr_remote); } | |
| 69 | |
| 70 void set_attrib(uint32_t f, bool v) { | |
| 71 if (v) m_attribs |= f; | |
| 72 else m_attribs &= ~f; | |
| 73 m_attribsValid |= f; | |
| 74 } | |
| 75 void set_file(bool v = true) { set_folder(!v); } | |
| 76 void set_folder(bool v = true) { set_attrib(attr_folder, v); } | |
| 77 void set_readonly(bool v) { set_attrib(attr_readonly, v); } | |
| 78 void set_hidden(bool v) { set_attrib(attr_hidden, v); } | |
| 79 void set_system(bool v) { set_attrib(attr_system, v); } | |
| 80 void set_remote(bool v = true) { set_attrib(attr_remote, v); } | |
| 81 | |
| 82 static pfc::string8 format_attribs(uint32_t flags, const char* delim = ", "); | |
| 83 pfc::string8 format_attribs(const char* delim = ", ") const { return format_attribs(m_attribs, delim); } | |
| 84 | |
| 85 static bool equals(t_filestats2 const& v1, t_filestats2 const& v2) { | |
| 86 return v1.m_size == v2.m_size && v1.m_timestamp == v2.m_timestamp && v1.m_timestampCreate == v2.m_timestampCreate && v1.m_attribsValid == v2.m_attribsValid && v1.m_attribs == v2.m_attribs; | |
| 87 } | |
| 88 bool operator==(const t_filestats2& other) const { return equals(*this, other); } | |
| 89 bool operator!=(const t_filestats2& other) const { return !equals(*this, other); } | |
| 90 | |
| 91 pfc::string8 describe() const; | |
| 92 pfc::string8 debug() const { return describe(); } | |
| 93 | |
| 94 bool haveSize() const { return m_size != filesize_invalid; } | |
| 95 bool haveTimestamp() const { return m_timestamp != filetimestamp_invalid; } | |
| 96 bool haveTimestampCreate() const { return m_timestampCreate != filetimestamp_invalid; } | |
| 97 }; | |
| 98 static constexpr uint32_t | |
| 99 stats2_size = 1 << 0, | |
| 100 stats2_timestamp = 1 << 1, | |
| 101 stats2_timestampCreate = 1 << 2, | |
| 102 stats2_fileOrFolder = 1 << 3, | |
| 103 stats2_readOnly = 1 << 4, | |
| 104 stats2_canWrite = stats2_readOnly, | |
| 105 stats2_hidden = 1 << 5, | |
| 106 stats2_remote = 1 << 6, | |
| 107 stats2_flags = (stats2_fileOrFolder | stats2_readOnly | stats2_hidden | stats2_remote), | |
| 108 stats2_legacy = (stats2_size | stats2_timestamp), | |
| 109 stats2_all = 0xFFFFFFFF; | |
| 110 | |
| 111 //! Invalid/unknown file stats constant. See: t_filestats. | |
| 112 static constexpr t_filestats filestats_invalid = t_filestats(); | |
| 113 static constexpr t_filestats2 filestats2_invalid = t_filestats2(); | |
| 114 | |
| 115 //! Struct to be used with guid_getFileTimes / guid_setFileTimes. | |
| 116 struct filetimes_t { | |
| 117 t_filetimestamp creation = filetimestamp_invalid; | |
| 118 t_filetimestamp lastAccess = filetimestamp_invalid; | |
| 119 t_filetimestamp lastWrite = filetimestamp_invalid; | |
| 120 }; | |
| 121 | |
| 122 //! Generic interface to read data from a nonseekable stream. Also see: stream_writer, file. \n | |
| 123 //! Error handling: all methods may throw exception_io or one of derivatives on failure; exception_aborted when abort_callback is signaled. | |
| 124 class NOVTABLE stream_reader { | |
| 125 public: | |
| 126 //! Attempts to reads specified number of bytes from the stream. | |
| 127 //! @param p_buffer Receives data being read. Must have at least p_bytes bytes of space allocated. | |
| 128 //! @param p_bytes Number of bytes to read. | |
| 129 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 130 //! @returns Number of bytes actually read. May be less than requested when EOF was reached. | |
| 131 virtual t_size read(void* p_buffer, t_size p_bytes, abort_callback& p_abort) = 0; | |
| 132 //! Reads specified number of bytes from the stream. If requested amount of bytes can't be read (e.g. EOF), throws exception_io_data_truncation. | |
| 133 //! @param p_buffer Receives data being read. Must have at least p_bytes bytes of space allocated. | |
| 134 //! @param p_bytes Number of bytes to read. | |
| 135 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 136 virtual void read_object(void* p_buffer, t_size p_bytes, abort_callback& p_abort); | |
| 137 //! Attempts to skip specified number of bytes in the stream. | |
| 138 //! @param p_bytes Number of bytes to skip. | |
| 139 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 140 //! @returns Number of bytes actually skipped, May be less than requested when EOF was reached. | |
| 141 virtual t_filesize skip(t_filesize p_bytes, abort_callback& p_abort); | |
| 142 //! Skips specified number of bytes in the stream. If requested amount of bytes can't be skipped (e.g. EOF), throws exception_io_data_truncation. | |
| 143 //! @param p_bytes Number of bytes to skip. | |
| 144 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 145 virtual void skip_object(t_filesize p_bytes, abort_callback& p_abort); | |
| 146 | |
| 147 //! Helper template built around read_object. Reads single raw object from the stream. | |
| 148 //! @param p_object Receives object read from the stream on success. | |
| 149 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 150 template<typename T> inline void read_object_t(T& p_object, abort_callback& p_abort) { pfc::assert_raw_type<T>(); read_object(&p_object, sizeof(p_object), p_abort); } | |
| 151 template<typename T> inline T read_object_t(abort_callback& a) { T val; this->read_object_t(val, a); return val; } | |
| 152 //! Helper template built around read_object. Reads single raw object from the stream; corrects byte order assuming stream uses little endian order. | |
| 153 //! @param p_object Receives object read from the stream on success. | |
| 154 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 155 template<typename T> inline void read_lendian_t(T& p_object, abort_callback& p_abort) { read_object_t(p_object, p_abort); byte_order::order_le_to_native_t(p_object); } | |
| 156 template<typename T> inline T read_lendian_t(abort_callback& a) { T val; this->read_lendian_t(val, a); return val; } | |
| 157 //! Helper template built around read_object. Reads single raw object from the stream; corrects byte order assuming stream uses big endian order. | |
| 158 //! @param p_object Receives object read from the stream on success. | |
| 159 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 160 template<typename T> inline void read_bendian_t(T& p_object, abort_callback& p_abort) { read_object_t(p_object, p_abort); byte_order::order_be_to_native_t(p_object); } | |
| 161 template<typename T> inline T read_bendian_t(abort_callback& a) { T val; this->read_bendian_t(val, a); return val; } | |
| 162 | |
| 163 //! Helper function; reads a string (with a 32-bit header indicating length in bytes followed by UTF-8 encoded data without a null terminator). | |
| 164 void read_string(pfc::string_base& p_out, abort_callback& p_abort); | |
| 165 //! Helper function; alternate way of storing strings; assumes string takes space up to end of stream. | |
| 166 void read_string_raw(pfc::string_base& p_out, abort_callback& p_abort, size_t sanity = SIZE_MAX); | |
| 167 //! Helper function; reads a string (with a 32-bit header indicating length in bytes followed by UTF-8 encoded data without a null terminator). | |
| 168 pfc::string read_string(abort_callback& p_abort); | |
| 169 | |
| 170 //! Helper function; reads a string of specified length from the stream. | |
| 171 void read_string_ex(pfc::string_base& p_out, t_size p_bytes, abort_callback& p_abort); | |
| 172 //! Helper function; reads a string of specified length from the stream. | |
| 173 pfc::string read_string_ex(t_size p_len, abort_callback& p_abort); | |
| 174 | |
| 175 void read_string_nullterm(pfc::string_base& out, abort_callback& abort); | |
| 176 | |
| 177 t_filesize skip_till_eof(abort_callback& abort); | |
| 178 | |
| 179 template<typename t_outArray> | |
| 180 void read_till_eof(t_outArray& out, abort_callback& abort) { | |
| 181 pfc::assert_raw_type<typename t_outArray::t_item>(); | |
| 182 const t_size itemWidth = sizeof(typename t_outArray::t_item); | |
| 183 out.set_size(pfc::max_t<t_size>(1, 256 / itemWidth)); t_size done = 0; | |
| 184 for (;;) { | |
| 185 t_size delta = out.get_size() - done; | |
| 186 t_size delta2 = read(out.get_ptr() + done, delta * itemWidth, abort) / itemWidth; | |
| 187 done += delta2; | |
| 188 if (delta2 != delta) break; | |
| 189 out.set_size(out.get_size() << 1); | |
| 190 } | |
| 191 out.set_size(done); | |
| 192 } | |
| 193 | |
| 194 uint8_t read_byte(abort_callback& abort); | |
| 195 protected: | |
| 196 stream_reader() {} | |
| 197 ~stream_reader() {} | |
| 198 }; | |
| 199 | |
| 200 | |
| 201 //! Generic interface to write data to a nonseekable stream. Also see: stream_reader, file. \n | |
| 202 //! Error handling: all methods may throw exception_io or one of derivatives on failure; exception_aborted when abort_callback is signaled. | |
| 203 class NOVTABLE stream_writer { | |
| 204 public: | |
| 205 //! Writes specified number of bytes from specified buffer to the stream. | |
| 206 //! @param p_buffer Buffer with data to write. Must contain at least p_bytes bytes. | |
| 207 //! @param p_bytes Number of bytes to write. | |
| 208 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 209 virtual void write(const void* p_buffer, t_size p_bytes, abort_callback& p_abort) = 0; | |
| 210 | |
| 211 //! Helper. Same as write(), provided for consistency. | |
| 212 inline void write_object(const void* p_buffer, t_size p_bytes, abort_callback& p_abort) { write(p_buffer, p_bytes, p_abort); } | |
| 213 | |
| 214 //! Helper template. Writes single raw object to the stream. | |
| 215 //! @param p_object Object to write. | |
| 216 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 217 template<typename T> inline void write_object_t(const T& p_object, abort_callback& p_abort) { pfc::assert_raw_type<T>(); write_object(&p_object, sizeof(p_object), p_abort); } | |
| 218 //! Helper template. Writes single raw object to the stream; corrects byte order assuming stream uses little endian order. | |
| 219 //! @param p_object Object to write. | |
| 220 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 221 template<typename T> inline void write_lendian_t(const T& p_object, abort_callback& p_abort) { T temp = p_object; byte_order::order_native_to_le_t(temp); write_object_t(temp, p_abort); } | |
| 222 //! Helper template. Writes single raw object to the stream; corrects byte order assuming stream uses big endian order. | |
| 223 //! @param p_object Object to write. | |
| 224 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 225 template<typename T> inline void write_bendian_t(const T& p_object, abort_callback& p_abort) { T temp = p_object; byte_order::order_native_to_be_t(temp); write_object_t(temp, p_abort); } | |
| 226 | |
| 227 //! Helper function; writes string (with 32-bit header indicating length in bytes followed by UTF-8 encoded data without null terminator). | |
| 228 void write_string(const char* p_string, abort_callback& p_abort); | |
| 229 void write_string(const char* p_string, t_size p_len, abort_callback& p_abort); | |
| 230 | |
| 231 template<typename T> | |
| 232 void write_string(const T& val, abort_callback& p_abort) { write_string(pfc::stringToPtr(val), p_abort); } | |
| 233 | |
| 234 //! Helper function; writes raw string to the stream, with no length info or null terminators. | |
| 235 void write_string_raw(const char* p_string, abort_callback& p_abort); | |
| 236 | |
| 237 void write_string_nullterm(const char* p_string, abort_callback& p_abort) { this->write(p_string, strlen(p_string) + 1, p_abort); } | |
| 238 protected: | |
| 239 stream_writer() {} | |
| 240 ~stream_writer() {} | |
| 241 }; | |
| 242 | |
| 243 //! A class providing abstraction for an open file object, with reading/writing/seeking methods. See also: stream_reader, stream_writer (which it inherits read/write methods from). \n | |
| 244 //! Error handling: all methods may throw exception_io or one of derivatives on failure; exception_aborted when abort_callback is signaled. | |
| 245 class NOVTABLE file : public service_base, public stream_reader, public stream_writer { | |
| 246 public: | |
| 247 | |
| 248 //! Seeking mode constants. Note: these are purposedly defined to same values as standard C SEEK_* constants | |
| 249 enum t_seek_mode { | |
| 250 //! Seek relative to beginning of file (same as seeking to absolute offset). | |
| 251 seek_from_beginning = 0, | |
| 252 //! Seek relative to current position. | |
| 253 seek_from_current = 1, | |
| 254 //! Seek relative to end of file. | |
| 255 seek_from_eof = 2, | |
| 256 }; | |
| 257 | |
| 258 //! Retrieves size of the file. | |
| 259 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 260 //! @returns File size on success; filesize_invalid if unknown (nonseekable stream etc). | |
| 261 virtual t_filesize get_size(abort_callback& p_abort) = 0; | |
| 262 | |
| 263 | |
| 264 //! Retrieves read/write cursor position in the file. In case of non-seekable stream, this should return number of bytes read so far since open/reopen call. | |
| 265 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 266 //! @returns Read/write cursor position | |
| 267 virtual t_filesize get_position(abort_callback& p_abort) = 0; | |
| 268 | |
| 269 //! Resizes file to the specified size in bytes. | |
| 270 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 271 virtual void resize(t_filesize p_size, abort_callback& p_abort) = 0; | |
| 272 | |
| 273 //! Sets read/write cursor position to the specified offset. Throws exception_io_seek_out_of_range if the specified offset is outside the valid range. | |
| 274 //! @param p_position position to seek to. | |
| 275 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 276 virtual void seek(t_filesize p_position, abort_callback& p_abort) = 0; | |
| 277 | |
| 278 //! Same as seek() but throws exception_io_data instead of exception_io_seek_out_of_range. | |
| 279 void seek_probe(t_filesize p_position, abort_callback& p_abort); | |
| 280 | |
| 281 //! Sets read/write cursor position to the specified offset; extended form allowing seeking relative to current position or to end of file. | |
| 282 //! @param p_position Position to seek to; interpretation of this value depends on p_mode parameter. | |
| 283 //! @param p_mode Seeking mode; see t_seek_mode enum values for further description. | |
| 284 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 285 virtual void seek_ex(t_sfilesize p_position, t_seek_mode p_mode, abort_callback& p_abort); | |
| 286 | |
| 287 //! Returns whether the file is seekable or not. If can_seek() returns false, all seek() or seek_ex() calls will fail; reopen() is still usable on nonseekable streams. | |
| 288 virtual bool can_seek() = 0; | |
| 289 | |
| 290 //! Retrieves mime type of the file. | |
| 291 //! @param p_out Receives content type string on success. | |
| 292 virtual bool get_content_type(pfc::string_base& p_out) = 0; | |
| 293 pfc::string8 get_content_type(); | |
| 294 | |
| 295 //! Hint, returns whether the file is already fully buffered into memory. | |
| 296 virtual bool is_in_memory() { return false; } | |
| 297 | |
| 298 //! Optional, called by owner thread before sleeping. | |
| 299 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 300 virtual void on_idle(abort_callback& p_abort) { (void)p_abort; } | |
| 301 | |
| 302 //! Retrieves last modification time of the file. | |
| 303 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 304 //! @returns Last modification time o fthe file; filetimestamp_invalid if N/A. | |
| 305 virtual t_filetimestamp get_timestamp(abort_callback& p_abort) { (void)p_abort; return filetimestamp_invalid; } | |
| 306 | |
| 307 //! Resets non-seekable stream, or seeks to zero on seekable file. | |
| 308 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 309 virtual void reopen(abort_callback& p_abort) = 0; | |
| 310 | |
| 311 //! Indicates whether the file is a remote resource and non-sequential access may be slowed down by lag. This is typically returns to true on non-seekable sources but may also return true on seekable sources indicating that seeking is supported but will be relatively slow. | |
| 312 virtual bool is_remote() = 0; | |
| 313 | |
| 314 //! Retrieves file stats structure. Uses get_size() and get_timestamp(). | |
| 315 t_filestats get_stats(abort_callback& p_abort); | |
| 316 | |
| 317 //! Returns whether read/write cursor position is at the end of file. | |
| 318 bool is_eof(abort_callback& p_abort); | |
| 319 | |
| 320 //! Truncates file to specified size (while preserving read/write cursor position if possible); uses set_eof(). | |
| 321 void truncate(t_filesize p_position, abort_callback& p_abort); | |
| 322 | |
| 323 //! Truncates the file at current read/write cursor position. | |
| 324 void set_eof(abort_callback& p_abort) { resize(get_position(p_abort), p_abort); } | |
| 325 | |
| 326 | |
| 327 //! Helper; retrieves size of the file. If size is not available (get_size() returns filesize_invalid), throws exception_io_no_length. | |
| 328 t_filesize get_size_ex(abort_callback& p_abort); | |
| 329 | |
| 330 //! Helper; retrieves amount of bytes between read/write cursor position and end of file. Fails when length can't be determined. | |
| 331 t_filesize get_remaining(abort_callback& p_abort); | |
| 332 | |
| 333 //! Security helper; fails early with exception_io_data_truncation if it is not possible to read this amount of bytes from this file at this position. | |
| 334 void probe_remaining(t_filesize bytes, abort_callback& p_abort); | |
| 335 bool probe_remaining_ex(t_filesize bytes, abort_callback& p_abort); | |
| 336 | |
| 337 //! Helper; throws exception_io_object_not_seekable if file is not seekable. | |
| 338 void ensure_seekable(); | |
| 339 | |
| 340 //! Helper; throws exception_io_object_is_remote if the file is remote. | |
| 341 void ensure_local(); | |
| 342 | |
| 343 //! Helper; transfers specified number of bytes between streams. | |
| 344 //! @returns number of bytes actually transferred. May be less than requested if e.g. EOF is reached. | |
| 345 static t_filesize g_transfer(stream_reader* src, stream_writer* dst, t_filesize bytes, abort_callback& p_abort); | |
| 346 //! Helper; transfers specified number of bytes between streams. Throws exception if requested number of bytes could not be read (EOF). | |
| 347 static void g_transfer_object(stream_reader* src, stream_writer* dst, t_filesize bytes, abort_callback& p_abort); | |
| 348 //! Helper; transfers entire file content from one file to another, erasing previous content. | |
| 349 static void g_transfer_file(const service_ptr_t<file>& p_from, const service_ptr_t<file>& p_to, abort_callback& p_abort); | |
| 350 //! Helper; transfers file modification times from one file to another, if supported by underlying objects. Returns true on success, false if the operation doesn't appear to be supported. | |
| 351 static bool g_copy_timestamps(service_ptr_t<file> from, service_ptr_t<file> to, abort_callback& abort); | |
| 352 static bool g_copy_creation_time(service_ptr_t<file> from, service_ptr_t<file> to, abort_callback& abort); | |
| 353 | |
| 354 //! Helper; improved performance over g_transfer on streams (avoids disk fragmentation when transferring large blocks). | |
| 355 static t_filesize g_transfer(service_ptr_t<file> p_src, service_ptr_t<file> p_dst, t_filesize p_bytes, abort_callback& p_abort); | |
| 356 //! Helper; improved performance over g_transfer_file on streams (avoids disk fragmentation when transferring large blocks). | |
| 357 static void g_transfer_object(service_ptr_t<file> p_src, service_ptr_t<file> p_dst, t_filesize p_bytes, abort_callback& p_abort); | |
| 358 | |
| 359 | |
| 360 //! file_v2 wrapper; | |
| 361 size_t lowLevelIO_(const GUID& guid, size_t arg1, void* arg2, size_t arg2size, abort_callback& abort); | |
| 362 | |
| 363 //! Helper | |
| 364 bool flushFileBuffers(abort_callback&); | |
| 365 bool flushFileBuffers_(abort_callback& a) { return flushFileBuffers(a); } | |
| 366 //! Helper | |
| 367 bool getFileTimes(filetimes_t& out, abort_callback&); | |
| 368 //! Helper | |
| 369 bool setFileTimes(filetimes_t const& in, abort_callback&); | |
| 370 | |
| 371 t_filesize skip(t_filesize p_bytes, abort_callback& p_abort); | |
| 372 t_filesize skip_seek(t_filesize p_bytes, abort_callback& p_abort); | |
| 373 | |
| 374 //! file_v2 wrapper. | |
| 375 service_ptr get_metadata_(abort_callback& a); | |
| 376 | |
| 377 //! file_v2 wrapper. | |
| 378 t_filestats2 get_stats2_(uint32_t f, abort_callback& a); | |
| 379 | |
| 380 //! file_v2 wrapper. | |
| 381 void set_stats(t_filestats2 const&, abort_callback&); | |
| 382 | |
| 383 //! file_v2 wrapper. | |
| 384 t_filetimestamp get_time_created(abort_callback& a); | |
| 385 | |
| 386 //! Alternate version of read() intended for network resources.\n | |
| 387 //! See: stream_receive::receive(); \n | |
| 388 //! If not implemented by this object, uses plain read(). | |
| 389 size_t receive(void*, size_t, abort_callback&); | |
| 390 | |
| 391 void commit(abort_callback& a) {flushFileBuffers(a);} | |
| 392 | |
| 393 FB2K_MAKE_SERVICE_INTERFACE(file, service_base); | |
| 394 }; | |
| 395 | |
| 396 typedef service_ptr_t<file> file_ptr; | |
| 397 | |
| 398 //! Extension for shoutcast dynamic metadata handling. | |
| 399 class file_dynamicinfo : public file { | |
| 400 FB2K_MAKE_SERVICE_INTERFACE(file_dynamicinfo, file); | |
| 401 public: | |
| 402 //! Retrieves "static" info that doesn't change in the middle of stream, such as station names etc. Returns true on success; false when static info is not available. | |
| 403 virtual bool get_static_info(class file_info& p_out) = 0; | |
| 404 //! Returns whether dynamic info is available on this stream or not. | |
| 405 virtual bool is_dynamic_info_enabled() = 0; | |
| 406 //! Retrieves dynamic stream info (e.g. online stream track titles). Returns true on success, false when info has not changed since last call. | |
| 407 virtual bool get_dynamic_info(class file_info& p_out) = 0; | |
| 408 }; | |
| 409 | |
| 410 //! \since 1.4.1 | |
| 411 //! Extended version of file_dynamicinfo | |
| 412 class file_dynamicinfo_v2 : public file_dynamicinfo { | |
| 413 FB2K_MAKE_SERVICE_INTERFACE(file_dynamicinfo_v2, file_dynamicinfo); | |
| 414 public: | |
| 415 virtual bool get_dynamic_info_v2(class file_info& out, t_filesize& outOffset) = 0; | |
| 416 protected: | |
| 417 // Obsolete | |
| 418 bool get_dynamic_info(class file_info& p_out); | |
| 419 }; | |
| 420 | |
| 421 //! Extension for cached file access - allows callers to know that they're dealing with a cache layer, to prevent cache duplication. | |
| 422 class file_cached : public file { | |
| 423 FB2K_MAKE_SERVICE_INTERFACE(file_cached, file); | |
| 424 public: | |
| 425 virtual size_t get_cache_block_size() = 0; | |
| 426 virtual void suggest_grow_cache(size_t suggestSize) = 0; | |
| 427 | |
| 428 static file::ptr g_create(service_ptr_t<file> p_base, abort_callback& p_abort, t_size blockSize); | |
| 429 static void g_create(service_ptr_t<file>& p_out, service_ptr_t<file> p_base, abort_callback& p_abort, t_size blockSize); | |
| 430 | |
| 431 static void g_decodeInitCache(file::ptr& theFile, abort_callback& abort, size_t blockSize); | |
| 432 }; | |
| 433 | |
| 434 //! \since 1.5 | |
| 435 //! Additional service implemented by standard file object providing access to low level OS specific APIs. \n | |
| 436 //! Obsolete, lowLevelIO() is now a part of file_v2 API. | |
| 437 class file_lowLevelIO : public service_base { | |
| 438 FB2K_MAKE_SERVICE_INTERFACE(file_lowLevelIO, service_base); | |
| 439 public: | |
| 440 //! @returns 0 if the command was not recognized, a command-defined non zero value otherwise. | |
| 441 virtual size_t lowLevelIO(const GUID& guid, size_t arg1, void* arg2, size_t arg2size, abort_callback& abort) = 0; | |
| 442 | |
| 443 //! Win32 FlushFileBuffers() wrapper. \n | |
| 444 //! Throws exception_io_denied on a file opened for reading. \n | |
| 445 //! No arguments are defined. \n | |
| 446 //! Returns 1 if handled, 0 if unsupported. | |
| 447 static const GUID guid_flushFileBuffers; | |
| 448 //! Retrieves file creation / last access / last write times. \n | |
| 449 //! Parameters: arg2 points to a filetimes_t struct to receive the data; arg2size must be set to sizeof(filetimes_t). \n | |
| 450 //! If the filesystem does not support a specific portion of the information, relevant struct member will be set to filetimestamp_invalid. \n | |
| 451 //! Returns 1 if handled, 0 if unsupported. | |
| 452 static const GUID guid_getFileTimes; | |
| 453 //! Sets file creation / last access / last write times. \n | |
| 454 //! Parameters: arg2 points to a filetimes_t struct holding the new data; arg2size must be set to sizeof(filetimes_t). \n | |
| 455 //! Individual members of the filetimes_t struct can be set to filetimestamp_invalid, if not all of the values are to be altered on the file. \n | |
| 456 //! Returns 1 if handled, 0 if unsupported. | |
| 457 static const GUID guid_setFileTimes; | |
| 458 | |
| 459 typedef ::foobar2000_io::filetimes_t filetimes_t; | |
| 460 }; | |
| 461 | |
| 462 //! Implementation helper - contains dummy implementations of methods that modify the file | |
| 463 template<typename t_base> class file_readonly_t : public t_base { | |
| 464 public: | |
| 465 void resize(t_filesize p_size, abort_callback& p_abort) override { throw exception_io_denied(); } | |
| 466 void write(const void* p_buffer, t_size p_bytes, abort_callback& p_abort) override { throw exception_io_denied(); } | |
| 467 }; | |
| 468 typedef file_readonly_t<file> file_readonly; | |
| 469 | |
| 470 //! \since 2.0 | |
| 471 class file_v2 : public file { | |
| 472 FB2K_MAKE_SERVICE_INTERFACE(file_v2, file); | |
| 473 public: | |
| 474 //! Returns an object with protocol specific metadata of the file. \n | |
| 475 //! It is essential that this object is made available to the caller by any wrappers working on top if a file object. \n | |
| 476 //! The returned object can be of any implementation-defined class; for http it's file_metdata_http. \n | |
| 477 //! Null return is allowed if no metadata is available. | |
| 478 virtual service_ptr get_metadata(abort_callback&) { return nullptr; } | |
| 479 | |
| 480 virtual t_filestats2 get_stats2(uint32_t s2flags, abort_callback&) = 0; | |
| 481 | |
| 482 virtual size_t lowLevelIO(const GUID& guid, size_t arg1, void* arg2, size_t arg2size, abort_callback& abort) { (void)guid; (void)arg1; (void)arg2; (void)arg2size; (void)abort; return 0; } | |
| 483 | |
| 484 // Old methods wrapped to get_stats2() | |
| 485 t_filetimestamp get_timestamp(abort_callback& p_abort) override; | |
| 486 bool is_remote() override; | |
| 487 t_filesize get_size(abort_callback& p_abort) override; | |
| 488 }; | |
| 489 | |
| 490 //! \since 1.6.7 | |
| 491 class file_metadata_http : public service_base { | |
| 492 FB2K_MAKE_SERVICE_INTERFACE(file_metadata_http, service_base); | |
| 493 public: | |
| 494 virtual bool get_http_header(const char* name, pfc::string_base& out) = 0; | |
| 495 virtual void get_connected_path(pfc::string_base& out) = 0; | |
| 496 }; | |
| 497 | |
| 498 | |
| 499 //! \since 2.1 | |
| 500 //! Extension to file object, implemented by network readers. Adds receive() method. | |
| 501 class stream_receive : public service_base { | |
| 502 FB2K_MAKE_SERVICE_INTERFACE(stream_receive, service_base); | |
| 503 public: | |
| 504 //! Alternate version of read() intended for network resources.\n | |
| 505 //! Returns as soon as any data is available (usually less than requested), or EOF has been reached (0 returned). | |
| 506 virtual size_t receive(void*, size_t, abort_callback&) = 0; | |
| 507 | |
| 508 size_t read_using_receive(void*, size_t, abort_callback&); | |
| 509 }; | |
| 510 } |
