1 // InOutTempBuffer.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/7zCrc.h"
6
7 #include "InOutTempBuffer.h"
8 #include "StreamUtils.h"
9
10 using namespace NWindows;
11 using namespace NFile;
12 using namespace NDirectory;
13
14 static const UInt32 kTempBufSize = (1 << 20);
15
16 static LPCTSTR kTempFilePrefixString = TEXT("7zt");
17
CInOutTempBuffer()18 CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
19
Create()20 void CInOutTempBuffer::Create()
21 {
22 if (!_buf)
23 _buf = new Byte[kTempBufSize];
24 }
25
~CInOutTempBuffer()26 CInOutTempBuffer::~CInOutTempBuffer()
27 {
28 delete []_buf;
29 }
30
InitWriting()31 void CInOutTempBuffer::InitWriting()
32 {
33 _bufPos = 0;
34 _tempFileCreated = false;
35 _size = 0;
36 _crc = CRC_INIT_VAL;
37 }
38
WriteToFile(const void * data,UInt32 size)39 bool 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
Write(const void * data,UInt32 size)62 bool 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
WriteToStream(ISequentialOutStream * stream)77 HRESULT 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
Write(const void * data,UInt32 size,UInt32 * processed)111 STDMETHODIMP 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