1// InOutTempBuffer.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/7zCrc.h"
6
7#include "InOutTempBuffer.h"
8#include "StreamUtils.h"
9
10using namespace NWindows;
11using namespace NFile;
12using namespace NDirectory;
13
14static const UInt32 kTempBufSize = (1 << 20);
15
16static LPCTSTR kTempFilePrefixString = TEXT("7zt");
17
18CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
19
20void CInOutTempBuffer::Create()
21{
22  if (!_buf)
23    _buf = new Byte[kTempBufSize];
24}
25
26CInOutTempBuffer::~CInOutTempBuffer()
27{
28  delete []_buf;
29}
30
31void CInOutTempBuffer::InitWriting()
32{
33  _bufPos = 0;
34  _tempFileCreated = false;
35  _size = 0;
36  _crc = CRC_INIT_VAL;
37}
38
39bool 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
62bool 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
77HRESULT 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
111STDMETHODIMP 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