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