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