Home | History | Annotate | Download | only in Common
      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