1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// InOutTempBuffer.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../C/7zCrc.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "InOutTempBuffer.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StreamUtils.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
11baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NFile;
12baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NDirectory;
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
14baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kTempBufSize = (1 << 20);
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic LPCTSTR kTempFilePrefixString = TEXT("7zt");
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
20baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CInOutTempBuffer::Create()
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_buf)
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _buf = new Byte[kTempBufSize];
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
26baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCInOutTempBuffer::~CInOutTempBuffer()
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  delete []_buf;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
31baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CInOutTempBuffer::InitWriting()
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bufPos = 0;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _tempFileCreated = false;
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _size = 0;
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _crc = CRC_INIT_VAL;
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
39baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size == 0)
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return true;
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_tempFileCreated)
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSysString tempDirPath;
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!MyGetTempPath(tempDirPath))
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0)
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!_outFile.Create(_tempFileName, true))
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _tempFileCreated = true;
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 processed;
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_outFile.Write(data, size, processed))
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _crc = CrcUpdate(_crc, data, processed);
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _size += processed;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (processed == size);
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
62baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CInOutTempBuffer::Write(const void *data, UInt32 size)
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_bufPos < kTempBufSize)
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 cur = MyMin(kTempBufSize - _bufPos, size);
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    memcpy(_buf + _bufPos, data, cur);
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _crc = CrcUpdate(_crc, data, cur);
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bufPos += cur;
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size -= cur;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    data = ((const Byte *)data) + cur;
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _size += cur;
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return WriteToFile(data, size);
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
77baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_outFile.Close())
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 size = 0;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 crc = CRC_INIT_VAL;
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_bufPos > 0)
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(WriteStream(stream, _buf, _bufPos));
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    crc = CrcUpdate(crc, _buf, _bufPos);
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size += _bufPos;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_tempFileCreated)
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NIO::CInFile inFile;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!inFile.Open(_tempFileName))
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    while (size < _size)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 processed;
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!inFile.ReadPart(_buf, kTempBufSize, processed))
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (processed == 0)
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(WriteStream(stream, _buf, processed));
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      crc = CrcUpdate(crc, _buf, processed);
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      size += processed;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (_crc == crc && size == _size) ? S_OK : E_FAIL;
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
111baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_buf->Write(data, size))
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (processed != NULL)
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      *processed = 0;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processed != NULL)
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processed = size;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
123