1 // CWrappers.h
2
3 #include "StdAfx.h"
4
5 #include "../../../C/Alloc.h"
6
7 #include "CWrappers.h"
8
9 #include "StreamUtils.h"
10
HRESULT_To_SRes(HRESULT res,SRes defaultRes)11 SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
12 {
13 switch (res)
14 {
15 case S_OK: return SZ_OK;
16 case E_OUTOFMEMORY: return SZ_ERROR_MEM;
17 case E_INVALIDARG: return SZ_ERROR_PARAM;
18 case E_ABORT: return SZ_ERROR_PROGRESS;
19 case S_FALSE: return SZ_ERROR_DATA;
20 case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
21 }
22 return defaultRes;
23 }
24
25
SResToHRESULT(SRes res)26 HRESULT SResToHRESULT(SRes res) throw()
27 {
28 switch (res)
29 {
30 case SZ_OK: return S_OK;
31
32 case SZ_ERROR_DATA:
33 case SZ_ERROR_CRC:
34 case SZ_ERROR_INPUT_EOF:
35 return S_FALSE;
36
37 case SZ_ERROR_MEM: return E_OUTOFMEMORY;
38 case SZ_ERROR_PARAM: return E_INVALIDARG;
39 case SZ_ERROR_PROGRESS: return E_ABORT;
40 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
41 // case SZ_ERROR_OUTPUT_EOF:
42 // case SZ_ERROR_READ:
43 // case SZ_ERROR_WRITE:
44 // case SZ_ERROR_THREAD:
45 // case SZ_ERROR_ARCHIVE:
46 // case SZ_ERROR_NO_ARCHIVE:
47 // return E_FAIL;
48 }
49 if (res < 0)
50 return res;
51 return E_FAIL;
52 }
53
54
55 #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)
56
57 #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
58
59
CompressProgress(const ICompressProgress * pp,UInt64 inSize,UInt64 outSize)60 static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
61 {
62 CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
63 p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
64 return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
65 }
66
Init(ICompressProgressInfo * progress)67 void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
68 {
69 vt.Progress = CompressProgress;
70 Progress = progress;
71 Res = SZ_OK;
72 }
73
74 static const UInt32 kStreamStepSize = (UInt32)1 << 31;
75
MyRead(const ISeqInStream * pp,void * data,size_t * size)76 static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
77 {
78 CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
79 UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
80 p->Res = (p->Stream->Read(data, curSize, &curSize));
81 *size = curSize;
82 p->Processed += curSize;
83 if (p->Res == S_OK)
84 return SZ_OK;
85 return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);
86 }
87
MyWrite(const ISeqOutStream * pp,const void * data,size_t size)88 static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw()
89 {
90 CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
91 if (p->Stream)
92 {
93 p->Res = WriteStream(p->Stream, data, size);
94 if (p->Res != 0)
95 return 0;
96 }
97 else
98 p->Res = S_OK;
99 p->Processed += size;
100 return size;
101 }
102
103
Init(ISequentialInStream * stream)104 void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()
105 {
106 vt.Read = MyRead;
107 Stream = stream;
108 Processed = 0;
109 Res = S_OK;
110 }
111
Init(ISequentialOutStream * stream)112 void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
113 {
114 vt.Write = MyWrite;
115 Stream = stream;
116 Res = SZ_OK;
117 Processed = 0;
118 }
119
120
InStreamWrap_Read(const ISeekInStream * pp,void * data,size_t * size)121 static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
122 {
123 CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
124 UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
125 p->Res = p->Stream->Read(data, curSize, &curSize);
126 *size = curSize;
127 return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
128 }
129
InStreamWrap_Seek(const ISeekInStream * pp,Int64 * offset,ESzSeek origin)130 static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
131 {
132 CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
133 UInt32 moveMethod;
134 switch (origin)
135 {
136 case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;
137 case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;
138 case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break;
139 default: return SZ_ERROR_PARAM;
140 }
141 UInt64 newPosition;
142 p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition);
143 *offset = (Int64)newPosition;
144 return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
145 }
146
Init(IInStream * stream)147 void CSeekInStreamWrap::Init(IInStream *stream) throw()
148 {
149 Stream = stream;
150 vt.Read = InStreamWrap_Read;
151 vt.Seek = InStreamWrap_Seek;
152 Res = S_OK;
153 }
154
155
156 /* ---------- CByteInBufWrap ---------- */
157
Free()158 void CByteInBufWrap::Free() throw()
159 {
160 ::MidFree(Buf);
161 Buf = 0;
162 }
163
Alloc(UInt32 size)164 bool CByteInBufWrap::Alloc(UInt32 size) throw()
165 {
166 if (Buf == 0 || size != Size)
167 {
168 Free();
169 Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);
170 Size = size;
171 }
172 return (Buf != 0);
173 }
174
ReadByteFromNewBlock()175 Byte CByteInBufWrap::ReadByteFromNewBlock() throw()
176 {
177 if (Res == S_OK)
178 {
179 UInt32 avail;
180 Processed += (Cur - Buf);
181 Res = Stream->Read(Buf, Size, &avail);
182 Cur = Buf;
183 Lim = Buf + avail;
184 if (avail != 0)
185 return *Cur++;
186 }
187 Extra = true;
188 return 0;
189 }
190
Wrap_ReadByte(const IByteIn * pp)191 static Byte Wrap_ReadByte(const IByteIn *pp) throw()
192 {
193 CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
194 if (p->Cur != p->Lim)
195 return *p->Cur++;
196 return p->ReadByteFromNewBlock();
197 }
198
CByteInBufWrap()199 CByteInBufWrap::CByteInBufWrap(): Buf(0)
200 {
201 vt.Read = Wrap_ReadByte;
202 }
203
204
205 /* ---------- CByteOutBufWrap ---------- */
206
Free()207 void CByteOutBufWrap::Free() throw()
208 {
209 ::MidFree(Buf);
210 Buf = 0;
211 }
212
Alloc(size_t size)213 bool CByteOutBufWrap::Alloc(size_t size) throw()
214 {
215 if (Buf == 0 || size != Size)
216 {
217 Free();
218 Buf = (Byte *)::MidAlloc(size);
219 Size = size;
220 }
221 return (Buf != 0);
222 }
223
Flush()224 HRESULT CByteOutBufWrap::Flush() throw()
225 {
226 if (Res == S_OK)
227 {
228 size_t size = (Cur - Buf);
229 Res = WriteStream(Stream, Buf, size);
230 if (Res == S_OK)
231 Processed += size;
232 Cur = Buf;
233 }
234 return Res;
235 }
236
Wrap_WriteByte(const IByteOut * pp,Byte b)237 static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw()
238 {
239 CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
240 Byte *dest = p->Cur;
241 *dest = b;
242 p->Cur = ++dest;
243 if (dest == p->Lim)
244 p->Flush();
245 }
246
CByteOutBufWrap()247 CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)
248 {
249 vt.Write = Wrap_WriteByte;
250 }
251