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