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