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
12using namespace NWindows;
13using namespace NFile;
14using namespace NDir;
15
16static const UInt32 kTempBufSize = (1 << 20);
17
18static CFSTR kTempFilePrefixString = FTEXT("7zt");
19
20CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
21
22void CInOutTempBuffer::Create()
23{
24  if (!_buf)
25    _buf = new Byte[kTempBufSize];
26}
27
28CInOutTempBuffer::~CInOutTempBuffer()
29{
30  delete []_buf;
31}
32
33void CInOutTempBuffer::InitWriting()
34{
35  _bufPos = 0;
36  _tempFileCreated = false;
37  _size = 0;
38  _crc = CRC_INIT_VAL;
39}
40
41bool 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
59bool 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
74HRESULT 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
108STDMETHODIMP 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