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