154 lines
3.4 KiB
C++
154 lines
3.4 KiB
C++
/*
|
|
* FileReader.cpp
|
|
* --------------
|
|
* 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.
|
|
*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "FileReader.h"
|
|
|
|
#if defined(MPT_ENABLE_TEMPFILE) && MPT_OS_WINDOWS
|
|
#include <windows.h>
|
|
#include "mptFileIO.h"
|
|
#include <stdexcept>
|
|
#endif // MPT_ENABLE_TEMPFILE && MPT_OS_WINDOWS
|
|
|
|
|
|
OPENMPT_NAMESPACE_BEGIN
|
|
|
|
|
|
#if defined(MPT_ENABLE_TEMPFILE) && MPT_OS_WINDOWS
|
|
|
|
|
|
OnDiskFileWrapper::OnDiskFileWrapper(FileReader &file, const mpt::PathString &fileNameExtension)
|
|
: m_IsTempFile(false)
|
|
{
|
|
try
|
|
{
|
|
file.Rewind();
|
|
if(file.GetFileName().empty())
|
|
{
|
|
const mpt::PathString tempName = mpt::CreateTempFileName(P_("OpenMPT"), fileNameExtension);
|
|
|
|
#if MPT_OS_WINDOWS && MPT_OS_WINDOWS_WINRT
|
|
#if (_WIN32_WINNT < 0x0602)
|
|
#define MPT_ONDISKFILEWRAPPER_NO_CREATEFILE
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MPT_ONDISKFILEWRAPPER_NO_CREATEFILE
|
|
|
|
mpt::ofstream f(tempName, std::ios::binary);
|
|
if(!f)
|
|
{
|
|
throw std::runtime_error("");
|
|
}
|
|
while(!file.EndOfFile())
|
|
{
|
|
FileReader::PinnedRawDataView view = file.ReadPinnedRawDataView(mpt::IO::BUFFERSIZE_NORMAL);
|
|
std::size_t towrite = view.size();
|
|
std::size_t written = 0;
|
|
do
|
|
{
|
|
std::size_t chunkSize = mpt::saturate_cast<std::size_t>(towrite);
|
|
bool chunkOk = false;
|
|
chunkOk = mpt::IO::WriteRaw(f, mpt::const_byte_span(view.data() + written, chunkSize));
|
|
if(!chunkOk)
|
|
{
|
|
throw std::runtime_error("");
|
|
}
|
|
towrite -= chunkSize;
|
|
written += chunkSize;
|
|
} while(towrite > 0);
|
|
}
|
|
f.close();
|
|
|
|
#else // !MPT_ONDISKFILEWRAPPER_NO_CREATEFILE
|
|
|
|
HANDLE hFile = NULL;
|
|
#if MPT_OS_WINDOWS_WINRT
|
|
hFile = CreateFile2(tempName.AsNative().c_str(), GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, NULL);
|
|
#else
|
|
hFile = CreateFile(tempName.AsNative().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
|
#endif
|
|
if(hFile == NULL || hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
throw std::runtime_error("");
|
|
}
|
|
while(!file.EndOfFile())
|
|
{
|
|
FileReader::PinnedRawDataView view = file.ReadPinnedRawDataView(mpt::IO::BUFFERSIZE_NORMAL);
|
|
std::size_t towrite = view.size();
|
|
std::size_t written = 0;
|
|
do
|
|
{
|
|
DWORD chunkSize = mpt::saturate_cast<DWORD>(towrite);
|
|
DWORD chunkDone = 0;
|
|
WriteFile(hFile, view.data() + written, chunkSize, &chunkDone, NULL);
|
|
if(chunkDone != chunkSize)
|
|
{
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
throw std::runtime_error("");
|
|
}
|
|
towrite -= chunkDone;
|
|
written += chunkDone;
|
|
} while(towrite > 0);
|
|
}
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
|
|
#endif // MPT_ONDISKFILEWRAPPER_NO_CREATEFILE
|
|
|
|
m_Filename = tempName;
|
|
m_IsTempFile = true;
|
|
} else
|
|
{
|
|
m_Filename = file.GetFileName();
|
|
}
|
|
} catch (const std::runtime_error &)
|
|
{
|
|
m_IsTempFile = false;
|
|
m_Filename = mpt::PathString();
|
|
}
|
|
}
|
|
|
|
|
|
OnDiskFileWrapper::~OnDiskFileWrapper()
|
|
{
|
|
if(m_IsTempFile)
|
|
{
|
|
DeleteFile(m_Filename.AsNative().c_str());
|
|
m_IsTempFile = false;
|
|
}
|
|
m_Filename = mpt::PathString();
|
|
}
|
|
|
|
|
|
bool OnDiskFileWrapper::IsValid() const
|
|
{
|
|
return !m_Filename.empty();
|
|
}
|
|
|
|
|
|
mpt::PathString OnDiskFileWrapper::GetFilename() const
|
|
{
|
|
return m_Filename;
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
|
|
MPT_MSVC_WORKAROUND_LNK4221(FileReader)
|
|
|
|
|
|
#endif // MPT_ENABLE_TEMPFILE && MPT_OS_WINDOWS
|
|
|
|
|
|
OPENMPT_NAMESPACE_END
|