From: <man...@us...> - 2014-12-13 09:59:41
|
Revision: 4645 http://sourceforge.net/p/modplug/code/4645 Author: manxorist Date: 2014-12-13 09:59:22 +0000 (Sat, 13 Dec 2014) Log Message: ----------- [Ref] Move FileReader.h from soundlib/ to common/. Modified Paths: -------------- trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 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_impl.cpp trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/MIDIMapping.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/PNG.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/VstPresets.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/ChunkReader.h trunk/OpenMPT/soundlib/Dlsbank.cpp trunk/OpenMPT/soundlib/ITCompression.h trunk/OpenMPT/soundlib/Loaders.h trunk/OpenMPT/soundlib/Message.cpp trunk/OpenMPT/soundlib/Mmcmp.cpp trunk/OpenMPT/soundlib/ModSequence.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/test/test.cpp trunk/OpenMPT/unarchiver/archive.h trunk/OpenMPT/unarchiver/unarchiver.cpp trunk/OpenMPT/unarchiver/unarchiver.h trunk/OpenMPT/unarchiver/ungzip.cpp trunk/OpenMPT/unarchiver/unzip.cpp Added Paths: ----------- trunk/OpenMPT/common/FileReader.h Removed Paths: ------------- trunk/OpenMPT/soundlib/FileReader.h Modified: trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj =================================================================== --- trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/build/vs2008/libopenmpt/libopenmpt.vcproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -174,6 +174,10 @@ > </File> <File + RelativePath="..\..\..\common\FileReader.h" + > + </File> + <File RelativePath="..\..\..\common\FlagSet.h" > </File> @@ -318,10 +322,6 @@ > </File> <File - RelativePath="..\..\..\soundlib\FileReader.h" - > - </File> - <File RelativePath="..\..\..\soundlib\FloatMixer.h" > </File> Copied: trunk/OpenMPT/common/FileReader.h (from rev 4644, trunk/OpenMPT/soundlib/FileReader.h) =================================================================== --- trunk/OpenMPT/common/FileReader.h (rev 0) +++ trunk/OpenMPT/common/FileReader.h 2014-12-13 09:59:22 UTC (rev 4645) @@ -0,0 +1,810 @@ +/* + * FileReader.h + * ------------ + * Purpose: A basic class for transparent reading of memory-based files. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + + +#include "typedefs.h" +#include "StringFixer.h" +#include "misc_util.h" +#include "Endianness.h" +#include "mptIO.h" +#include <algorithm> +#include <limits> +#include <vector> +#include <cstring> + + +OPENMPT_NAMESPACE_BEGIN + + +// change to show warnings for functions which trigger pre-caching the whole file for unseekable streams +//#define FILEREADER_DEPRECATED MPT_DEPRECATED +#define FILEREADER_DEPRECATED + + +//============== +class FileReader +//============== +{ + +public: + +#if defined(MPT_FILEREADER_STD_ISTREAM) + typedef IFileDataContainer::off_t off_t; +#else + typedef FileDataContainerMemory::off_t off_t; +#endif + +private: + +#if defined(MPT_FILEREADER_STD_ISTREAM) + const IFileDataContainer & DataContainer() const { return *data; } + IFileDataContainer & DataContainer() { return *data; } + MPT_SHARED_PTR<IFileDataContainer> data; +#else + const FileDataContainerMemory & DataContainer() const { return data; } + FileDataContainerMemory & DataContainer() { return data; } + FileDataContainerMemory data; +#endif + + off_t streamPos; // Cursor location in the file + +#if defined(MPT_WITH_FILEIO) + const mpt::PathString *fileName; // Filename that corresponds to this FileReader. It is only set if this FileReader represents the whole contents of fileName. May be nullptr. + #define MPT_FILEREADER_INIT_FILENAME ,fileName(nullptr) +#else // !MPT_WITH_FILEIO + #define MPT_FILEREADER_INIT_FILENAME +#endif // MPT_WITH_FILEIO + +public: + +#if defined(MPT_FILEREADER_STD_ISTREAM) + + // Initialize invalid file reader object. + FileReader() : data(mpt::make_shared<FileDataContainerDummy>()), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + + // Initialize file reader object with pointer to data and data length. + FileReader(const void *voiddata, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(static_cast<const char *>(voiddata), length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + FileReader(const char *chardata, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(chardata, length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + FileReader(const uint8 *uint8data, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(reinterpret_cast<const char *>(uint8data), length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } +#if defined(MPT_WITH_FILEIO) + FileReader(const void *voiddata, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(static_cast<const char *>(voiddata), length)), streamPos(0), fileName(filename) { } + FileReader(const char *chardata, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(chardata, length)), streamPos(0), fileName(filename) { } + FileReader(const uint8 *uint8data, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(reinterpret_cast<const char *>(uint8data), length)), streamPos(0), fileName(filename) { } +#endif // MPT_WITH_FILEIO + + // Initialize file reader object with a std::istream. + FileReader(std::istream *s) : data(mpt::make_shared<FileDataContainerStdStream>(s)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } +#if defined(MPT_WITH_FILEIO) + FileReader(std::istream *s, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerStdStream>(s)), streamPos(0), fileName(filename) { } +#endif // MPT_WITH_FILEIO + + // Initialize file reader object based on an existing file reader object window. + FileReader(MPT_SHARED_PTR<IFileDataContainer> other) : data(other), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + + // Initialize file reader object based on an existing file reader object. The other object's stream position is copied. + FileReader(const FileReader &other) : data(other.data), streamPos(other.streamPos) +#if defined(MPT_WITH_FILEIO) + , fileName(other.fileName) +#endif // MPT_WITH_FILEIO + { } + +#else // !MPT_FILEREADER_STD_ISTREAM + + // Initialize invalid file reader object. + FileReader() : data(nullptr, 0), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + + // Initialize file reader object with pointer to data and data length. + FileReader(const void *voiddata, off_t length) : data(static_cast<const char *>(voiddata), length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + FileReader(const char *chardata, off_t length) : data(chardata, length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } + FileReader(const uint8 *uint8data, off_t length) : data(reinterpret_cast<const char *>(uint8data), length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } +#if defined(MPT_WITH_FILEIO) + FileReader(const void *voiddata, off_t length, const mpt::PathString *filename) : data(static_cast<const char *>(voiddata), length), streamPos(0), fileName(filename) { } + FileReader(const char *chardata, off_t length, const mpt::PathString *filename) : data(chardata, length), streamPos(0), fileName(filename) { } + FileReader(const uint8 *uint8data, off_t length, const mpt::PathString *filename) : data(reinterpret_cast<const char *>(uint8data), length), streamPos(0), fileName(filename) { } +#endif // MPT_WITH_FILEIO + + // Initialize file reader object based on an existing file reader object. The other object's stream position is copied. + FileReader(const FileReader &other) : data(other.data), streamPos(other.streamPos) +#if defined(MPT_WITH_FILEIO) + , fileName(other.fileName) +#endif // MPT_WITH_FILEIO + { } + +#endif // MPT_FILEREADER_STD_ISTREAM + + +#if defined(MPT_WITH_FILEIO) + mpt::PathString GetFileName() const + { + if(!fileName) + { + return mpt::PathString(); + } + return *fileName; + } +#endif // MPT_WITH_FILEIO + + // Returns true if the object points to a valid stream. + bool IsValid() const + { + return DataContainer().IsValid(); + } + + // Reset cursor to first byte in file. + void Rewind() + { + streamPos = 0; + } + + // Seek to a position in the mapped file. + // Returns false if position is invalid. + bool Seek(off_t position) + { + if(position <= streamPos) + { + streamPos = position; + return true; + } + if(position <= DataContainer().GetLength()) + { + streamPos = position; + return true; + } else + { + return false; + } + } + + // Increases position by skipBytes. + // Returns true if skipBytes could be skipped or false if the file end was reached earlier. + bool Skip(off_t skipBytes) + { + if(CanRead(skipBytes)) + { + streamPos += skipBytes; + return true; + } else + { + streamPos = DataContainer().GetLength(); + return false; + } + } + + // Decreases position by skipBytes. + // Returns true if skipBytes could be skipped or false if the file start was reached earlier. + bool SkipBack(off_t skipBytes) + { + if(streamPos >= skipBytes) + { + streamPos -= skipBytes; + return true; + } else + { + streamPos = 0; + return false; + } + } + + // Returns cursor position in the mapped file. + off_t GetPosition() const + { + return streamPos; + } + + // Returns size of the mapped file in bytes. + FILEREADER_DEPRECATED off_t GetLength() const + { + // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file + return DataContainer().GetLength(); + } + + // Return byte count between cursor position and end of file, i.e. how many bytes can still be read. + FILEREADER_DEPRECATED off_t BytesLeft() const + { + // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file + return DataContainer().GetLength() - streamPos; + } + + bool AreBytesLeft() const + { + return CanRead(1); + } + + bool NoBytesLeft() const + { + return !CanRead(1); + } + + // Check if "amount" bytes can be read from the current position in the stream. + bool CanRead(off_t amount) const + { + return DataContainer().CanRead(streamPos, amount); + } + + // Create a new FileReader object for parsing a sub chunk at a given position with a given length. + // The file cursor is not modified. + FileReader GetChunk(off_t position, off_t length) const + { + off_t readableLength = DataContainer().GetReadableLength(position, length); + if(readableLength == 0) + { + return FileReader(); + } + #if defined(MPT_FILEREADER_STD_ISTREAM) + return FileReader(mpt::make_shared<FileDataContainerWindow>(data, position, std::min(length, DataContainer().GetLength() - position))); + #else + return FileReader(DataContainer().GetRawData() + position, std::min(length, DataContainer().GetLength() - position)); + #endif + } + + // Create a new FileReader object for parsing a sub chunk at the current position with a given length. + // The file cursor is advanced by "length" bytes. + FileReader ReadChunk(off_t length) + { + off_t position = streamPos; + Skip(length); + return GetChunk(position, length); + } + + // Returns raw stream data at cursor position. + // Should only be used if absolutely necessary, for example for sample reading. + FILEREADER_DEPRECATED const char *GetRawData() const + { + // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file + return DataContainer().GetRawData() + streamPos; + } + + std::size_t ReadRaw(char *dst, std::size_t count) + { + std::size_t result = static_cast<std::size_t>(DataContainer().Read(dst, streamPos, count)); + streamPos += result; + return result; + } + +protected: + + // Read a "T" object from the stream. + // If not enough bytes can be read, false is returned. + // If successful, the file cursor is advanced by the size of "T". + template <typename T> + bool Read(T &target) + { + if(sizeof(T) != DataContainer().Read(reinterpret_cast<char*>(&target), streamPos, sizeof(T))) + { + return false; + } + streamPos += sizeof(T); + return true; + } + +public: + + // Read some kind of integer in little-endian format. + // If successful, the file cursor is advanced by the size of the integer. + template <typename T> + T ReadIntLE() + { + static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); + T target; + if(Read(target)) + { + return SwapBytesReturnLE(target); + } else + { + return 0; + } + } + + // Read some kind of integer in big-endian format. + // If successful, the file cursor is advanced by the size of the integer. + template <typename T> + T ReadIntBE() + { + static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); + T target; + if(Read(target)) + { + return SwapBytesReturnBE(target); + } else + { + return 0; + } + } + + // Read a integer in little-endian format which has some of its higher bytes not stored in file. + // If successful, the file cursor is advanced by the given size. + template <typename T> + T ReadTruncatedIntLE(off_t size) + { + static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); + MPT_ASSERT(sizeof(T) >= size); + if(size == 0) + { + return 0; + } + if(!CanRead(size)) + { + return 0; + } + uint8 buf[sizeof(T)]; + for(std::size_t i = 0; i < sizeof(T); ++i) + { + if(i < size) + { + Read(buf[i]); + } else + { + if(std::numeric_limits<T>::is_signed) + { + // sign extend + const bool negative = (i > 0) && ((buf[i-1] & 0x80) != 0x00); + buf[i] = negative ? 0xff : 0x00; + } else + { + // zero extend + buf[i] = 0x00; + } + } + } + T target; + std::memcpy(&target, buf, sizeof(T)); + return SwapBytesReturnLE(target); + } + + // Read a supplied-size little endian integer to a fixed size variable. + // The data is properly sign-extended when fewer bytes are stored. + // If more bytes are stored, higher order bytes are silently ignored. + // If successful, the file cursor is advanced by the given size. + template <typename T> + T ReadSizedIntLE(off_t size) + { + static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); + if(size == 0) + { + return 0; + } + if(!CanRead(size)) + { + return 0; + } + if(size < sizeof(T)) + { + return ReadTruncatedIntLE<T>(size); + } + T retval = ReadIntLE<T>(); + Skip(size - sizeof(T)); + return retval; + } + + // Read unsigned 32-Bit integer in little-endian format. + // If successful, the file cursor is advanced by the size of the integer. + uint32 ReadUint32LE() + { + return ReadIntLE<uint32>(); + } + + // Read unsigned 32-Bit integer in big-endian format. + // If successful, the file cursor is advanced by the size of the integer. + uint32 ReadUint32BE() + { + return ReadIntBE<uint32>(); + } + + // Read signed 32-Bit integer in little-endian format. + // If successful, the file cursor is advanced by the size of the integer. + int32 ReadInt32LE() + { + return ReadIntLE<int32>(); + } + + // Read signed 32-Bit integer in big-endian format. + // If successful, the file cursor is advanced by the size of the integer. + int32 ReadInt32BE() + { + return ReadIntBE<int32>(); + } + + // Read unsigned 16-Bit integer in little-endian format. + // If successful, the file cursor is advanced by the size of the integer. + uint16 ReadUint16LE() + { + return ReadIntLE<uint16>(); + } + + // Read unsigned 16-Bit integer in big-endian format. + // If successful, the file cursor is advanced by the size of the integer. + uint16 ReadUint16BE() + { + return ReadIntBE<uint16>(); + } + + // Read signed 16-Bit integer in little-endian format. + // If successful, the file cursor is advanced by the size of the integer. + int16 ReadInt16LE() + { + return ReadIntLE<int16>(); + } + + // Read signed 16-Bit integer in big-endian format. + // If successful, the file cursor is advanced by the size of the integer. + int16 ReadInt16BE() + { + return ReadIntBE<int16>(); + } + + // Read unsigned 8-Bit integer. + // If successful, the file cursor is advanced by the size of the integer. + uint8 ReadUint8() + { + uint8 target; + if(Read(target)) + { + return target; + } else + { + return 0; + } + } + + // Read signed 8-Bit integer. If successful, the file cursor is advanced by the size of the integer. + int8 ReadInt8() + { + int8 target; + if(Read(target)) + { + return target; + } else + { + return 0; + } + } + + // Read 32-Bit float in little-endian format. + // If successful, the file cursor is advanced by the size of the float. + float ReadFloatLE() + { + IEEE754binary32LE target; + if(Read(target)) + { + return target; + } else + { + return 0.0f; + } + } + + // Read 32-Bit float in big-endian format. + // If successful, the file cursor is advanced by the size of the float. + float ReadFloatBE() + { + IEEE754binary32BE target; + if(Read(target)) + { + return target; + } else + { + return 0.0f; + } + } + + // Read 64-Bit float in little-endian format. + // If successful, the file cursor is advanced by the size of the float. + double ReadDoubleLE() + { + IEEE754binary64LE target; + if(Read(target)) + { + return target; + } else + { + return 0.0f; + } + } + + // Read 64-Bit float in big-endian format. + // If successful, the file cursor is advanced by the size of the float. + double ReadDoubleBE() + { + IEEE754binary64BE target; + if(Read(target)) + { + return target; + } else + { + return 0.0f; + } + } + + // Read a struct. + // If successful, the file cursor is advanced by the size of the struct. Otherwise, the target is zeroed. + template <typename T> + bool ReadStruct(T &target) + { + if(Read(target)) + { + return true; + } else + { + MemsetZero(target); + return false; + } + } + + // Allow to read a struct partially (if there's less memory available than the struct's size, fill it up with zeros). + // The file cursor is advanced by "partialSize" bytes. + template <typename T> + bool ReadStructPartial(T &target, off_t partialSize = sizeof(T)) + { + off_t copyBytes = std::min(partialSize, sizeof(T)); + if(!CanRead(copyBytes)) + { + copyBytes = BytesLeft(); + } + DataContainer().Read(reinterpret_cast<char *>(&target), streamPos, copyBytes); + memset(reinterpret_cast<char *>(&target) + copyBytes, 0, sizeof(target) - copyBytes); + Skip(partialSize); + return true; + } + + // Read a "T" object from the stream. + // If not enough bytes can be read, false is returned. + // If successful, the file cursor is advanced by the size of "T" and the object's "ConvertEndianness()" method is called. + template <typename T> + bool ReadConvertEndianness(T &target) + { + if(Read(target)) + { + target.ConvertEndianness(); + return true; + } else + { + return false; + } + } + + // Read a string of length srcSize into fixed-length char array destBuffer using a given read mode. + // The file cursor is advanced by "srcSize" bytes. + template<mpt::String::ReadWriteMode mode, off_t destSize> + bool ReadString(char (&destBuffer)[destSize], const off_t srcSize) + { + if(CanRead(srcSize)) + { + mpt::String::Read<mode, destSize>(destBuffer, DataContainer().GetPartialRawData(streamPos, srcSize), srcSize); + streamPos += srcSize; + return true; + } else + { + return false; + } + } + + // Read a string of length srcSize into a std::string dest using a given read mode. + // The file cursor is advanced by "srcSize" bytes. + template<mpt::String::ReadWriteMode mode> + bool ReadString(std::string &dest, const off_t srcSize) + { + if(CanRead(srcSize)) + { + mpt::String::Read<mode>(dest, DataContainer().GetPartialRawData(streamPos, srcSize), srcSize); + streamPos += srcSize; + return true; + } else + { + return false; + } + } + + // Read a null-terminated string into a std::string + bool ReadNullString(std::string &dest, const off_t maxLength = std::numeric_limits<std::size_t>::max()) + { + dest.clear(); + char c; + while(Read(c) && c != 0 && dest.length() < maxLength) + { + dest += c; + } + return dest.length() != 0; + } + + // Read an array of byte-sized values. + // If successful, the file cursor is advanced by the size of the array. + // Otherwise, the target is zeroed. + template<typename T, off_t destSize> + bool ReadArray(T (&destArray)[destSize]) + { + STATIC_ASSERT(sizeof(T) == 1); + if(CanRead(sizeof(destArray))) + { + for(std::size_t i = 0; i < destSize; ++i) + { + Read(destArray[i]); + } + return true; + } else + { + MemsetZero(destArray); + return false; + } + } + + // Read an array. + // If successful, the file cursor is advanced by the size of the array. + // Otherwise, the target is zeroed. + template<typename T, off_t destSize> + bool ReadArrayLE(T (&destArray)[destSize]) + { + if(CanRead(sizeof(destArray))) + { + for(std::size_t i = 0; i < destSize; ++i) + { + destArray[i] = ReadIntLE<T>(); + } + return true; + } else + { + MemsetZero(destArray); + return false; + } + } + + // Read destSize elements of byte-sized type T into a vector. + // If successful, the file cursor is advanced by the size of the vector. + // Otherwise, the vector is resized to destSize, but possibly existing contents are not cleared. + template<typename T> + bool ReadVector(std::vector<T> &destVector, size_t destSize) + { + STATIC_ASSERT(sizeof(T) == 1); + const off_t readSize = sizeof(T) * destSize; + destVector.resize(destSize); + if(CanRead(readSize)) + { + for(std::size_t i = 0; i < destSize; ++i) + { + Read(destVector[i]); + } + return true; + } else + { + return false; + } + } + + // Read destSize elements of type T into a vector. + // If successful, the file cursor is advanced by the size of the vector. + // Otherwise, the vector is resized to destSize, but possibly existing contents are not cleared. + template<typename T> + bool ReadVectorLE(std::vector<T> &destVector, size_t destSize) + { + const off_t readSize = sizeof(T) * destSize; + destVector.resize(destSize); + if(CanRead(readSize)) + { + for(std::size_t i = 0; i < destSize; ++i) + { + destVector[i] = ReadIntLE<T>(); + } + return true; + } else + { + return false; + } + } + + // Compare a magic string with the current stream position. + // Returns true if they are identical and advances the file cursor by the the length of the "magic" string. + // Returns false if the string could not be found. The file cursor is not advanced in this case. + bool ReadMagic(const char *const magic) + { + const off_t magicLength = strlen(magic); + if(CanRead(magicLength)) + { + if(!memcmp(DataContainer().GetPartialRawData(streamPos, magicLength), magic, magicLength)) + { + streamPos += magicLength; + return true; + } else + { + return false; + } + } else + { + return false; + } + } + + // Read variable-length integer (as found in MIDI files). + // If successful, the file cursor is advanced by the size of the integer and true is returned. + // False is returned if not enough bytes were left to finish reading of the integer or if an overflow happened (source doesn't fit into target integer). + // In case of an overflow, the target is also set to the maximum value supported by its data type. + template<typename T> + bool ReadVarInt(T &target) + { + static_assert(std::numeric_limits<T>::is_integer == true + && std::numeric_limits<T>::is_signed == false, + "Target type is a not an unsigned integer"); + + if(NoBytesLeft()) + { + target = 0; + return false; + } + + size_t writtenBits = 0; + uint8 b = ReadUint8(); + target = (b & 0x7F); + + // Count actual bits used in most significant byte (i.e. this one) + for(size_t bit = 0; bit < 7; bit++) + { + if((b & (1 << bit)) != 0) + { + writtenBits = bit + 1; + } + } + + while(AreBytesLeft() && (b & 0x80) != 0) + { + b = ReadUint8(); + target <<= 7; + target |= (b & 0x7F); + writtenBits += 7; + }; + + if(writtenBits > sizeof(target) * 8) + { + // Overflow + target = Util::MaxValueOfType<T>(target); + return false; + } else if((b & 0x80) != 0) + { + // Reached EOF + return false; + } + return true; + } + +}; + + +#if defined(MPT_WITH_FILEIO) +// templated in order to reduce header inter-depoendencies +template <typename TInputFile> +FileReader GetFileReader(TInputFile &file) +{ + #if defined(MPT_FILEREADER_STD_ISTREAM) + typename TInputFile::ContentsRef tmp = file.Get(); + if(!tmp.first) + { + return FileReader(); + } + if(!tmp.first->good()) + { + return FileReader(); + } + #ifdef MPT_WITH_FILEIO + return FileReader(tmp.first, tmp.second); + #else + return FileReader(tmp.first); + #endif + #else + typename TInputFile::ContentsRef tmp = file.Get(); + #ifdef MPT_WITH_FILEIO + return FileReader(tmp.first.data, tmp.first.size, tmp.second); + #else + return FileReader(tmp.first.data, tmp.first.size); + #endif + #endif +} +#endif // MPT_WITH_FILEIO + + +OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -181,6 +181,7 @@ <ClInclude Include="..\common\CompilerDetect.h" /> <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> + <ClInclude Include="..\common\FileReader.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> @@ -202,7 +203,6 @@ <ClInclude Include="..\soundlib\ChunkReader.h" /> <ClInclude Include="..\soundlib\Dither.h" /> <ClInclude Include="..\soundlib\Dlsbank.h" /> - <ClInclude Include="..\soundlib\FileReader.h" /> <ClInclude Include="..\soundlib\FloatMixer.h" /> <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-12-13 09:59:22 UTC (rev 4645) @@ -74,9 +74,6 @@ <ClInclude Include="..\soundlib\Dlsbank.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> - <ClInclude Include="..\soundlib\FileReader.h"> - <Filter>Header Files\soundlib</Filter> - </ClInclude> <ClInclude Include="..\soundlib\ITCompression.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> @@ -269,6 +266,9 @@ <ClInclude Include="..\common\mptFileIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\FileReader.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -189,6 +189,7 @@ <ClInclude Include="..\common\CompilerDetect.h" /> <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> + <ClInclude Include="..\common\FileReader.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> @@ -210,7 +211,6 @@ <ClInclude Include="..\soundlib\ChunkReader.h" /> <ClInclude Include="..\soundlib\Dither.h" /> <ClInclude Include="..\soundlib\Dlsbank.h" /> - <ClInclude Include="..\soundlib\FileReader.h" /> <ClInclude Include="..\soundlib\FloatMixer.h" /> <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-12-13 09:59:22 UTC (rev 4645) @@ -74,9 +74,6 @@ <ClInclude Include="..\soundlib\Dlsbank.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> - <ClInclude Include="..\soundlib\FileReader.h"> - <Filter>Header Files\soundlib</Filter> - </ClInclude> <ClInclude Include="..\soundlib\ITCompression.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> @@ -275,6 +272,9 @@ <ClInclude Include="..\common\mptFileIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\FileReader.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -27,9 +27,9 @@ #include "common/version.h" #include "common/misc_util.h" +#include "common/FileReader.h" #include "soundlib/Sndfile.h" #include "soundlib/AudioReadTarget.h" -#include "soundlib/FileReader.h" using namespace OpenMPT; Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -185,6 +185,7 @@ <ClInclude Include="..\common\CompilerDetect.h" /> <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> + <ClInclude Include="..\common\FileReader.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> @@ -206,7 +207,6 @@ <ClInclude Include="..\soundlib\ChunkReader.h" /> <ClInclude Include="..\soundlib\Dither.h" /> <ClInclude Include="..\soundlib\Dlsbank.h" /> - <ClInclude Include="..\soundlib\FileReader.h" /> <ClInclude Include="..\soundlib\FloatMixer.h" /> <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-12-13 09:59:22 UTC (rev 4645) @@ -74,9 +74,6 @@ <ClInclude Include="..\soundlib\Dlsbank.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> - <ClInclude Include="..\soundlib\FileReader.h"> - <Filter>Header Files\soundlib</Filter> - </ClInclude> <ClInclude Include="..\soundlib\ITCompression.h"> <Filter>Header Files\soundlib</Filter> </ClInclude> @@ -269,6 +266,9 @@ <ClInclude Include="..\common\mptFileIO.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\FileReader.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -19,7 +19,7 @@ #include "../common/StringFixer.h" #include "MIDIMacros.h" #include "VstPresets.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "InputHandler.h" #include "dlg_misc.h" Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -24,7 +24,7 @@ #include "../common/StringFixer.h" #include "SelectPluginDialog.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "FileDialog.h" Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -28,7 +28,7 @@ #include "Autotune.h" #include "../common/StringFixer.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "../soundlib/SampleFormatConverters.h" #include "FileDialog.h" #include "../common/ComponentManager.h" Modified: trunk/OpenMPT/mptrack/MIDIMapping.cpp =================================================================== --- trunk/OpenMPT/mptrack/MIDIMapping.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/MIDIMapping.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -11,7 +11,7 @@ #include "stdafx.h" #include "../soundlib/MIDIEvents.h" #include "Mainfrm.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "MIDIMapping.h" Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -35,7 +35,7 @@ #include "ExceptionHandler.h" #include "PatternClipboard.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "../common/Profiler.h" #include "FileDialog.h" #include <HtmlHelp.h> Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -30,7 +30,7 @@ #include "CleanupSong.h" #include "../common/StringFixer.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include <shlwapi.h> #include "FileDialog.h" #include "ExternalSamples.h" Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -20,7 +20,7 @@ // VST cloning #include "Vstplug.h" #include "VstPresets.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include <sstream> Modified: trunk/OpenMPT/mptrack/PNG.cpp =================================================================== --- trunk/OpenMPT/mptrack/PNG.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/PNG.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -12,7 +12,7 @@ #include "stdafx.h" #include "MPTrackUtil.h" #include "PNG.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #if !defined(NO_ZLIB) #include <zlib.h> #elif !defined(NO_MINIZ) Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -23,7 +23,7 @@ #include "../soundlib/MIDIEvents.h" #include "SampleEditorDialogs.h" #include "../soundlib/WAVTools.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "../soundlib/SampleFormatConverters.h" Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -19,7 +19,7 @@ #include "dlg_misc.h" #include "vstplug.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "FileDialog.h" #include "Globals.h" #include "ExternalSamples.h" Modified: trunk/OpenMPT/mptrack/VstPresets.cpp =================================================================== --- trunk/OpenMPT/mptrack/VstPresets.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/VstPresets.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -15,7 +15,7 @@ #include "Vstplug.h" #include <vstsdk2.4/pluginterfaces/vst2.x/vstfxstore.h> #include "VstPresets.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include <ostream> Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -24,7 +24,7 @@ #include "MIDIMappingDialog.h" #include "../common/StringFixer.h" #include "../common/mptFileIO.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "FileDialog.h" Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -1254,7 +1254,7 @@ > </File> <File - RelativePath=".\FolderScanner.h" + RelativePath="..\common\FileReader.h" > </File> <File @@ -1266,6 +1266,10 @@ > </File> <File + RelativePath=".\FolderScanner.h" + > + </File> + <File RelativePath=".\globals.h" > </File> @@ -1770,10 +1774,6 @@ > </File> <File - RelativePath="..\soundlib\FileReader.h" - > - </File> - <File RelativePath="..\soundlib\ITTools.cpp" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-12-13 09:59:22 UTC (rev 4645) @@ -941,6 +941,7 @@ <ClInclude Include="..\common\CompilerDetect.h" /> <ClInclude Include="..\common\ComponentManager.h" /> <ClInclude Include="..\common\Endianness.h" /> + <ClInclude Include="..\common\FileReader.h" /> <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> @@ -975,7 +976,6 @@ <ClInclude Include="..\soundlib\ChunkReader.h" /> <ClInclude Include="..\soundlib\Dither.h" /> <ClInclude Include="..\soundlib\Dlsbank.h" /> - <ClInclude Include="..\soundlib\FileReader.h" /> <ClInclude Include="..\soundlib\FloatMixer.h" /> <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-12-13 09:59:22 UTC (rev 4645) @@ -609,9 +609,6 @@ <ClInclude Include="..\soundlib\ChunkReader.h"> <Filter>Source Files\soundlib\Module Loaders</Filter> </ClInclude> - <ClInclude Include="..\soundlib\FileReader.h"> - <Filter>Source Files\soundlib\Module Loaders</Filter> - </ClInclude> <ClInclude Include="..\soundlib\WAVTools.h"> <Filter>Source Files\soundlib\Module Loaders</Filter> </ClInclude> @@ -1053,6 +1050,9 @@ <ClInclude Include="CListCtrl.h"> <Filter>Header Files\mptrack</Filter> </ClInclude> + <ClInclude Include="..\common\FileReader.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/soundlib/ChunkReader.h =================================================================== --- trunk/OpenMPT/soundlib/ChunkReader.h 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/soundlib/ChunkReader.h 2014-12-13 09:59:22 UTC (rev 4645) @@ -10,7 +10,7 @@ #pragma once -#include "FileReader.h" +#include "../common/FileReader.h" #include <vector> Modified: trunk/OpenMPT/soundlib/Dlsbank.cpp =================================================================== --- trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-12-13 09:59:22 UTC (rev 4645) @@ -18,7 +18,7 @@ #include "Dlsbank.h" #include "Wav.h" #include "../common/StringFixer.h" -#include "../soundlib/FileReader.h" +#include "../common/FileReader.h" #include "../common/Endianness.h" #include "SampleIO.h" Deleted: trunk/OpenMPT/soundlib/FileReader.h =================================================================== --- trunk/OpenMPT/soundlib/FileReader.h 2014-12-12 10:51:53 UTC (rev 4644) +++ trunk/OpenMPT/soundlib/FileReader.h 2014-12-13 09:59:22 UTC (rev 4645) @@ -1,810 +0,0 @@ -/* - * FileReader.h - * ------------ - * Purpose: A basic class for transparent reading of memory-based files. - * Notes : (currently none) - * Authors: OpenMPT Devs - * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. - */ - - -#pragma once - - -#include "../common/typedefs.h" -#include "../common/StringFixer.h" -#include "../common/misc_util.h" -#include "../common/Endianness.h" -#include "../common/mptIO.h" -#include <algorithm> -#include <limits> -#include <vector> -#include <cstring> - - -OPENMPT_NAMESPACE_BEGIN - - -// change to show warnings for functions which trigger pre-caching the whole file for unseekable streams -//#define FILEREADER_DEPRECATED MPT_DEPRECATED -#define FILEREADER_DEPRECATED - - -//============== -class FileReader -//============== -{ - -public: - -#if defined(MPT_FILEREADER_STD_ISTREAM) - typedef IFileDataContainer::off_t off_t; -#else - typedef FileDataContainerMemory::off_t off_t; -#endif - -private: - -#if defined(MPT_FILEREADER_STD_ISTREAM) - const IFileDataContainer & DataContainer() const { return *data; } - IFileDataContainer & DataContainer() { return *data; } - MPT_SHARED_PTR<IFileDataContainer> data; -#else - const FileDataContainerMemory & DataContainer() const { return data; } - FileDataContainerMemory & DataContainer() { return data; } - FileDataContainerMemory data; -#endif - - off_t streamPos; // Cursor location in the file - -#if defined(MPT_WITH_FILEIO) - const mpt::PathString *fileName; // Filename that corresponds to this FileReader. It is only set if this FileReader represents the whole contents of fileName. May be nullptr. - #define MPT_FILEREADER_INIT_FILENAME ,fileName(nullptr) -#else // !MPT_WITH_FILEIO - #define MPT_FILEREADER_INIT_FILENAME -#endif // MPT_WITH_FILEIO - -public: - -#if defined(MPT_FILEREADER_STD_ISTREAM) - - // Initialize invalid file reader object. - FileReader() : data(mpt::make_shared<FileDataContainerDummy>()), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - - // Initialize file reader object with pointer to data and data length. - FileReader(const void *voiddata, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(static_cast<const char *>(voiddata), length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - FileReader(const char *chardata, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(chardata, length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - FileReader(const uint8 *uint8data, off_t length) : data(mpt::make_shared<FileDataContainerMemory>(reinterpret_cast<const char *>(uint8data), length)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } -#if defined(MPT_WITH_FILEIO) - FileReader(const void *voiddata, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(static_cast<const char *>(voiddata), length)), streamPos(0), fileName(filename) { } - FileReader(const char *chardata, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(chardata, length)), streamPos(0), fileName(filename) { } - FileReader(const uint8 *uint8data, off_t length, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerMemory>(reinterpret_cast<const char *>(uint8data), length)), streamPos(0), fileName(filename) { } -#endif // MPT_WITH_FILEIO - - // Initialize file reader object with a std::istream. - FileReader(std::istream *s) : data(mpt::make_shared<FileDataContainerStdStream>(s)), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } -#if defined(MPT_WITH_FILEIO) - FileReader(std::istream *s, const mpt::PathString *filename) : data(mpt::make_shared<FileDataContainerStdStream>(s)), streamPos(0), fileName(filename) { } -#endif // MPT_WITH_FILEIO - - // Initialize file reader object based on an existing file reader object window. - FileReader(MPT_SHARED_PTR<IFileDataContainer> other) : data(other), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - - // Initialize file reader object based on an existing file reader object. The other object's stream position is copied. - FileReader(const FileReader &other) : data(other.data), streamPos(other.streamPos) -#if defined(MPT_WITH_FILEIO) - , fileName(other.fileName) -#endif // MPT_WITH_FILEIO - { } - -#else // !MPT_FILEREADER_STD_ISTREAM - - // Initialize invalid file reader object. - FileReader() : data(nullptr, 0), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - - // Initialize file reader object with pointer to data and data length. - FileReader(const void *voiddata, off_t length) : data(static_cast<const char *>(voiddata), length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - FileReader(const char *chardata, off_t length) : data(chardata, length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } - FileReader(const uint8 *uint8data, off_t length) : data(reinterpret_cast<const char *>(uint8data), length), streamPos(0) MPT_FILEREADER_INIT_FILENAME { } -#if defined(MPT_WITH_FILEIO) - FileReader(const void *voiddata, off_t length, const mpt::PathString *filename) : data(static_cast<const char *>(voiddata), length), streamPos(0), fileName(filename) { } - FileReader(const char *chardata, off_t length, const mpt::PathString *filename) : data(chardata, length), streamPos(0), fileName(filename) { } - FileReader(const uint8 *uint8data, off_t length, const mpt::PathString *filename) : data(reinterpret_cast<const char *>(uint8data), length), streamPos(0), fileName(filename) { } -#endif // MPT_WITH_FILEIO - - // Initialize file reader object based on an existing file reader object. The other object's stream position is copied. - FileReader(const FileReader &other) : data(other.data), streamPos(other.streamPos) -#if defined(MPT_WITH_FILEIO) - , fileName(other.fileName) -#endif // MPT_WITH_FILEIO - { } - -#endif // MPT_FILEREADER_STD_ISTREAM - - -#if defined(MPT_WITH_FILEIO) - mpt::PathString GetFileName() const - { - if(!fileName) - { - return mpt::PathString(); - } - return *fileName; - } -#endif // MPT_WITH_FILEIO - - // Returns true if the object points to a valid stream. - bool IsValid() const - { - return DataContainer().IsValid(); - } - - // Reset cursor to first byte in file. - void Rewind() - { - streamPos = 0; - } - - // Seek to a position in the mapped file. - // Returns false if position is invalid. - bool Seek(off_t position) - { - if(position <= streamPos) - { - streamPos = position; - return true; - } - if(position <= DataContainer().GetLength()) - { - streamPos = position; - return true; - } else - { - return false; - } - } - - // Increases position by skipBytes. - // Returns true if skipBytes could be skipped or false if the file end was reached earlier. - bool Skip(off_t skipBytes) - { - if(CanRead(skipBytes)) - { - streamPos += skipBytes; - return true; - } else - { - streamPos = DataContainer().GetLength(); - return false; - } - } - - // Decreases position by skipBytes. - // Returns true if skipBytes could be skipped or false if the file start was reached earlier. - bool SkipBack(off_t skipBytes) - { - if(streamPos >= skipBytes) - { - streamPos -= skipBytes; - return true; - } else - { - streamPos = 0; - return false; - } - } - - // Returns cursor position in the mapped file. - off_t GetPosition() const - { - return streamPos; - } - - // Returns size of the mapped file in bytes. - FILEREADER_DEPRECATED off_t GetLength() const - { - // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file - return DataContainer().GetLength(); - } - - // Return byte count between cursor position and end of file, i.e. how many bytes can still be read. - FILEREADER_DEPRECATED off_t BytesLeft() const - { - // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file - return DataContainer().GetLength() - streamPos; - } - - bool AreBytesLeft() const - { - return CanRead(1); - } - - bool NoBytesLeft() const - { - return !CanRead(1); - } - - // Check if "amount" bytes can be read from the current position in the stream. - bool CanRead(off_t amount) const - { - return DataContainer().CanRead(streamPos, amount); - } - - // Create a new FileReader object for parsing a sub chunk at a given position with a given length. - // The file cursor is not modified. - FileReader GetChunk(off_t position, off_t length) const - { - off_t readableLength = DataContainer().GetReadableLength(position, length); - if(readableLength == 0) - { - return FileReader(); - } - #if defined(MPT_FILEREADER_STD_ISTREAM) - return FileReader(mpt::make_shared<FileDataContainerWindow>(data, position, std::min(length, DataContainer().GetLength() - position))); - #else - return FileReader(DataContainer().GetRawData() + position, std::min(length, DataContainer().GetLength() - position)); - #endif - } - - // Create a new FileReader object for parsing a sub chunk at the current position with a given length. - // The file cursor is advanced by "length" bytes. - FileReader ReadChunk(off_t length) - { - off_t position = streamPos; - Skip(length); - return GetChunk(position, length); - } - - // Returns raw stream data at cursor position. - // Should only be used if absolutely necessary, for example for sample reading. - FILEREADER_DEPRECATED const char *GetRawData() const - { - // deprecated because in case of an unseekable std::istream, this triggers caching of the whole file - return DataContainer().GetRawData() + streamPos; - } - - std::size_t ReadRaw(char *dst, std::size_t count) - { - std::size_t result = static_cast<std::size_t>(DataContainer().Read(dst, streamPos, count)); - streamPos += result; - return result; - } - -protected: - - // Read a "T" object from the stream. - // If not enough bytes can be read, false is returned. - // If successful, the file cursor is advanced by the size of "T". - template <typename T> - bool Read(T &target) - { - if(sizeof(T) != DataContainer().Read(reinterpret_cast<char*>(&target), streamPos, sizeof(T))) - { - return false; - } - streamPos += sizeof(T); - return true; - } - -public: - - // Read some kind of integer in little-endian format. - // If successful, the file cursor is advanced by the size of the integer. - template <typename T> - T ReadIntLE() - { - static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); - T target; - if(Read(target)) - { - return SwapBytesReturnLE(target); - } else - { - return 0; - } - } - - // Read some kind of integer in big-endian format. - // If successful, the file cursor is advanced by the size of the integer. - template <typename T> - T ReadIntBE() - { - static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); - T target; - if(Read(target)) - { - return SwapBytesReturnBE(target); - } else - { - return 0; - } - } - - // Read a integer in little-endian format which has some of its higher bytes not stored in file. - // If successful, the file cursor is advanced by the given size. - template <typename T> - T ReadTruncatedIntLE(off_t size) - { - static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); - MPT_ASSERT(sizeof(T) >= size); - if(size == 0) - { - return 0; - } - if(!CanRead(size)) - { - return 0; - } - uint8 buf[sizeof(T)]; - for(std::size_t i = 0; i < sizeof(T); ++i) - { - if(i < size) - { - Read(buf[i]); - } else - { - if(std::numeric_limits<T>::is_signed) - { - // sign extend - const bool negative = (i > 0) && ((buf[i-1] & 0x80) != 0x00); - buf[i] = negative ? 0xff : 0x00; - } else - { - // zero extend - buf[i] = 0x00; - } - } - } - T target; - std::memcpy(&target, buf, sizeof(T)); - return SwapBytesReturnLE(target); - } - - // Read a supplied-size little endian integer to a fixed size variable. - // The data is properly sign-extended when fewer bytes are stored. - // If more bytes are stored, higher order bytes are silently ignored. - // If successful, the file cursor is advanced by the given size. - template <typename T> - T ReadSizedIntLE(off_t size) - { - static_assert(std::numeric_limits<T>::is_integer == true, "Target type is a not an integer"); - if(size == 0) - { - return 0; - } - if(!CanRead(size)) - { - return 0; - } - if(size < sizeof(T)) - { - return ReadTruncatedIntLE<T>(size); - } - T retval = ReadIntLE<T>(); - Skip(size - sizeof(T)); - return retval; - } - - // Read unsigned 32-Bit integer in little-endian format. - // If successful, the file cursor is advanced by the size of the integer. - uint32 ReadUint32LE() - { - return ReadIntLE<uint32>(); - } - - // Read unsigned 32-Bit integer in big-endian format. - // If successful, the file cursor is advanced by the size of the integer. - uint32 ReadUint32BE() - { - return ReadIntBE<uint32>(); - } - - // Read signed 32-Bit integer in little-endian format. - // If successful, the file cursor is advanced by the size of the integer. - int32 ReadInt32LE() - { - return ReadIntLE<int32>(); - } - - // Read signed 32-Bit integer in big-endian format. - // If successful, the file cursor is advanced by the size of the integer. - int32 ReadInt32BE() - { - return ReadIntBE<int32>(); - } - - // Read unsigned 16-Bit integer in little-endian format. - // If successful, the file cursor is advanced by the size of the integer. - uint16 ReadUint16LE() - { - return ReadIntLE<uint16>(); - } - - // Read unsigned 16-Bit integer in big-endian format. - // If successful, the file cursor is advanced by the size of the integer. - uint16 ReadUint16BE() - { - return ReadIntBE<uint16>(); - } - - // Read signed 16-Bit integer in little-endian format. - // If successful, the file cursor is advanced by the size of the integer. - int16 ReadInt16LE() - { - return ReadIntLE<int16>(); - } - - // Read signed 16-Bit integer in big-endian format. - // If successful, the file cursor is advanced by the size of the integer. - int16 ReadInt16BE() - { - return ReadIntBE<int16>(); - } - - // Read unsigned 8-Bit integer. - // If successful, the file cursor is advanced by the size of the integer. - uint8 ReadUint8() - { - uint8 target; - if(Read(target)) - { - return target; - } else - { - return 0; - } - } - - // Read signed 8-Bit integer. If successful, the file cursor is advanced by the size of the integer. - int8 ReadInt8() - { - int8 target; - if(Read(target)) - { - return target; - } else - { - return 0; - } - } - - // Read 32-Bit float in little-endian format. - // If successful, the file cursor is advanced by the size of the float. - float ReadFloatLE() - { - IEEE754binary32LE target; - if(Read(target)) - { - return target; - } else - { - return 0.0f; - } - } - - // Read 32-Bit float in big-endian format. - // If successful, the file cursor is advanced by the size of the float. - float ReadFloatBE() - { - IEEE754binary32BE target; - if(Read(target)) - { - return target; - } else - { - return 0.0f; - } - } - - // Read 64-Bit float in little-endian format. - // If successful, the file cursor is advanced by the size of the float. - double ReadDoubleLE() - { - IEEE754binary64LE target; - if(Read(target)) - { - return target; - } else - { - return 0.0f; - } - } - - // Read 64-Bit float in big-endian format. - // If successful, the file cursor is advanced by the size of the float. - double ReadDoubleBE() - { - IEEE754binary64BE target; - if(Read(target)) - { - return target; - } else - { - return 0.0f; - } - } - - // Read a struct. - // If successful, the file cursor is advanced by the size of the struct. Otherwise, the target is zeroed. - template <typename T> - bool ReadStruct(T &target) - { - if(Read(target)) - { - return true; - } else - { - MemsetZero(target); - return false; - } - } - - // Allow to read a struct partially (if there's less memory available than the struct's size, fill it up with zeros). - // The file cursor is advanced by "partialSize" bytes. - template <typename T> - bool ReadStructPartial(T &target, off_t partialSize = sizeof(T)) - { - off_t copyBytes = std::min(partialSize, sizeof(T)); - if(!CanRead(copyBytes)) - { - copyBytes = BytesLeft(); - } - DataContainer().Read(reinterpret_cast<char *>(&target), streamPos, copyBytes); - memset(reinterpret_cast<char *>(&target) + copyBytes, 0, sizeof(target) - copyBytes); - Skip(partialSize); - return true; - } - - // Read a "T" object from the stream. - // If not enough bytes can be read, false is returned. - // If successful, the file cursor is advanced by the size of "T" and the object's "ConvertEndianness()" method is called. - template <typename T> - bool ReadConvertEndianness(T &target) - { - if(Read(target)) - { - target.ConvertEndianness(); - return true; - } else - { - return false; - } - } - - // Read a string of length srcSize into fixed-length char array destBuffer using a given read mode. - // The file cursor is advanced by "srcSize" bytes. - template<mpt::String::ReadWriteMode mode, off_t destSize> - bool ReadString(char (&destBuffer)[destSize], const off_t srcSize) - { - if(CanRead(srcSize)) - { - mpt::String::Read<mode, destSize>(destBuffer, DataContainer().GetPartialRawData(streamPos, srcSize), srcSize); - streamPos += srcSize; - return true; - } else - { - return false; - } - } - - // Read a string of length srcSize into a std::string dest using a given read mode. - // The file cursor is advanced by "srcSize" bytes. - template<mpt::String::ReadWriteMode mode> - bool ReadString(std::string &dest, const off_t srcSize) - { - if(CanRead(srcSize)) - { - mpt::String::Read<mode>(dest, DataContainer().GetPartialRawData(streamPos, srcSize), srcSize); - streamPos += srcSize; - return true; - } else - { - return false; - } - } - - // Read... [truncated message content] |