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
12 using namespace NWindows;
13 using namespace NFile;
14 using namespace NDir;
15
16 static const UInt32 kTempBufSize = (1 << 20);
17
18 static CFSTR kTempFilePrefixString = FTEXT("7zt");
19
CInOutTempBuffer()20 CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
21
Create()22 void CInOutTempBuffer::Create()
23 {
24 if (!_buf)
25 _buf = new Byte[kTempBufSize];
26 }
27
~CInOutTempBuffer()28 CInOutTempBuffer::~CInOutTempBuffer()
29 {
30 delete []_buf;
31 }
32
InitWriting()33 void CInOutTempBuffer::InitWriting()
34 {
35 _bufPos = 0;
36 _tempFileCreated = false;
37 _size = 0;
38 _crc = CRC_INIT_VAL;
39 }
40
WriteToFile(const void * data,UInt32 size)41 bool 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
Write(const void * data,UInt32 size)59 bool 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
WriteToStream(ISequentialOutStream * stream)74 HRESULT 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
Write(const void * data,UInt32 size,UInt32 * processed)108 STDMETHODIMP 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