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 }
|