CWrappers.cpp (5918B)
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 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 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 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 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 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 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 104 void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw() 105 { 106 vt.Read = MyRead; 107 Stream = stream; 108 Processed = 0; 109 Res = S_OK; 110 } 111 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 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 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 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 158 void CByteInBufWrap::Free() throw() 159 { 160 ::MidFree(Buf); 161 Buf = 0; 162 } 163 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 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 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 199 CByteInBufWrap::CByteInBufWrap(): Buf(0) 200 { 201 vt.Read = Wrap_ReadByte; 202 } 203 204 205 /* ---------- CByteOutBufWrap ---------- */ 206 207 void CByteOutBufWrap::Free() throw() 208 { 209 ::MidFree(Buf); 210 Buf = 0; 211 } 212 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 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 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 247 CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) 248 { 249 vt.Write = Wrap_WriteByte; 250 }