1// InOutTempBuffer.cpp 2 3#include "StdAfx.h" 4 5#include "../../../C/7zCrc.h" 6 7#include "../../Common/Defs.h" 8 9#include "InOutTempBuffer.h" 10#include "StreamUtils.h" 11 12using namespace NWindows; 13using namespace NFile; 14using namespace NDir; 15 16static const UInt32 kTempBufSize = (1 << 20); 17 18static CFSTR kTempFilePrefixString = FTEXT("7zt"); 19 20CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } 21 22void CInOutTempBuffer::Create() 23{ 24 if (!_buf) 25 _buf = new Byte[kTempBufSize]; 26} 27 28CInOutTempBuffer::~CInOutTempBuffer() 29{ 30 delete []_buf; 31} 32 33void CInOutTempBuffer::InitWriting() 34{ 35 _bufPos = 0; 36 _tempFileCreated = false; 37 _size = 0; 38 _crc = CRC_INIT_VAL; 39} 40 41bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) 42{ 43 if (size == 0) 44 return true; 45 if (!_tempFileCreated) 46 { 47 if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) 48 return false; 49 _tempFileCreated = true; 50 } 51 UInt32 processed; 52 if (!_outFile.Write(data, size, processed)) 53 return false; 54 _crc = CrcUpdate(_crc, data, processed); 55 _size += processed; 56 return (processed == size); 57} 58 59bool CInOutTempBuffer::Write(const void *data, UInt32 size) 60{ 61 if (_bufPos < kTempBufSize) 62 { 63 UInt32 cur = MyMin(kTempBufSize - _bufPos, size); 64 memcpy(_buf + _bufPos, data, cur); 65 _crc = CrcUpdate(_crc, data, cur); 66 _bufPos += cur; 67 size -= cur; 68 data = ((const Byte *)data) + cur; 69 _size += cur; 70 } 71 return WriteToFile(data, size); 72} 73 74HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) 75{ 76 if (!_outFile.Close()) 77 return E_FAIL; 78 79 UInt64 size = 0; 80 UInt32 crc = CRC_INIT_VAL; 81 82 if (_bufPos > 0) 83 { 84 RINOK(WriteStream(stream, _buf, _bufPos)); 85 crc = CrcUpdate(crc, _buf, _bufPos); 86 size += _bufPos; 87 } 88 if (_tempFileCreated) 89 { 90 NIO::CInFile inFile; 91 if (!inFile.Open(_tempFile.GetPath())) 92 return E_FAIL; 93 while (size < _size) 94 { 95 UInt32 processed; 96 if (!inFile.ReadPart(_buf, kTempBufSize, processed)) 97 return E_FAIL; 98 if (processed == 0) 99 break; 100 RINOK(WriteStream(stream, _buf, processed)); 101 crc = CrcUpdate(crc, _buf, processed); 102 size += processed; 103 } 104 } 105 return (_crc == crc && size == _size) ? S_OK : E_FAIL; 106} 107 108STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed) 109{ 110 if (!_buf->Write(data, size)) 111 { 112 if (processed != NULL) 113 *processed = 0; 114 return E_FAIL; 115 } 116 if (processed != NULL) 117 *processed = size; 118 return S_OK; 119} 120