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