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) 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) 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 } 41 return defaultRes; 42 } 43 44 static 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 55 static 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 70 CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) 71 { 72 p.Read = MyRead; 73 Stream = stream; 74 } 75 76 CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) 77 { 78 p.Write = MyWrite; 79 Stream = stream; 80 Res = SZ_OK; 81 Processed = 0; 82 } 83 84 HRESULT 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 97 static 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 106 static 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 123 CSeekInStreamWrap::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 134 void CByteInBufWrap::Free() 135 { 136 ::MidFree(Buf); 137 Buf = 0; 138 } 139 140 bool 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 151 Byte 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 167 static 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 175 CByteInBufWrap::CByteInBufWrap(): Buf(0) 176 { 177 p.Read = Wrap_ReadByte; 178 } 179 180 181 /* ---------- CByteOutBufWrap ---------- */ 182 183 void CByteOutBufWrap::Free() 184 { 185 ::MidFree(Buf); 186 Buf = 0; 187 } 188 189 bool 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 200 HRESULT 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 213 static 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 223 CByteOutBufWrap::CByteOutBufWrap(): Buf(0) 224 { 225 p.Write = Wrap_WriteByte; 226 } 227