summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp
blob: be65ba32ff03882f06c7493d9557d5d68cf8e3b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// InOutTempBuffer.cpp

#include "StdAfx.h"

#include "../../../C/7zCrc.h"

#include "../../Common/Defs.h"

#include "InOutTempBuffer.h"
#include "StreamUtils.h"

using namespace NWindows;
using namespace NFile;
using namespace NDir;

static const UInt32 kTempBufSize = (1 << 20);

static CFSTR kTempFilePrefixString = FTEXT("7zt");

CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }

void CInOutTempBuffer::Create()
{
  if (!_buf)
    _buf = new Byte[kTempBufSize];
}

CInOutTempBuffer::~CInOutTempBuffer()
{
  delete []_buf;
}

void CInOutTempBuffer::InitWriting()
{
  _bufPos = 0;
  _tempFileCreated = false;
  _size = 0;
  _crc = CRC_INIT_VAL;
}

bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
{
  if (size == 0)
    return true;
  if (!_tempFileCreated)
  {
    if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
      return false;
    _tempFileCreated = true;
  }
  UInt32 processed;
  if (!_outFile.Write(data, size, processed))
    return false;
  _crc = CrcUpdate(_crc, data, processed);
  _size += processed;
  return (processed == size);
}

bool CInOutTempBuffer::Write(const void *data, UInt32 size)
{
  if (_bufPos < kTempBufSize)
  {
    UInt32 cur = MyMin(kTempBufSize - _bufPos, size);
    memcpy(_buf + _bufPos, data, cur);
    _crc = CrcUpdate(_crc, data, cur);
    _bufPos += cur;
    size -= cur;
    data = ((const Byte *)data) + cur;
    _size += cur;
  }
  return WriteToFile(data, size);
}

HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
{
  if (!_outFile.Close())
    return E_FAIL;

  UInt64 size = 0;
  UInt32 crc = CRC_INIT_VAL;

  if (_bufPos > 0)
  {
    RINOK(WriteStream(stream, _buf, _bufPos));
    crc = CrcUpdate(crc, _buf, _bufPos);
    size += _bufPos;
  }
  if (_tempFileCreated)
  {
    NIO::CInFile inFile;
    if (!inFile.Open(_tempFile.GetPath()))
      return E_FAIL;
    while (size < _size)
    {
      UInt32 processed;
      if (!inFile.ReadPart(_buf, kTempBufSize, processed))
        return E_FAIL;
      if (processed == 0)
        break;
      RINOK(WriteStream(stream, _buf, processed));
      crc = CrcUpdate(crc, _buf, processed);
      size += processed;
    }
  }
  return (_crc == crc && size == _size) ? S_OK : E_FAIL;
}

STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
{
  if (!_buf->Write(data, size))
  {
    if (processed != NULL)
      *processed = 0;
    return E_FAIL;
  }
  if (processed != NULL)
    *processed = size;
  return S_OK;
}