// InOutTempBuffer.cpp | |
#include "StdAfx.h" | |
#include "../../../C/7zCrc.h" | |
#include "../../Common/Defs.h" | |
#include "InOutTempBuffer.h" | |
#include "StreamUtils.h" | |
using namespace NWindows; | |
using namespace NFile; | |
using namespace NDir; | |
static const UInt32 kTempBufSize = (1 << 20); | |
static CFSTR kTempFilePrefixString = FTEXT("7zt"); | |
CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } | |
void CInOutTempBuffer::Create() | |
{ | |
if (!_buf) | |
_buf = new Byte[kTempBufSize]; | |
} | |
CInOutTempBuffer::~CInOutTempBuffer() | |
{ | |
delete []_buf; | |
} | |
void CInOutTempBuffer::InitWriting() | |
{ | |
_bufPos = 0; | |
_tempFileCreated = false; | |
_size = 0; | |
_crc = CRC_INIT_VAL; | |
} | |
bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) | |
{ | |
if (size == 0) | |
return true; | |
if (!_tempFileCreated) | |
{ | |
if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) | |
return false; | |
_tempFileCreated = true; | |
} | |
UInt32 processed; | |
if (!_outFile.Write(data, size, processed)) | |
return false; | |
_crc = CrcUpdate(_crc, data, processed); | |
_size += processed; | |
return (processed == size); | |
} | |
bool CInOutTempBuffer::Write(const void *data, UInt32 size) | |
{ | |
if (_bufPos < kTempBufSize) | |
{ | |
UInt32 cur = MyMin(kTempBufSize - _bufPos, size); | |
memcpy(_buf + _bufPos, data, cur); | |
_crc = CrcUpdate(_crc, data, cur); | |
_bufPos += cur; | |
size -= cur; | |
data = ((const Byte *)data) + cur; | |
_size += cur; | |
} | |
return WriteToFile(data, size); | |
} | |
HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) | |
{ | |
if (!_outFile.Close()) | |
return E_FAIL; | |
UInt64 size = 0; | |
UInt32 crc = CRC_INIT_VAL; | |
if (_bufPos > 0) | |
{ | |
RINOK(WriteStream(stream, _buf, _bufPos)); | |
crc = CrcUpdate(crc, _buf, _bufPos); | |
size += _bufPos; | |
} | |
if (_tempFileCreated) | |
{ | |
NIO::CInFile inFile; | |
if (!inFile.Open(_tempFile.GetPath())) | |
return E_FAIL; | |
while (size < _size) | |
{ | |
UInt32 processed; | |
if (!inFile.ReadPart(_buf, kTempBufSize, processed)) | |
return E_FAIL; | |
if (processed == 0) | |
break; | |
RINOK(WriteStream(stream, _buf, processed)); | |
crc = CrcUpdate(crc, _buf, processed); | |
size += processed; | |
} | |
} | |
return (_crc == crc && size == _size) ? S_OK : E_FAIL; | |
} | |
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed) | |
{ | |
if (!_buf->Write(data, size)) | |
{ | |
if (processed != NULL) | |
*processed = 0; | |
return E_FAIL; | |
} | |
if (processed != NULL) | |
*processed = size; | |
return S_OK; | |
} |