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 15 static 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 22 CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw() 23 { 24 p.Progress = CompressProgress; 25 Progress = progress; 26 Res = SZ_OK; 27 } 28 29 static const UInt32 kStreamStepSize = (UInt32)1 << 31; 30 31 SRes 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 45 static 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 57 static 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 72 CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw() 73 { 74 p.Read = MyRead; 75 Stream = stream; 76 Processed = 0; 77 } 78 79 CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw() 80 { 81 p.Write = MyWrite; 82 Stream = stream; 83 Res = SZ_OK; 84 Processed = 0; 85 } 86 87 HRESULT 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 101 static 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 110 static 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 127 CSeekInStreamWrap::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 138 void CByteInBufWrap::Free() throw() 139 { 140 ::MidFree(Buf); 141 Buf = 0; 142 } 143 144 bool 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 155 Byte 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 171 static 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 179 CByteInBufWrap::CByteInBufWrap(): Buf(0) 180 { 181 p.Read = Wrap_ReadByte; 182 } 183 184 185 /* ---------- CByteOutBufWrap ---------- */ 186 187 void CByteOutBufWrap::Free() throw() 188 { 189 ::MidFree(Buf); 190 Buf = 0; 191 } 192 193 bool 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 204 HRESULT 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 217 static 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 227 CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) 228 { 229 p.Write = Wrap_WriteByte; 230 } 231