// CWrappers.h | |
#include "StdAfx.h" | |
#include "../../../C/Alloc.h" | |
#include "CWrappers.h" | |
#include "StreamUtils.h" | |
#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) | |
#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) | |
static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw() | |
{ | |
CCompressProgressWrap *p = (CCompressProgressWrap *)pp; | |
p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); | |
return (SRes)p->Res; | |
} | |
CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw() | |
{ | |
p.Progress = CompressProgress; | |
Progress = progress; | |
Res = SZ_OK; | |
} | |
static const UInt32 kStreamStepSize = (UInt32)1 << 31; | |
SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) | |
{ | |
switch (res) | |
{ | |
case S_OK: return SZ_OK; | |
case E_OUTOFMEMORY: return SZ_ERROR_MEM; | |
case E_INVALIDARG: return SZ_ERROR_PARAM; | |
case E_ABORT: return SZ_ERROR_PROGRESS; | |
case S_FALSE: return SZ_ERROR_DATA; | |
case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; | |
} | |
return defaultRes; | |
} | |
static SRes MyRead(void *object, void *data, size_t *size) throw() | |
{ | |
CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; | |
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); | |
p->Res = (p->Stream->Read(data, curSize, &curSize)); | |
*size = curSize; | |
p->Processed += curSize; | |
if (p->Res == S_OK) | |
return SZ_OK; | |
return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); | |
} | |
static size_t MyWrite(void *object, const void *data, size_t size) throw() | |
{ | |
CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; | |
if (p->Stream) | |
{ | |
p->Res = WriteStream(p->Stream, data, size); | |
if (p->Res != 0) | |
return 0; | |
} | |
else | |
p->Res = S_OK; | |
p->Processed += size; | |
return size; | |
} | |
CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw() | |
{ | |
p.Read = MyRead; | |
Stream = stream; | |
Processed = 0; | |
} | |
CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw() | |
{ | |
p.Write = MyWrite; | |
Stream = stream; | |
Res = SZ_OK; | |
Processed = 0; | |
} | |
HRESULT SResToHRESULT(SRes res) throw() | |
{ | |
switch(res) | |
{ | |
case SZ_OK: return S_OK; | |
case SZ_ERROR_MEM: return E_OUTOFMEMORY; | |
case SZ_ERROR_PARAM: return E_INVALIDARG; | |
case SZ_ERROR_PROGRESS: return E_ABORT; | |
case SZ_ERROR_DATA: return S_FALSE; | |
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; | |
} | |
return E_FAIL; | |
} | |
static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw() | |
{ | |
CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; | |
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); | |
p->Res = p->Stream->Read(data, curSize, &curSize); | |
*size = curSize; | |
return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; | |
} | |
static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw() | |
{ | |
CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; | |
UInt32 moveMethod; | |
switch(origin) | |
{ | |
case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break; | |
case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break; | |
case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break; | |
default: return SZ_ERROR_PARAM; | |
} | |
UInt64 newPosition; | |
p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition); | |
*offset = (Int64)newPosition; | |
return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; | |
} | |
CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) throw() | |
{ | |
Stream = stream; | |
p.Read = InStreamWrap_Read; | |
p.Seek = InStreamWrap_Seek; | |
Res = S_OK; | |
} | |
/* ---------- CByteInBufWrap ---------- */ | |
void CByteInBufWrap::Free() throw() | |
{ | |
::MidFree(Buf); | |
Buf = 0; | |
} | |
bool CByteInBufWrap::Alloc(UInt32 size) throw() | |
{ | |
if (Buf == 0 || size != Size) | |
{ | |
Free(); | |
Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); | |
Size = size; | |
} | |
return (Buf != 0); | |
} | |
Byte CByteInBufWrap::ReadByteFromNewBlock() throw() | |
{ | |
if (Res == S_OK) | |
{ | |
UInt32 avail; | |
Processed += (Cur - Buf); | |
Res = Stream->Read(Buf, Size, &avail); | |
Cur = Buf; | |
Lim = Buf + avail; | |
if (avail != 0) | |
return *Cur++; | |
} | |
Extra = true; | |
return 0; | |
} | |
static Byte Wrap_ReadByte(void *pp) throw() | |
{ | |
CByteInBufWrap *p = (CByteInBufWrap *)pp; | |
if (p->Cur != p->Lim) | |
return *p->Cur++; | |
return p->ReadByteFromNewBlock(); | |
} | |
CByteInBufWrap::CByteInBufWrap(): Buf(0) | |
{ | |
p.Read = Wrap_ReadByte; | |
} | |
/* ---------- CByteOutBufWrap ---------- */ | |
void CByteOutBufWrap::Free() throw() | |
{ | |
::MidFree(Buf); | |
Buf = 0; | |
} | |
bool CByteOutBufWrap::Alloc(size_t size) throw() | |
{ | |
if (Buf == 0 || size != Size) | |
{ | |
Free(); | |
Buf = (Byte *)::MidAlloc(size); | |
Size = size; | |
} | |
return (Buf != 0); | |
} | |
HRESULT CByteOutBufWrap::Flush() throw() | |
{ | |
if (Res == S_OK) | |
{ | |
size_t size = (Cur - Buf); | |
Res = WriteStream(Stream, Buf, size); | |
if (Res == S_OK) | |
Processed += size; | |
Cur = Buf; | |
} | |
return Res; | |
} | |
static void Wrap_WriteByte(void *pp, Byte b) throw() | |
{ | |
CByteOutBufWrap *p = (CByteOutBufWrap *)pp; | |
Byte *dest = p->Cur; | |
*dest = b; | |
p->Cur = ++dest; | |
if (dest == p->Lim) | |
p->Flush(); | |
} | |
CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) | |
{ | |
p.Write = Wrap_WriteByte; | |
} |