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 size_t 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 (size == 0)
62 return true;
63 size_t cur = kTempBufSize - _bufPos;
64 if (cur != 0)
65 {
66 if (cur > size)
67 cur = size;
68 memcpy(_buf + _bufPos, data, cur);
69 _crc = CrcUpdate(_crc, data, cur);
70 _bufPos += cur;
71 _size += cur;
72 size -= (UInt32)cur;
73 data = ((const Byte *)data) + cur;
74 }
75 return WriteToFile(data, size);
76 }
77
WriteToStream(ISequentialOutStream * stream)78 HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
79 {
80 if (!_outFile.Close())
81 return E_FAIL;
82
83 UInt64 size = 0;
84 UInt32 crc = CRC_INIT_VAL;
85
86 if (_bufPos != 0)
87 {
88 RINOK(WriteStream(stream, _buf, _bufPos));
89 crc = CrcUpdate(crc, _buf, _bufPos);
90 size += _bufPos;
91 }
92
93 if (_tempFileCreated)
94 {
95 NIO::CInFile inFile;
96 if (!inFile.Open(_tempFile.GetPath()))
97 return E_FAIL;
98 while (size < _size)
99 {
100 UInt32 processed;
101 if (!inFile.ReadPart(_buf, kTempBufSize, processed))
102 return E_FAIL;
103 if (processed == 0)
104 break;
105 RINOK(WriteStream(stream, _buf, processed));
106 crc = CrcUpdate(crc, _buf, processed);
107 size += processed;
108 }
109 }
110
111 return (_crc == crc && size == _size) ? S_OK : E_FAIL;
112 }
113
114 /*
115 STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
116 {
117 if (!_buf->Write(data, size))
118 {
119 if (processed)
120 *processed = 0;
121 return E_FAIL;
122 }
123 if (processed)
124 *processed = size;
125 return S_OK;
126 }
127 */
128