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