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