annotate src/win32/7zip/7z/CPP/7zip/Common/OutMemStream.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
rev   line source
rlm@1 1 // OutMemStream.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "OutMemStream.h"
rlm@1 6
rlm@1 7 void COutMemStream::Free()
rlm@1 8 {
rlm@1 9 Blocks.Free(_memManager);
rlm@1 10 Blocks.LockMode = true;
rlm@1 11 }
rlm@1 12
rlm@1 13 void COutMemStream::Init()
rlm@1 14 {
rlm@1 15 WriteToRealStreamEvent.Reset();
rlm@1 16 _unlockEventWasSent = false;
rlm@1 17 _realStreamMode = false;
rlm@1 18 Free();
rlm@1 19 _curBlockPos = 0;
rlm@1 20 _curBlockIndex = 0;
rlm@1 21 }
rlm@1 22
rlm@1 23 void COutMemStream::DetachData(CMemLockBlocks &blocks)
rlm@1 24 {
rlm@1 25 Blocks.Detach(blocks, _memManager);
rlm@1 26 Free();
rlm@1 27 }
rlm@1 28
rlm@1 29
rlm@1 30 HRESULT COutMemStream::WriteToRealStream()
rlm@1 31 {
rlm@1 32 RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));
rlm@1 33 Blocks.Free(_memManager);
rlm@1 34 return S_OK;
rlm@1 35 }
rlm@1 36
rlm@1 37 STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
rlm@1 38 {
rlm@1 39 if (_realStreamMode)
rlm@1 40 return OutSeqStream->Write(data, size, processedSize);
rlm@1 41 if (processedSize != 0)
rlm@1 42 *processedSize = 0;
rlm@1 43 while(size != 0)
rlm@1 44 {
rlm@1 45 if ((int)_curBlockIndex < Blocks.Blocks.Size())
rlm@1 46 {
rlm@1 47 Byte *p = (Byte *)Blocks.Blocks[(int)_curBlockIndex] + _curBlockPos;
rlm@1 48 size_t curSize = _memManager->GetBlockSize() - _curBlockPos;
rlm@1 49 if (size < curSize)
rlm@1 50 curSize = size;
rlm@1 51 memmove(p, data, curSize);
rlm@1 52 if (processedSize != 0)
rlm@1 53 *processedSize += (UInt32)curSize;
rlm@1 54 data = (const void *)((const Byte *)data + curSize);
rlm@1 55 size -= (UInt32)curSize;
rlm@1 56 _curBlockPos += curSize;
rlm@1 57
rlm@1 58 UInt64 pos64 = GetPos();
rlm@1 59 if (pos64 > Blocks.TotalSize)
rlm@1 60 Blocks.TotalSize = pos64;
rlm@1 61 if (_curBlockPos == _memManager->GetBlockSize())
rlm@1 62 {
rlm@1 63 _curBlockIndex++;
rlm@1 64 _curBlockPos = 0;
rlm@1 65 }
rlm@1 66 continue;
rlm@1 67 }
rlm@1 68 HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore };
rlm@1 69 DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE);
rlm@1 70 switch (waitResult)
rlm@1 71 {
rlm@1 72 case (WAIT_OBJECT_0 + 0):
rlm@1 73 return StopWriteResult;
rlm@1 74 case (WAIT_OBJECT_0 + 1):
rlm@1 75 {
rlm@1 76 _realStreamMode = true;
rlm@1 77 RINOK(WriteToRealStream());
rlm@1 78 UInt32 processedSize2;
rlm@1 79 HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
rlm@1 80 if (processedSize != 0)
rlm@1 81 *processedSize += processedSize2;
rlm@1 82 return res;
rlm@1 83 }
rlm@1 84 /*
rlm@1 85 case (WAIT_OBJECT_0 + 2):
rlm@1 86 {
rlm@1 87 // it has bug: no write.
rlm@1 88 if (!Blocks.SwitchToNoLockMode(_memManager))
rlm@1 89 return E_FAIL;
rlm@1 90 break;
rlm@1 91 }
rlm@1 92 */
rlm@1 93 case (WAIT_OBJECT_0 + 2):
rlm@1 94 break;
rlm@1 95 default:
rlm@1 96 return E_FAIL;
rlm@1 97 }
rlm@1 98 Blocks.Blocks.Add(_memManager->AllocateBlock());
rlm@1 99 if (Blocks.Blocks.Back() == 0)
rlm@1 100 return E_FAIL;
rlm@1 101 }
rlm@1 102 return S_OK;
rlm@1 103 }
rlm@1 104
rlm@1 105 STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
rlm@1 106 {
rlm@1 107 if (_realStreamMode)
rlm@1 108 {
rlm@1 109 if (!OutStream)
rlm@1 110 return E_FAIL;
rlm@1 111 return OutStream->Seek(offset, seekOrigin, newPosition);
rlm@1 112 }
rlm@1 113 if (seekOrigin == STREAM_SEEK_CUR)
rlm@1 114 {
rlm@1 115 if (offset != 0)
rlm@1 116 return E_NOTIMPL;
rlm@1 117 }
rlm@1 118 else if (seekOrigin == STREAM_SEEK_SET)
rlm@1 119 {
rlm@1 120 if (offset != 0)
rlm@1 121 return E_NOTIMPL;
rlm@1 122 _curBlockIndex = 0;
rlm@1 123 _curBlockPos = 0;
rlm@1 124 }
rlm@1 125 else
rlm@1 126 return E_NOTIMPL;
rlm@1 127 if (newPosition != 0)
rlm@1 128 *newPosition = GetPos();
rlm@1 129 return S_OK;
rlm@1 130 }
rlm@1 131
rlm@1 132 STDMETHODIMP COutMemStream::SetSize(Int64 newSize)
rlm@1 133 {
rlm@1 134 if (_realStreamMode)
rlm@1 135 {
rlm@1 136 if (!OutStream)
rlm@1 137 return E_FAIL;
rlm@1 138 return OutStream->SetSize(newSize);
rlm@1 139 }
rlm@1 140 Blocks.TotalSize = newSize;
rlm@1 141 return S_OK;
rlm@1 142 }