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