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