From: <man...@us...> - 2014-10-08 12:41:01
|
Revision: 4404 http://sourceforge.net/p/modplug/code/4404 Author: manxorist Date: 2014-10-08 12:40:51 +0000 (Wed, 08 Oct 2014) Log Message: ----------- [Ref] Move mpt_fopen from mptPathString.h into mptFstream.h where all disk based file io functionality is now located. [Ref] Do not include full iostream headers in mptIO.h. Instead, just use <iosfwd> and move the implementation for std::istream and std::ostream (and FILE* as well) into mptIO.cpp. [Ref] Move FILE* streambuf classes and FILE_ostream from mptIO.h into mptFstream.h. [Ref] Move the DataContainer implementations from FileReader.h into mptIO.h . Make the std::istream based implementation non-inline in order to make the inclusion of <iosfwd> sufficient in the headers. [Ref] All in all, this speeds up compilation of libopenmpt non-test builds by up to 10% (depending on the compiler and platform) and improves separation between file io from the rest of the code. Modified Paths: -------------- trunk/OpenMPT/build/android_ndk/Android.mk trunk/OpenMPT/build/autotools/Makefile.am trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj trunk/OpenMPT/common/Logging.cpp trunk/OpenMPT/common/mptFstream.h trunk/OpenMPT/common/mptIO.h trunk/OpenMPT/common/mptPathString.cpp trunk/OpenMPT/common/mptPathString.h trunk/OpenMPT/common/stdafx.h trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters trunk/OpenMPT/mptrack/mod2midi.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/Dlsbank.cpp trunk/OpenMPT/soundlib/FileReader.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Load_s3m.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/SampleFormats.cpp trunk/OpenMPT/soundlib/SampleIO.cpp trunk/OpenMPT/soundlib/WAVTools.cpp Modified: trunk/OpenMPT/build/android_ndk/Android.mk =================================================================== --- trunk/OpenMPT/build/android_ndk/Android.mk 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/build/android_ndk/Android.mk 2014-10-08 12:40:51 UTC (rev 4404) @@ -19,6 +19,7 @@ common/stdafx.cpp \ common/Logging.cpp \ common/misc_util.cpp \ + common/mptIO.cpp \ common/mptPathString.cpp \ common/mptString.cpp \ common/Profiler.cpp \ Modified: trunk/OpenMPT/build/autotools/Makefile.am =================================================================== --- trunk/OpenMPT/build/autotools/Makefile.am 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/build/autotools/Makefile.am 2014-10-08 12:40:51 UTC (rev 4404) @@ -86,6 +86,7 @@ libopenmpt_la_SOURCES += common/misc_util.h libopenmpt_la_SOURCES += common/mptAtomic.h libopenmpt_la_SOURCES += common/mptFstream.h +libopenmpt_la_SOURCES += common/mptIO.cpp libopenmpt_la_SOURCES += common/mptIO.h libopenmpt_la_SOURCES += common/mptPathString.cpp libopenmpt_la_SOURCES += common/mptPathString.h @@ -283,6 +284,7 @@ libopenmpttest_SOURCES += common/misc_util.h libopenmpttest_SOURCES += common/mptAtomic.h libopenmpttest_SOURCES += common/mptFstream.h +libopenmpttest_SOURCES += common/mptIO.cpp libopenmpttest_SOURCES += common/mptIO.h libopenmpttest_SOURCES += common/mptPathString.cpp libopenmpttest_SOURCES += common/mptPathString.h Modified: trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj =================================================================== --- trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -194,6 +194,10 @@ > </File> <File + RelativePath="..\..\..\common\mptIO.cpp" + > + </File> + <File RelativePath="..\..\..\common\mptPathString.cpp" > </File> Modified: trunk/OpenMPT/common/Logging.cpp =================================================================== --- trunk/OpenMPT/common/Logging.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/Logging.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -11,6 +11,7 @@ #include "stdafx.h" #include "Logging.h" +#include "mptFstream.h" #include <iostream> #include <cstring> Modified: trunk/OpenMPT/common/mptFstream.h =================================================================== --- trunk/OpenMPT/common/mptFstream.h 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/mptFstream.h 2014-10-08 12:40:51 UTC (rev 4404) @@ -10,14 +10,38 @@ #pragma once #include <fstream> +#include <ios> +#include <ostream> +#include <streambuf> #include "../common/mptString.h" #include "../common/mptPathString.h" +#if defined(MPT_WITH_PATHSTRING) +#include "../common/mptIO.h" +#endif + OPENMPT_NAMESPACE_BEGIN + #if defined(MPT_WITH_PATHSTRING) + +static inline FILE * mpt_fopen(const mpt::PathString &filename, const char *mode) +//------------------------------------------------------------------------------- +{ + #if MPT_OS_WINDOWS + #if defined(MPT_WITH_CHARSET_LOCALE) + return _wfopen(filename.AsNative().c_str(), mode ? mpt::ToWide(mpt::CharsetLocale, mode).c_str() : nullptr); + #else + return _wfopen(filename.AsNative().c_str(), mode ? mpt::ToWide(mpt::CharsetUTF8, mode).c_str() : nullptr); + #endif + #else // !MPT_OS_WINDOWS + return fopen(filename.AsNative().c_str(), mode); + #endif // MPT_OS_WINDOWS +} + + namespace mpt { @@ -195,8 +219,278 @@ #undef MPT_FSTREAM_OPEN + + +// class FILE_ostream, FILE_output_streambuf and FILE_output_buffered_streambuf +// provide a portable way of wrapping a std::ostream around an FILE* opened for output. +// They offer similar functionality to the badly documented +// MSVC std::fstream(FILE*) constructor or GCC libstdc++ __gnu_cxx::stdio_sync_filebuf class, +// and, for other compilers, provide a race-free alternative to +// closing the FILE* and opening it again as a std::ofstream. +// +// Only output functionality is implemented because we have no need for an input wrapper. +// +// During the whole lifetime of the iostream wrappers, the FILE* object is assumend to be +// either +// - NULL +// or +// - valid +// - opened for writing in non-append mode +// - opened in binary mode +// - seekable +// Some of these preconditions cannot be verified, +// and even the others do not get verified. +// Behaviour in case of any unmet preconditions is undefined. +// +// The buffered streambuf and the ostream use a buffer of 64KiB by default. +// +// For FILE_output_streambuf, coherency with the underlying FILE* is always guaranteed. +// For FILE_ostream and FILE_output_buffered_streambuf, coherence is only +// guaranteed when flush() or pubsync() get called. +// The constructors and destructors take care to not violate coherency. +// When mixing FILE* and iostream I/O during the lifetime of the iostream objects, +// the user is responsible for providing coherency via the appropriate +// flush and sync functions. +// Behaviour in case of incoherent access is undefined. + + +class FILE_output_streambuf : public std::streambuf +{ +public: + typedef std::streambuf::char_type char_type; + typedef std::streambuf::traits_type traits_type; + typedef traits_type::int_type int_type; + typedef traits_type::pos_type pos_type; + typedef traits_type::off_type off_type; +protected: + FILE *f; +public: + FILE_output_streambuf(FILE *f) + : f(f) + { + return; + } + ~FILE_output_streambuf() + { + return; + } +protected: + virtual int_type overflow(int_type ch) + { + if(!mpt::IO::IsValid(f)) + { + return traits_type::eof(); + } + if(traits_type::eq_int_type(ch, traits_type::eof())) + { + return traits_type::eof(); + } + char_type c = traits_type::to_char_type(ch); + if(!mpt::IO::WriteRaw(f, &c, 1)) + { + return traits_type::eof(); + } + return ch; + } + virtual int sync() + { + if(!mpt::IO::IsValid(f)) + { + return -1; + } + if(!mpt::IO::Flush(f)) + { + return -1; + } + return 0; + } + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) + { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } + return seekoff(pos, std::ios_base::beg, which); + } + virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } + if(which & std::ios_base::in) + { + return pos_type(off_type(-1)); + } + if(!(which & std::ios_base::out)) + { + return pos_type(off_type(-1)); + } + mpt::IO::Offset oldpos = mpt::IO::TellWrite(f); + if(dir == std::ios_base::beg) + { + if(!mpt::IO::SeekAbsolute(f, off)) + { + mpt::IO::SeekAbsolute(f, oldpos); + return pos_type(off_type(-1)); + } + } else if(dir == std::ios_base::cur) + { + if(!mpt::IO::SeekRelative(f, off)) + { + mpt::IO::SeekAbsolute(f, oldpos); + return pos_type(off_type(-1)); + } + } else if(dir == std::ios_base::end) + { + if(!(mpt::IO::SeekEnd(f) && mpt::IO::SeekRelative(f, off))) + { + mpt::IO::SeekAbsolute(f, oldpos); + return pos_type(off_type(-1)); + } + } else + { + return pos_type(off_type(-1)); + } + mpt::IO::Offset newpos = mpt::IO::TellWrite(f); + if(!mpt::IO::OffsetFits<off_type>(newpos)) + { + mpt::IO::SeekAbsolute(f, oldpos); + return pos_type(off_type(-1)); + } + return static_cast<pos_type>(newpos); + } +}; // class FILE_output_streambuf + + +class FILE_output_buffered_streambuf : public FILE_output_streambuf +{ +public: + typedef std::streambuf::char_type char_type; + typedef std::streambuf::traits_type traits_type; + typedef traits_type::int_type int_type; + typedef traits_type::pos_type pos_type; + typedef traits_type::off_type off_type; +private: + typedef FILE_output_streambuf Tparent; + std::vector<char_type> buf; +public: + FILE_output_buffered_streambuf(FILE *f, std::size_t bufSize = 64*1024) + : FILE_output_streambuf(f) + , buf((bufSize > 0) ? bufSize : 1) + { + setp(&buf[0], &buf[0] + buf.size()); + } + ~FILE_output_buffered_streambuf() + { + if(!mpt::IO::IsValid(f)) + { + return; + } + WriteOut(); + } +private: + bool IsDirty() const + { + return ((pptr() - pbase()) > 0); + } + bool WriteOut() + { + std::ptrdiff_t n = pptr() - pbase(); + std::ptrdiff_t left = n; + while(left > 0) + { + int backchunk = mpt::saturate_cast<int>(-left); + pbump(backchunk); + left += backchunk; + } + return mpt::IO::WriteRaw(f, pbase(), n); + } +protected: + virtual int_type overflow(int_type ch) + { + if(!mpt::IO::IsValid(f)) + { + return traits_type::eof(); + } + if(traits_type::eq_int_type(ch, traits_type::eof())) + { + return traits_type::eof(); + } + if(!WriteOut()) + { + return traits_type::eof(); + } + char_type c = traits_type::to_char_type(ch); + *pptr() = c; + pbump(1); + return ch; + } + virtual int sync() + { + if(!mpt::IO::IsValid(f)) + { + return -1; + } + if(!WriteOut()) + { + return -1; + } + return Tparent::sync(); + } + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) + { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } + if(!WriteOut()) + { + return pos_type(off_type(-1)); + } + return Tparent::seekpos(pos, which); + } + virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } + if(!WriteOut()) + { + return pos_type(off_type(-1)); + } + return Tparent::seekoff(off, dir, which); + } +}; // class FILE_output_buffered_streambuf + + +class FILE_ostream : public std::ostream { +private: + FILE *f; + FILE_output_buffered_streambuf buf; +public: + FILE_ostream(FILE *f, std::size_t bufSize = 64*1024) + : std::ostream(&buf) + , f(f) + , buf(f, bufSize) + { + if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); + } + ~FILE_ostream() + { + flush(); + buf.pubsync(); + if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); + } +}; // class FILE_ostream + + } // namespace mpt + #endif // MPT_WITH_PATHSTRING + OPENMPT_NAMESPACE_END + Modified: trunk/OpenMPT/common/mptIO.h =================================================================== --- trunk/OpenMPT/common/mptIO.h 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/mptIO.h 2014-10-08 12:40:51 UTC (rev 4404) @@ -5,6 +5,7 @@ * Notes : This is work-in-progress. * Some useful functions for reading and writing are still missing. * Authors: Joern Heusipp + * OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ @@ -15,16 +16,17 @@ #include "../common/typedefs.h" #include "../common/Endianness.h" #include <algorithm> -#include <ios> -#include <istream> +#include <iosfwd> #include <limits> -#include <ostream> #if defined(HAS_TYPE_TRAITS) #include <type_traits> #endif +#include <cstring> + +#if defined(MPT_WITH_PATHSTRING) #include <cstdio> -#include <cstring> #include <stdio.h> +#endif OPENMPT_NAMESPACE_BEGIN @@ -47,79 +49,58 @@ -//STATIC_ASSERT(sizeof(std::streamoff) == 8); // Assert 64bit file support. -inline bool IsValid(std::ostream & f) { return !f.fail(); } -inline bool IsValid(std::istream & f) { return !f.fail(); } -inline bool IsValid(std::iostream & f) { return !f.fail(); } -inline IO::Offset TellRead(std::istream & f) { return f.tellg(); } -inline IO::Offset TellWrite(std::ostream & f) { return f.tellp(); } -inline bool SeekBegin(std::ostream & f) { f.seekp(0); return !f.fail(); } -inline bool SeekBegin(std::istream & f) { f.seekg(0); return !f.fail(); } -inline bool SeekBegin(std::iostream & f) { f.seekg(0); f.seekp(0); return !f.fail(); } -inline bool SeekEnd(std::ostream & f) { f.seekp(0, std::ios::end); return !f.fail(); } -inline bool SeekEnd(std::istream & f) { f.seekg(0, std::ios::end); return !f.fail(); } -inline bool SeekEnd(std::iostream & f) { f.seekg(0, std::ios::end); f.seekp(0, std::ios::end); return !f.fail(); } -inline bool SeekAbsolute(std::ostream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail(); } -inline bool SeekAbsolute(std::istream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail(); } -inline bool SeekAbsolute(std::iostream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail(); } -inline bool SeekRelative(std::ostream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail(); } -inline bool SeekRelative(std::istream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekg(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail(); } -inline bool SeekRelative(std::iostream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekg(static_cast<std::streamoff>(off), std::ios::cur); f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail(); } -inline IO::Offset ReadRaw(std::istream & f, uint8 * data, std::size_t size) { return f.read(reinterpret_cast<char *>(data), size) ? f.gcount() : std::streamsize(0); } -inline IO::Offset ReadRaw(std::istream & f, char * data, std::size_t size) { return f.read(data, size) ? f.gcount() : std::streamsize(0); } -inline IO::Offset ReadRaw(std::istream & f, void * data, std::size_t size) { return f.read(reinterpret_cast<char *>(data), size) ? f.gcount() : std::streamsize(0); } -inline bool WriteRaw(std::ostream & f, const uint8 * data, std::size_t size) { f.write(reinterpret_cast<const char *>(data), size); return !f.fail(); } -inline bool WriteRaw(std::ostream & f, const char * data, std::size_t size) { f.write(data, size); return !f.fail(); } -inline bool WriteRaw(std::ostream & f, const void * data, std::size_t size) { f.write(reinterpret_cast<const char *>(data), size); return !f.fail(); } -inline bool IsEof(std::istream & f) { return f.eof(); } -inline bool Flush(std::ostream & f) { f.flush(); return !f.fail(); } +bool IsValid(std::ostream & f); +bool IsValid(std::istream & f); +bool IsValid(std::iostream & f); +IO::Offset TellRead(std::istream & f); +IO::Offset TellWrite(std::ostream & f); +bool SeekBegin(std::ostream & f); +bool SeekBegin(std::istream & f); +bool SeekBegin(std::iostream & f); +bool SeekEnd(std::ostream & f); +bool SeekEnd(std::istream & f); +bool SeekEnd(std::iostream & f); +bool SeekAbsolute(std::ostream & f, IO::Offset pos); +bool SeekAbsolute(std::istream & f, IO::Offset pos); +bool SeekAbsolute(std::iostream & f, IO::Offset pos); +bool SeekRelative(std::ostream & f, IO::Offset off); +bool SeekRelative(std::istream & f, IO::Offset off); +bool SeekRelative(std::iostream & f, IO::Offset off); +IO::Offset ReadRaw(std::istream & f, uint8 * data, std::size_t size); +IO::Offset ReadRaw(std::istream & f, char * data, std::size_t size); +IO::Offset ReadRaw(std::istream & f, void * data, std::size_t size); +bool WriteRaw(std::ostream & f, const uint8 * data, std::size_t size); +bool WriteRaw(std::ostream & f, const char * data, std::size_t size); +bool WriteRaw(std::ostream & f, const void * data, std::size_t size); +bool IsEof(std::istream & f); +bool Flush(std::ostream & f); -inline bool IsValid(FILE* & f) { return f != NULL; } +#if defined(MPT_WITH_PATHSTRING) -#if MPT_COMPILER_MSVC +// FILE* only makes sense if we support filenames at all. -inline IO::Offset TellRead(FILE* & f) { return _ftelli64(f); } -inline IO::Offset TellWrite(FILE* & f) { return _ftelli64(f); } -inline bool SeekBegin(FILE* & f) { return _fseeki64(f, 0, SEEK_SET) == 0; } -inline bool SeekEnd(FILE* & f) { return _fseeki64(f, 0, SEEK_END) == 0; } -inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return _fseeki64(f, pos, SEEK_SET) == 0; } -inline bool SeekRelative(FILE* & f, IO::Offset off) { return _fseeki64(f, off, SEEK_CUR) == 0; } +bool IsValid(FILE* & f); +IO::Offset TellRead(FILE* & f); +IO::Offset TellWrite(FILE* & f); +bool SeekBegin(FILE* & f); +bool SeekEnd(FILE* & f); +bool SeekAbsolute(FILE* & f, IO::Offset pos); +bool SeekRelative(FILE* & f, IO::Offset off); +IO::Offset ReadRaw(FILE * & f, uint8 * data, std::size_t size); +IO::Offset ReadRaw(FILE * & f, char * data, std::size_t size); +IO::Offset ReadRaw(FILE * & f, void * data, std::size_t size); +bool WriteRaw(FILE* & f, const uint8 * data, std::size_t size); +bool WriteRaw(FILE* & f, const char * data, std::size_t size); +bool WriteRaw(FILE* & f, const void * data, std::size_t size); +bool IsEof(FILE * & f); +bool Flush(FILE* & f); -#elif defined(_POSIX_SOURCE) && (_POSIX_SOURCE > 0) +#endif // MPT_WITH_PATHSTRING -//STATIC_ASSERT(sizeof(off_t) == 8); -inline IO::Offset TellRead(FILE* & f) { return ftello(f); } -inline IO::Offset TellWrite(FILE* & f) { return ftello(f); } -inline bool SeekBegin(FILE* & f) { return fseeko(f, 0, SEEK_SET) == 0; } -inline bool SeekEnd(FILE* & f) { return fseeko(f, 0, SEEK_END) == 0; } -inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return OffsetFits<off_t>(pos) && (fseek(f, mpt::saturate_cast<off_t>(pos), SEEK_SET) == 0); } -inline bool SeekRelative(FILE* & f, IO::Offset off) { return OffsetFits<off_t>(off) && (fseek(f, mpt::saturate_cast<off_t>(off), SEEK_CUR) == 0); } -#else -//STATIC_ASSERT(sizeof(long) == 8); // Fails on 32bit non-POSIX systems for now. -inline IO::Offset TellRead(FILE* & f) { return ftell(f); } -inline IO::Offset TellWrite(FILE* & f) { return ftell(f); } -inline bool SeekBegin(FILE* & f) { return fseek(f, 0, SEEK_SET) == 0; } -inline bool SeekEnd(FILE* & f) { return fseek(f, 0, SEEK_END) == 0; } -inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return OffsetFits<long>(pos) && (fseek(f, mpt::saturate_cast<long>(pos), SEEK_SET) == 0); } -inline bool SeekRelative(FILE* & f, IO::Offset off) { return OffsetFits<long>(off) && (fseek(f, mpt::saturate_cast<long>(off), SEEK_CUR) == 0); } - -#endif - -inline IO::Offset ReadRaw(FILE * & f, uint8 * data, std::size_t size) { return fread(data, 1, size, f); } -inline IO::Offset ReadRaw(FILE * & f, char * data, std::size_t size) { return fread(data, 1, size, f); } -inline IO::Offset ReadRaw(FILE * & f, void * data, std::size_t size) { return fread(data, 1, size, f); } -inline bool WriteRaw(FILE* & f, const uint8 * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } -inline bool WriteRaw(FILE* & f, const char * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } -inline bool WriteRaw(FILE* & f, const void * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } -inline bool IsEof(FILE * & f) { return feof(f) != 0; } -inline bool Flush(FILE* & f) { return fflush(f) == 0; } - - - template <typename Tbinary, typename Tfile> inline bool Read(Tfile & f, Tbinary & v) { @@ -364,272 +345,243 @@ } // namespace IO -// class FILE_ostream, FILE_output_streambuf and FILE_output_buffered_streambuf -// provide a portable way of wrapping a std::ostream around an FILE* opened for output. -// They offer similar functionality to the badly documented -// MSVC std::fstream(FILE*) constructor or GCC libstdc++ __gnu_cxx::stdio_sync_filebuf class, -// and, for other compilers, provide a race-free alternative to -// closing the FILE* and opening it again as a std::ofstream. -// -// Only output functionality is implemented because we have no need for an input wrapper. -// -// During the whole lifetime of the iostream wrappers, the FILE* object is assumend to be -// either -// - NULL -// or -// - valid -// - opened for writing in non-append mode -// - opened in binary mode -// - seekable -// Some of these preconditions cannot be verified, -// and even the others do not get verified. -// Behaviour in case of any unmet preconditions is undefined. -// -// The buffered streambuf and the ostream use a buffer of 64KiB by default. -// -// For FILE_output_streambuf, coherency with the underlying FILE* is always guaranteed. -// For FILE_ostream and FILE_output_buffered_streambuf, coherence is only -// guaranteed when flush() or pubsync() get called. -// The constructors and destructors take care to not violate coherency. -// When mixing FILE* and iostream I/O during the lifetime of the iostream objects, -// the user is responsible for providing coherency via the appropriate -// flush and sync functions. -// Behaviour in case of incoherent access is undefined. +} // namespace mpt -class FILE_output_streambuf : public std::streambuf -{ + +#if defined(MPT_FILEREADER_STD_ISTREAM) + +class IFileDataContainer { public: - typedef std::streambuf::char_type char_type; - typedef std::streambuf::traits_type traits_type; - typedef traits_type::int_type int_type; - typedef traits_type::pos_type pos_type; - typedef traits_type::off_type off_type; + typedef std::size_t off_t; protected: - FILE *f; + IFileDataContainer() { } public: - FILE_output_streambuf(FILE *f) - : f(f) + virtual ~IFileDataContainer() { } +public: + virtual bool IsValid() const = 0; + virtual const char *GetRawData() const = 0; + virtual off_t GetLength() const = 0; + virtual off_t Read(char *dst, off_t pos, off_t count) const = 0; + + virtual const char *GetPartialRawData(off_t pos, off_t length) const // DO NOT USE!!! this is just for ReadMagic ... the pointer returned may be invalid after the next Read() { - return; + if(pos + length > GetLength()) + { + return nullptr; + } + return GetRawData() + pos; } - ~FILE_output_streambuf() + + virtual bool CanRead(off_t pos, off_t length) const { - return; + return pos + length <= GetLength(); } -protected: - virtual int_type overflow(int_type ch) + + virtual off_t GetReadableLength(off_t pos, off_t length) const { - if(!mpt::IO::IsValid(f)) + if(pos >= GetLength()) { - return traits_type::eof(); + return 0; } - if(traits_type::eq_int_type(ch, traits_type::eof())) - { - return traits_type::eof(); - } - char_type c = traits_type::to_char_type(ch); - if(!mpt::IO::WriteRaw(f, &c, 1)) - { - return traits_type::eof(); - } - return ch; + return std::min<off_t>(length, GetLength() - pos); } - virtual int sync() +}; + + +class FileDataContainerDummy : public IFileDataContainer { +public: + FileDataContainerDummy() { } + virtual ~FileDataContainerDummy() { } +public: + bool IsValid() const { - if(!mpt::IO::IsValid(f)) - { - return -1; - } - if(!mpt::IO::Flush(f)) - { - return -1; - } - return 0; + return false; } - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) + + const char *GetRawData() const { - if(!mpt::IO::IsValid(f)) - { - return pos_type(off_type(-1)); - } - return seekoff(pos, std::ios_base::beg, which); + return nullptr; } - virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + + off_t GetLength() const { - if(!mpt::IO::IsValid(f)) - { - return pos_type(off_type(-1)); - } - if(which & std::ios_base::in) - { - return pos_type(off_type(-1)); - } - if(!(which & std::ios_base::out)) - { - return pos_type(off_type(-1)); - } - mpt::IO::Offset oldpos = mpt::IO::TellWrite(f); - if(dir == std::ios_base::beg) - { - if(!mpt::IO::SeekAbsolute(f, off)) - { - mpt::IO::SeekAbsolute(f, oldpos); - return pos_type(off_type(-1)); - } - } else if(dir == std::ios_base::cur) - { - if(!mpt::IO::SeekRelative(f, off)) - { - mpt::IO::SeekAbsolute(f, oldpos); - return pos_type(off_type(-1)); - } - } else if(dir == std::ios_base::end) - { - if(!(mpt::IO::SeekEnd(f) && mpt::IO::SeekRelative(f, off))) - { - mpt::IO::SeekAbsolute(f, oldpos); - return pos_type(off_type(-1)); - } - } else - { - return pos_type(off_type(-1)); - } - mpt::IO::Offset newpos = mpt::IO::TellWrite(f); - if(!mpt::IO::OffsetFits<off_type>(newpos)) - { - mpt::IO::SeekAbsolute(f, oldpos); - return pos_type(off_type(-1)); - } - return static_cast<pos_type>(newpos); + return 0; } -}; // class FILE_output_streambuf + off_t Read(char * /*dst*/, off_t /*pos*/, off_t /*count*/) const + { + return 0; + } +}; -class FILE_output_buffered_streambuf : public FILE_output_streambuf +class FileDataContainerWindow : public IFileDataContainer { -public: - typedef std::streambuf::char_type char_type; - typedef std::streambuf::traits_type traits_type; - typedef traits_type::int_type int_type; - typedef traits_type::pos_type pos_type; - typedef traits_type::off_type off_type; private: - typedef FILE_output_streambuf Tparent; - std::vector<char_type> buf; + MPT_SHARED_PTR<IFileDataContainer> data; + const off_t dataOffset; + const off_t dataLength; public: - FILE_output_buffered_streambuf(FILE *f, std::size_t bufSize = 64*1024) - : FILE_output_streambuf(f) - , buf((bufSize > 0) ? bufSize : 1) + FileDataContainerWindow(MPT_SHARED_PTR<IFileDataContainer> src, off_t off, off_t len) : data(src), dataOffset(off), dataLength(len) { } + virtual ~FileDataContainerWindow() { } + + bool IsValid() const { - setp(&buf[0], &buf[0] + buf.size()); + return data->IsValid(); } - ~FILE_output_buffered_streambuf() - { - if(!mpt::IO::IsValid(f)) - { - return; - } - WriteOut(); + const char *GetRawData() const { + return data->GetRawData() + dataOffset; } -private: - bool IsDirty() const - { - return ((pptr() - pbase()) > 0); + off_t GetLength() const { + return dataLength; } - bool WriteOut() + off_t Read(char *dst, off_t pos, off_t count) const { - std::ptrdiff_t n = pptr() - pbase(); - std::ptrdiff_t left = n; - while(left > 0) + if(pos >= dataLength) { - int backchunk = mpt::saturate_cast<int>(-left); - pbump(backchunk); - left += backchunk; + return 0; } - return mpt::IO::WriteRaw(f, pbase(), n); + return data->Read(dst, dataOffset + pos, std::min(count, dataLength - pos)); } -protected: - virtual int_type overflow(int_type ch) + const char *GetPartialRawData(off_t pos, off_t length) const { - if(!mpt::IO::IsValid(f)) + if(pos + length > dataLength) { - return traits_type::eof(); + return nullptr; } - if(traits_type::eq_int_type(ch, traits_type::eof())) - { - return traits_type::eof(); - } - if(!WriteOut()) - { - return traits_type::eof(); - } - char_type c = traits_type::to_char_type(ch); - *pptr() = c; - pbump(1); - return ch; + return data->GetPartialRawData(dataOffset + pos, length); } - virtual int sync() + bool CanRead(off_t pos, off_t length) const { + return (pos + length <= dataLength); + } + off_t GetReadableLength(off_t pos, off_t length) const { - if(!mpt::IO::IsValid(f)) + if(pos >= dataLength) { - return -1; + return 0; } - if(!WriteOut()) - { - return -1; - } - return Tparent::sync(); + return std::min(length, dataLength - pos); } - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) +}; + + +class FileDataContainerStdStream : public IFileDataContainer { + +private: + + mutable std::vector<char> cache; + mutable bool streamFullyCached; + + std::istream *stream; + +public: + + FileDataContainerStdStream(std::istream *s); + virtual ~FileDataContainerStdStream(); + +private: + + static const std::size_t buffer_size = 65536; + + void CacheStream() const; + void CacheStreamUpTo(std::streampos pos) const; + +private: + + void ReadCached(char *dst, off_t pos, off_t count) const; + +public: + + bool IsValid() const; + const char *GetRawData() const; + off_t GetLength() const; + off_t Read(char *dst, off_t pos, off_t count) const; + const char *GetPartialRawData(off_t pos, off_t length) const; + bool CanRead(off_t pos, off_t length) const; + off_t GetReadableLength(off_t pos, off_t length) const; + +}; + +#endif + + +class FileDataContainerMemory +#if defined(MPT_FILEREADER_STD_ISTREAM) + : public IFileDataContainer +#endif +{ + +#if !defined(MPT_FILEREADER_STD_ISTREAM) +public: + typedef std::size_t off_t; +#endif + +private: + + const char *streamData; // Pointer to memory-mapped file + off_t streamLength; // Size of memory-mapped file in bytes + +public: + FileDataContainerMemory() : streamData(nullptr), streamLength(0) { } + FileDataContainerMemory(const char *data, off_t length) : streamData(data), streamLength(length) { } +#if defined(MPT_FILEREADER_STD_ISTREAM) + virtual +#endif + ~FileDataContainerMemory() { } + +public: + + bool IsValid() const { - if(!mpt::IO::IsValid(f)) + return streamData != nullptr; + } + + const char *GetRawData() const + { + return streamData; + } + + off_t GetLength() const + { + return streamLength; + } + + off_t Read(char *dst, off_t pos, off_t count) const + { + if(pos >= streamLength) { - return pos_type(off_type(-1)); + return 0; } - if(!WriteOut()) - { - return pos_type(off_type(-1)); - } - return Tparent::seekpos(pos, which); + off_t avail = std::min<off_t>(streamLength - pos, count); + std::copy(streamData + pos, streamData + pos + avail, dst); + return avail; } - virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + + const char *GetPartialRawData(off_t pos, off_t length) const { - if(!mpt::IO::IsValid(f)) + if(pos + length > streamLength) { - return pos_type(off_type(-1)); + return nullptr; } - if(!WriteOut()) - { - return pos_type(off_type(-1)); - } - return Tparent::seekoff(off, dir, which); + return streamData + pos; } -}; // class FILE_output_buffered_streambuf - -class FILE_ostream : public std::ostream { -private: - FILE *f; - FILE_output_buffered_streambuf buf; -public: - FILE_ostream(FILE *f, std::size_t bufSize = 64*1024) - : std::ostream(&buf) - , f(f) - , buf(f, bufSize) + bool CanRead(off_t pos, off_t length) const { - if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); + return pos + length <= streamLength; } - ~FILE_ostream() + + off_t GetReadableLength(off_t pos, off_t length) const { - flush(); - buf.pubsync(); - if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); + if(pos >= streamLength) + { + return 0; + } + return std::min<off_t>(length, streamLength - pos); } -}; // class FILE_ostream +}; -} // namespace mpt OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/common/mptPathString.cpp =================================================================== --- trunk/OpenMPT/common/mptPathString.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/mptPathString.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -205,21 +205,6 @@ #endif -FILE * mpt_fopen(const mpt::PathString &filename, const char *mode) -//----------------------------------------------------------------- -{ - #if MPT_OS_WINDOWS - #if defined(MPT_WITH_CHARSET_LOCALE) - return _wfopen(filename.AsNative().c_str(), mode ? mpt::ToWide(mpt::CharsetLocale, mode).c_str() : nullptr); - #else - return _wfopen(filename.AsNative().c_str(), mode ? mpt::ToWide(mpt::CharsetUTF8, mode).c_str() : nullptr); - #endif - #else // !MPT_OS_WINDOWS - return fopen(filename.AsNative().c_str(), mode); - #endif // MPT_OS_WINDOWS -} - - #if defined(MODPLUG_TRACKER) static inline char SanitizeFilenameChar(char c) Modified: trunk/OpenMPT/common/mptPathString.h =================================================================== --- trunk/OpenMPT/common/mptPathString.h 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/mptPathString.h 2014-10-08 12:40:51 UTC (rev 4404) @@ -10,9 +10,6 @@ #pragma once -#include <cstdio> -#include <stdio.h> - OPENMPT_NAMESPACE_BEGIN #if defined(MPT_WITH_PATHSTRING) @@ -231,8 +228,6 @@ #endif // MPT_OS_WINDOWS -FILE * mpt_fopen(const mpt::PathString &filename, const char *mode); - #if defined(MODPLUG_TRACKER) // Sanitize a filename (remove special chars) Modified: trunk/OpenMPT/common/stdafx.h =================================================================== --- trunk/OpenMPT/common/stdafx.h 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/common/stdafx.h 2014-10-08 12:40:51 UTC (rev 4404) @@ -59,8 +59,6 @@ // <cstring> #include "../common/mptPathString.h" -// <cstdio> -// <stdio.h> #include "../common/Logging.h" @@ -73,9 +71,15 @@ // <cstring> // <time.h> +// for std::abs #include <cstdlib> #include <stdlib.h> +#ifndef MODPLUG_NO_FILESAVE +// for FILE* definition (which cannot be forward-declared in a portable way) +#include <stdio.h> +#endif + //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -259,6 +259,7 @@ <ClCompile Include="..\common\AudioCriticalSection.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> + <ClCompile Include="..\common\mptIO.cpp" /> <ClCompile Include="..\common\mptPathString.cpp" /> <ClCompile Include="..\common\mptString.cpp" /> <ClCompile Include="..\common\Profiler.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-10-08 12:40:51 UTC (rev 4404) @@ -517,5 +517,8 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\mptIO.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -269,6 +269,7 @@ <ClCompile Include="..\common\AudioCriticalSection.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> + <ClCompile Include="..\common\mptIO.cpp" /> <ClCompile Include="..\common\mptPathString.cpp" /> <ClCompile Include="..\common\mptString.cpp" /> <ClCompile Include="..\common\Profiler.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-10-08 12:40:51 UTC (rev 4404) @@ -523,5 +523,8 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\mptIO.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -263,6 +263,7 @@ <ClCompile Include="..\common\AudioCriticalSection.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> + <ClCompile Include="..\common\mptIO.cpp" /> <ClCompile Include="..\common\mptPathString.cpp" /> <ClCompile Include="..\common\mptString.cpp" /> <ClCompile Include="..\common\Profiler.cpp" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-10-08 12:40:51 UTC (rev 4404) @@ -520,5 +520,8 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>Source Files\test</Filter> </ClCompile> + <ClCompile Include="..\common\mptIO.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file Modified: trunk/OpenMPT/mptrack/mod2midi.cpp =================================================================== --- trunk/OpenMPT/mptrack/mod2midi.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/mptrack/mod2midi.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -12,6 +12,7 @@ #include "Mptrack.h" #include "../soundlib/Sndfile.h" #include "../common/StringFixer.h" +#include "../common/mptFstream.h" #include "mod2midi.h" #include "Wav.h" Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -664,6 +664,10 @@ > </File> <File + RelativePath="..\common\mptIO.cpp" + > + </File> + <File RelativePath="..\common\mptPathString.cpp" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-10-08 12:40:51 UTC (rev 4404) @@ -447,6 +447,7 @@ <ClCompile Include="..\common\AudioCriticalSection.cpp" /> <ClCompile Include="..\common\Logging.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> + <ClCompile Include="..\common\mptIO.cpp" /> <ClCompile Include="..\common\mptPathString.cpp" /> <ClCompile Include="..\common\mptString.cpp" /> <ClCompile Include="..\common\Profiler.cpp" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-10-08 12:40:51 UTC (rev 4404) @@ -523,6 +523,9 @@ <ClCompile Include="MPTrackLink.cpp"> <Filter>Source Files\mptrack</Filter> </ClCompile> + <ClCompile Include="..\common\mptIO.cpp"> + <Filter>Source Files\common</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\soundlib\Loaders.h"> Modified: trunk/OpenMPT/soundlib/Dlsbank.cpp =================================================================== --- trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -14,6 +14,7 @@ #ifdef MODPLUG_TRACKER #include "../mptrack/mptrack.h" #include "../mptrack/MemoryMappedFile.h" +#include "../common/mptFstream.h" #endif #include "Dlsbank.h" #include "Wav.h" Modified: trunk/OpenMPT/soundlib/FileReader.h =================================================================== --- trunk/OpenMPT/soundlib/FileReader.h 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/FileReader.h 2014-10-08 12:40:51 UTC (rev 4404) @@ -15,11 +15,8 @@ #include "../common/StringFixer.h" #include "../common/misc_util.h" #include "../common/Endianness.h" +#include "../common/mptIO.h" #include <algorithm> -#if defined(MPT_FILEREADER_STD_ISTREAM) -#include <ios> -#include <istream> -#endif #include <limits> #include <vector> #include <cstring> @@ -33,340 +30,6 @@ #define FILEREADER_DEPRECATED -#if defined(MPT_FILEREADER_STD_ISTREAM) - -class IFileDataContainer { -public: - typedef std::size_t off_t; -protected: - IFileDataContainer() { } -public: - virtual ~IFileDataContainer() { } -public: - virtual bool IsValid() const = 0; - virtual const char *GetRawData() const = 0; - virtual off_t GetLength() const = 0; - virtual off_t Read(char *dst, off_t pos, off_t count) const = 0; - - virtual const char *GetPartialRawData(off_t pos, off_t length) const // DO NOT USE!!! this is just for ReadMagic ... the pointer returned may be invalid after the next Read() - { - if(pos + length > GetLength()) - { - return nullptr; - } - return GetRawData() + pos; - } - - virtual bool CanRead(off_t pos, off_t length) const - { - return pos + length <= GetLength(); - } - - virtual off_t GetReadableLength(off_t pos, off_t length) const - { - if(pos >= GetLength()) - { - return 0; - } - return std::min<off_t>(length, GetLength() - pos); - } -}; - - -class FileDataContainerDummy : public IFileDataContainer { -public: - FileDataContainerDummy() { } - virtual ~FileDataContainerDummy() { } -public: - bool IsValid() const - { - return false; - } - - const char *GetRawData() const - { - return nullptr; - } - - off_t GetLength() const - { - return 0; - } - off_t Read(char * /*dst*/, off_t /*pos*/, off_t /*count*/) const - { - return 0; - } -}; - - -class FileDataContainerWindow : public IFileDataContainer -{ -private: - MPT_SHARED_PTR<IFileDataContainer> data; - const off_t dataOffset; - const off_t dataLength; -public: - FileDataContainerWindow(MPT_SHARED_PTR<IFileDataContainer> src, off_t off, off_t len) : data(src), dataOffset(off), dataLength(len) { } - virtual ~FileDataContainerWindow() { } - - bool IsValid() const - { - return data->IsValid(); - } - const char *GetRawData() const { - return data->GetRawData() + dataOffset; - } - off_t GetLength() const { - return dataLength; - } - off_t Read(char *dst, off_t pos, off_t count) const - { - if(pos >= dataLength) - { - return 0; - } - return data->Read(dst, dataOffset + pos, std::min(count, dataLength - pos)); - } - const char *GetPartialRawData(off_t pos, off_t length) const - { - if(pos + length > dataLength) - { - return nullptr; - } - return data->GetPartialRawData(dataOffset + pos, length); - } - bool CanRead(off_t pos, off_t length) const { - return (pos + length <= dataLength); - } - off_t GetReadableLength(off_t pos, off_t length) const - { - if(pos >= dataLength) - { - return 0; - } - return std::min(length, dataLength - pos); - } -}; - - -class FileDataContainerStdStream : public IFileDataContainer { -private: - mutable std::vector<char> cache; - mutable bool streamFullyCached; - - std::istream *stream; - -public: - FileDataContainerStdStream(std::istream *s) : streamFullyCached(false), stream(s) { } - virtual ~FileDataContainerStdStream() { } - -private: - static const std::size_t buffer_size = 65536; - void CacheStream() const - { - if(streamFullyCached) - { - return; - } - while(*stream) - { - cache.resize(cache.size() + buffer_size); - stream->read(&cache[cache.size() - buffer_size], buffer_size); - std::size_t readcount = static_cast<std::size_t>(stream->gcount()); - cache.resize(cache.size() - buffer_size + readcount); - } - streamFullyCached = true; - } - void CacheStreamUpTo(std::streampos pos) const - { - if(streamFullyCached) - { - return; - } - if(pos <= std::streampos(cache.size())) - { - return; - } - std::size_t needcount = static_cast<std::size_t>(pos - std::streampos(cache.size())); - cache.resize(static_cast<std::size_t>(pos)); - stream->read(&cache[cache.size() - needcount], needcount); - std::size_t readcount = static_cast<std::size_t>(stream->gcount()); - cache.resize(cache.size() - needcount + readcount); - if(*stream) - { - // can read further - return; - } - streamFullyCached = true; - } -private: - void ReadCached(char *dst, off_t pos, off_t count) const - { - std::copy(cache.begin() + pos, cache.begin() + pos + count, dst); - } - -public: - - bool IsValid() const - { - return true; - } - - const char *GetRawData() const - { - CacheStream(); - return &cache[0]; - } - - off_t GetLength() const - { - if(streamFullyCached) - { - return cache.size(); - } else - { - stream->clear(); - std::streampos oldpos = stream->tellg(); - if(!stream->fail() && oldpos != std::streampos(-1)) - { - stream->seekg(0, std::ios::end); - if(!stream->fail()) - { - std::streampos length = stream->tellg(); - if(!stream->fail() && length != std::streampos(-1)) - { - stream->seekg(oldpos); - stream->clear(); - return static_cast<off_t>(length); - } - } - stream->clear(); - stream->seekg(oldpos); - } - // not seekable - stream->clear(); - CacheStream(); - return cache.size(); - } - } - - off_t Read(char *dst, off_t pos, off_t count) const - { - CacheStreamUpTo(pos + count); - if(pos >= off_t(cache.size())) - { - return 0; - } - off_t cache_avail = std::min<off_t>(off_t(cache.size()) - pos, count); - ReadCached(dst, pos, cache_avail); - return cache_avail; - } - - const char *GetPartialRawData(off_t pos, off_t length) const - { - CacheStreamUpTo(pos + length); - if(pos + length > off_t(cache.size())) - { - return nullptr; - } - return &cache[pos]; - } - - bool CanRead(off_t pos, off_t length) const - { - CacheStreamUpTo(pos + length); - return pos + length <= off_t(cache.size()); - } - - off_t GetReadableLength(off_t pos, off_t length) const - { - CacheStreamUpTo(pos + length); - return std::min<off_t>(cache.size() - pos, length); - } - -}; - -#endif - - -class FileDataContainerMemory -#if defined(MPT_FILEREADER_STD_ISTREAM) - : public IFileDataContainer -#endif -{ - -#if !defined(MPT_FILEREADER_STD_ISTREAM) -public: - typedef std::size_t off_t; -#endif - -private: - - const char *streamData; // Pointer to memory-mapped file - off_t streamLength; // Size of memory-mapped file in bytes - -public: - FileDataContainerMemory() : streamData(nullptr), streamLength(0) { } - FileDataContainerMemory(const char *data, off_t length) : streamData(data), streamLength(length) { } -#if defined(MPT_FILEREADER_STD_ISTREAM) - virtual -#endif - ~FileDataContainerMemory() { } - -public: - - bool IsValid() const - { - return streamData != nullptr; - } - - const char *GetRawData() const - { - return streamData; - } - - off_t GetLength() const - { - return streamLength; - } - - off_t Read(char *dst, off_t pos, off_t count) const - { - if(pos >= streamLength) - { - return 0; - } - off_t avail = std::min<off_t>(streamLength - pos, count); - std::copy(streamData + pos, streamData + pos + avail, dst); - return avail; - } - - const char *GetPartialRawData(off_t pos, off_t length) const - { - if(pos + length > streamLength) - { - return nullptr; - } - return streamData + pos; - } - - bool CanRead(off_t pos, off_t length) const - { - return pos + length <= streamLength; - } - - off_t GetReadableLength(off_t pos, off_t length) const - { - if(pos >= streamLength) - { - return 0; - } - return std::min<off_t>(length, streamLength - pos); - } - -}; - - //============== class FileReader //============== Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -18,7 +18,9 @@ #endif #include "../common/mptIO.h" #include "../common/serialization_utils.h" +#ifndef MODPLUG_NO_FILESAVE #include "../common/mptFstream.h" +#endif #include <sstream> #include <list> #include "../common/version.h" Modified: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -22,7 +22,8 @@ #include "../mptrack/TrackerSettings.h" #if !defined(MPT_FILEREADER_STD_ISTREAM) #include "../mptrack/MemoryMappedFile.h" -#else +#endif +#ifndef MODPLUG_NO_FILESAVE #include "../common/mptFstream.h" #endif #include "../mptrack/Moddoc.h" Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -12,6 +12,9 @@ #include "stdafx.h" #include "Loaders.h" #include "Tables.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif OPENMPT_NAMESPACE_BEGIN Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -11,6 +11,9 @@ #include "stdafx.h" #include "Loaders.h" #include "S3MTools.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif #include "../common/version.h" Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -15,6 +15,9 @@ #include "../common/version.h" #include "../common/misc_util.h" #include "XMTools.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif #include <algorithm> #ifdef MODPLUG_TRACKER #include "../mptrack/TrackerSettings.h" // For super smooth ramping option Modified: trunk/OpenMPT/soundlib/SampleFormats.cpp =================================================================== --- trunk/OpenMPT/soundlib/SampleFormats.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/SampleFormats.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -16,6 +16,9 @@ #include "../mptrack/TrackerSettings.h" #endif //MODPLUG_TRACKER #include "../common/AudioCriticalSection.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif #include "Wav.h" #include "Tagging.h" #include "ITTools.h" Modified: trunk/OpenMPT/soundlib/SampleIO.cpp =================================================================== --- trunk/OpenMPT/soundlib/SampleIO.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/SampleIO.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -16,6 +16,9 @@ #include "SampleFormatConverters.h" #include "ITCompression.h" #include "../common/mptIO.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif OPENMPT_NAMESPACE_BEGIN Modified: trunk/OpenMPT/soundlib/WAVTools.cpp =================================================================== --- trunk/OpenMPT/soundlib/WAVTools.cpp 2014-10-07 15:17:38 UTC (rev 4403) +++ trunk/OpenMPT/soundlib/WAVTools.cpp 2014-10-08 12:40:51 UTC (rev 4404) @@ -11,6 +11,9 @@ #include "stdafx.h" #include "Loaders.h" #include "WAVTools.h" +#ifndef MODPLUG_NO_FILESAVE +#include "../common/mptFstream.h" +#endif OPENMPT_NAMESPACE_BEGIN This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |