mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 16:07:04 -06:00
Normalize all the line endings
This commit is contained in:
@@ -1,250 +1,250 @@
|
||||
// CWrappers.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "CWrappers.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
HRESULT SResToHRESULT(SRes res) throw()
|
||||
{
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: return S_OK;
|
||||
|
||||
case SZ_ERROR_DATA:
|
||||
case SZ_ERROR_CRC:
|
||||
case SZ_ERROR_INPUT_EOF:
|
||||
return S_FALSE;
|
||||
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
case SZ_ERROR_PROGRESS: return E_ABORT;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
// case SZ_ERROR_OUTPUT_EOF:
|
||||
// case SZ_ERROR_READ:
|
||||
// case SZ_ERROR_WRITE:
|
||||
// case SZ_ERROR_THREAD:
|
||||
// case SZ_ERROR_ARCHIVE:
|
||||
// case SZ_ERROR_NO_ARCHIVE:
|
||||
// return E_FAIL;
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)
|
||||
|
||||
#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
|
||||
|
||||
|
||||
static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
|
||||
{
|
||||
CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
|
||||
p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
|
||||
return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
|
||||
}
|
||||
|
||||
void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
|
||||
{
|
||||
vt.Progress = CompressProgress;
|
||||
Progress = progress;
|
||||
Res = SZ_OK;
|
||||
}
|
||||
|
||||
static const UInt32 kStreamStepSize = (UInt32)1 << 31;
|
||||
|
||||
static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
|
||||
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(const ISeqOutStream *pp, const void *data, size_t size) throw()
|
||||
{
|
||||
CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()
|
||||
{
|
||||
vt.Read = MyRead;
|
||||
Stream = stream;
|
||||
Processed = 0;
|
||||
Res = S_OK;
|
||||
}
|
||||
|
||||
void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
|
||||
{
|
||||
vt.Write = MyWrite;
|
||||
Stream = stream;
|
||||
Res = SZ_OK;
|
||||
Processed = 0;
|
||||
}
|
||||
|
||||
|
||||
static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
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(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
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;
|
||||
}
|
||||
|
||||
void CSeekInStreamWrap::Init(IInStream *stream) throw()
|
||||
{
|
||||
Stream = stream;
|
||||
vt.Read = InStreamWrap_Read;
|
||||
vt.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(const IByteIn *pp) throw()
|
||||
{
|
||||
CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
|
||||
if (p->Cur != p->Lim)
|
||||
return *p->Cur++;
|
||||
return p->ReadByteFromNewBlock();
|
||||
}
|
||||
|
||||
CByteInBufWrap::CByteInBufWrap(): Buf(0)
|
||||
{
|
||||
vt.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(const IByteOut *pp, Byte b) throw()
|
||||
{
|
||||
CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
|
||||
Byte *dest = p->Cur;
|
||||
*dest = b;
|
||||
p->Cur = ++dest;
|
||||
if (dest == p->Lim)
|
||||
p->Flush();
|
||||
}
|
||||
|
||||
CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)
|
||||
{
|
||||
vt.Write = Wrap_WriteByte;
|
||||
}
|
||||
// CWrappers.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "CWrappers.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
HRESULT SResToHRESULT(SRes res) throw()
|
||||
{
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: return S_OK;
|
||||
|
||||
case SZ_ERROR_DATA:
|
||||
case SZ_ERROR_CRC:
|
||||
case SZ_ERROR_INPUT_EOF:
|
||||
return S_FALSE;
|
||||
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
case SZ_ERROR_PROGRESS: return E_ABORT;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
// case SZ_ERROR_OUTPUT_EOF:
|
||||
// case SZ_ERROR_READ:
|
||||
// case SZ_ERROR_WRITE:
|
||||
// case SZ_ERROR_THREAD:
|
||||
// case SZ_ERROR_ARCHIVE:
|
||||
// case SZ_ERROR_NO_ARCHIVE:
|
||||
// return E_FAIL;
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)
|
||||
|
||||
#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
|
||||
|
||||
|
||||
static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
|
||||
{
|
||||
CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
|
||||
p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
|
||||
return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
|
||||
}
|
||||
|
||||
void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
|
||||
{
|
||||
vt.Progress = CompressProgress;
|
||||
Progress = progress;
|
||||
Res = SZ_OK;
|
||||
}
|
||||
|
||||
static const UInt32 kStreamStepSize = (UInt32)1 << 31;
|
||||
|
||||
static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
|
||||
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(const ISeqOutStream *pp, const void *data, size_t size) throw()
|
||||
{
|
||||
CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()
|
||||
{
|
||||
vt.Read = MyRead;
|
||||
Stream = stream;
|
||||
Processed = 0;
|
||||
Res = S_OK;
|
||||
}
|
||||
|
||||
void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
|
||||
{
|
||||
vt.Write = MyWrite;
|
||||
Stream = stream;
|
||||
Res = SZ_OK;
|
||||
Processed = 0;
|
||||
}
|
||||
|
||||
|
||||
static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
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(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
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;
|
||||
}
|
||||
|
||||
void CSeekInStreamWrap::Init(IInStream *stream) throw()
|
||||
{
|
||||
Stream = stream;
|
||||
vt.Read = InStreamWrap_Read;
|
||||
vt.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(const IByteIn *pp) throw()
|
||||
{
|
||||
CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
|
||||
if (p->Cur != p->Lim)
|
||||
return *p->Cur++;
|
||||
return p->ReadByteFromNewBlock();
|
||||
}
|
||||
|
||||
CByteInBufWrap::CByteInBufWrap(): Buf(0)
|
||||
{
|
||||
vt.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(const IByteOut *pp, Byte b) throw()
|
||||
{
|
||||
CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
|
||||
Byte *dest = p->Cur;
|
||||
*dest = b;
|
||||
p->Cur = ++dest;
|
||||
if (dest == p->Lim)
|
||||
p->Flush();
|
||||
}
|
||||
|
||||
CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)
|
||||
{
|
||||
vt.Write = Wrap_WriteByte;
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
// CWrappers.h
|
||||
|
||||
#ifndef __C_WRAPPERS_H
|
||||
#define __C_WRAPPERS_H
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw();
|
||||
HRESULT SResToHRESULT(SRes res) throw();
|
||||
|
||||
struct CCompressProgressWrap
|
||||
{
|
||||
ICompressProgress vt;
|
||||
ICompressProgressInfo *Progress;
|
||||
HRESULT Res;
|
||||
|
||||
void Init(ICompressProgressInfo *progress) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeqInStreamWrap
|
||||
{
|
||||
ISeqInStream vt;
|
||||
ISequentialInStream *Stream;
|
||||
HRESULT Res;
|
||||
UInt64 Processed;
|
||||
|
||||
void Init(ISequentialInStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeekInStreamWrap
|
||||
{
|
||||
ISeekInStream vt;
|
||||
IInStream *Stream;
|
||||
HRESULT Res;
|
||||
|
||||
void Init(IInStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeqOutStreamWrap
|
||||
{
|
||||
ISeqOutStream vt;
|
||||
ISequentialOutStream *Stream;
|
||||
HRESULT Res;
|
||||
UInt64 Processed;
|
||||
|
||||
void Init(ISequentialOutStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CByteInBufWrap
|
||||
{
|
||||
IByteIn vt;
|
||||
const Byte *Cur;
|
||||
const Byte *Lim;
|
||||
Byte *Buf;
|
||||
UInt32 Size;
|
||||
ISequentialInStream *Stream;
|
||||
UInt64 Processed;
|
||||
bool Extra;
|
||||
HRESULT Res;
|
||||
|
||||
CByteInBufWrap();
|
||||
~CByteInBufWrap() { Free(); }
|
||||
void Free() throw();
|
||||
bool Alloc(UInt32 size) throw();
|
||||
void Init()
|
||||
{
|
||||
Lim = Cur = Buf;
|
||||
Processed = 0;
|
||||
Extra = false;
|
||||
Res = S_OK;
|
||||
}
|
||||
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
|
||||
Byte ReadByteFromNewBlock() throw();
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (Cur != Lim)
|
||||
return *Cur++;
|
||||
return ReadByteFromNewBlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CByteOutBufWrap
|
||||
{
|
||||
IByteOut vt;
|
||||
Byte *Cur;
|
||||
const Byte *Lim;
|
||||
Byte *Buf;
|
||||
size_t Size;
|
||||
ISequentialOutStream *Stream;
|
||||
UInt64 Processed;
|
||||
HRESULT Res;
|
||||
|
||||
CByteOutBufWrap() throw();
|
||||
~CByteOutBufWrap() { Free(); }
|
||||
void Free() throw();
|
||||
bool Alloc(size_t size) throw();
|
||||
void Init()
|
||||
{
|
||||
Cur = Buf;
|
||||
Lim = Buf + Size;
|
||||
Processed = 0;
|
||||
Res = S_OK;
|
||||
}
|
||||
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
|
||||
HRESULT Flush() throw();
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
*Cur++ = b;
|
||||
if (Cur == Lim)
|
||||
Flush();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
// CWrappers.h
|
||||
|
||||
#ifndef __C_WRAPPERS_H
|
||||
#define __C_WRAPPERS_H
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw();
|
||||
HRESULT SResToHRESULT(SRes res) throw();
|
||||
|
||||
struct CCompressProgressWrap
|
||||
{
|
||||
ICompressProgress vt;
|
||||
ICompressProgressInfo *Progress;
|
||||
HRESULT Res;
|
||||
|
||||
void Init(ICompressProgressInfo *progress) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeqInStreamWrap
|
||||
{
|
||||
ISeqInStream vt;
|
||||
ISequentialInStream *Stream;
|
||||
HRESULT Res;
|
||||
UInt64 Processed;
|
||||
|
||||
void Init(ISequentialInStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeekInStreamWrap
|
||||
{
|
||||
ISeekInStream vt;
|
||||
IInStream *Stream;
|
||||
HRESULT Res;
|
||||
|
||||
void Init(IInStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CSeqOutStreamWrap
|
||||
{
|
||||
ISeqOutStream vt;
|
||||
ISequentialOutStream *Stream;
|
||||
HRESULT Res;
|
||||
UInt64 Processed;
|
||||
|
||||
void Init(ISequentialOutStream *stream) throw();
|
||||
};
|
||||
|
||||
|
||||
struct CByteInBufWrap
|
||||
{
|
||||
IByteIn vt;
|
||||
const Byte *Cur;
|
||||
const Byte *Lim;
|
||||
Byte *Buf;
|
||||
UInt32 Size;
|
||||
ISequentialInStream *Stream;
|
||||
UInt64 Processed;
|
||||
bool Extra;
|
||||
HRESULT Res;
|
||||
|
||||
CByteInBufWrap();
|
||||
~CByteInBufWrap() { Free(); }
|
||||
void Free() throw();
|
||||
bool Alloc(UInt32 size) throw();
|
||||
void Init()
|
||||
{
|
||||
Lim = Cur = Buf;
|
||||
Processed = 0;
|
||||
Extra = false;
|
||||
Res = S_OK;
|
||||
}
|
||||
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
|
||||
Byte ReadByteFromNewBlock() throw();
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (Cur != Lim)
|
||||
return *Cur++;
|
||||
return ReadByteFromNewBlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CByteOutBufWrap
|
||||
{
|
||||
IByteOut vt;
|
||||
Byte *Cur;
|
||||
const Byte *Lim;
|
||||
Byte *Buf;
|
||||
size_t Size;
|
||||
ISequentialOutStream *Stream;
|
||||
UInt64 Processed;
|
||||
HRESULT Res;
|
||||
|
||||
CByteOutBufWrap() throw();
|
||||
~CByteOutBufWrap() { Free(); }
|
||||
void Free() throw();
|
||||
bool Alloc(size_t size) throw();
|
||||
void Init()
|
||||
{
|
||||
Cur = Buf;
|
||||
Lim = Buf + Size;
|
||||
Processed = 0;
|
||||
Res = S_OK;
|
||||
}
|
||||
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
|
||||
HRESULT Flush() throw();
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
*Cur++ = b;
|
||||
if (Cur == Lim)
|
||||
Flush();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,192 +1,192 @@
|
||||
// CreateCoder.h
|
||||
|
||||
#ifndef __CREATE_CODER_H
|
||||
#define __CREATE_CODER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "MethodId.h"
|
||||
|
||||
/*
|
||||
if EXTERNAL_CODECS is not defined, the code supports only codecs that
|
||||
are statically linked at compile-time and link-time.
|
||||
|
||||
if EXTERNAL_CODECS is defined, the code supports also codecs from another
|
||||
executable modules, that can be linked dynamically at run-time:
|
||||
- EXE module can use codecs from external DLL files.
|
||||
- DLL module can use codecs from external EXE and DLL files.
|
||||
|
||||
CExternalCodecs contains information about codecs and interfaces to create them.
|
||||
|
||||
The order of codecs:
|
||||
1) Internal codecs
|
||||
2) External codecs
|
||||
*/
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
struct CCodecInfoEx
|
||||
{
|
||||
CMethodId Id;
|
||||
AString Name;
|
||||
UInt32 NumStreams;
|
||||
bool EncoderIsAssigned;
|
||||
bool DecoderIsAssigned;
|
||||
|
||||
CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
|
||||
};
|
||||
|
||||
struct CHasherInfoEx
|
||||
{
|
||||
CMethodId Id;
|
||||
AString Name;
|
||||
};
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
|
||||
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
|
||||
#define IMPL_ISetCompressCodecsInfo2(x) \
|
||||
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
|
||||
COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END }
|
||||
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
|
||||
|
||||
struct CExternalCodecs
|
||||
{
|
||||
CMyComPtr<ICompressCodecsInfo> GetCodecs;
|
||||
CMyComPtr<IHashers> GetHashers;
|
||||
|
||||
CObjectVector<CCodecInfoEx> Codecs;
|
||||
CObjectVector<CHasherInfoEx> Hashers;
|
||||
|
||||
bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; }
|
||||
|
||||
HRESULT Load();
|
||||
|
||||
void ClearAndRelease()
|
||||
{
|
||||
Hashers.Clear();
|
||||
Codecs.Clear();
|
||||
GetHashers.Release();
|
||||
GetCodecs.Release();
|
||||
}
|
||||
|
||||
~CExternalCodecs()
|
||||
{
|
||||
GetHashers.Release();
|
||||
GetCodecs.Release();
|
||||
}
|
||||
};
|
||||
|
||||
extern CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
|
||||
#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,
|
||||
#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs
|
||||
#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
|
||||
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
|
||||
|
||||
#else
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
#define DECL_ISetCompressCodecsInfo
|
||||
#define IMPL_ISetCompressCodecsInfo
|
||||
#define EXTERNAL_CODECS_VARS2
|
||||
#define DECL_EXTERNAL_CODECS_VARS
|
||||
#define EXTERNAL_CODECS_VARS
|
||||
#define EXTERNAL_CODECS_VARS_L
|
||||
#define EXTERNAL_CODECS_VARS_G
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2
|
||||
#define EXTERNAL_CODECS_LOC_VARS2
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
#define EXTERNAL_CODECS_LOC_VARS
|
||||
|
||||
#endif
|
||||
|
||||
int FindMethod_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams);
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId,
|
||||
AString &name);
|
||||
|
||||
bool FindHashMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
CMethodId &methodId);
|
||||
|
||||
void GetHashMethods(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CRecordVector<CMethodId> &methods);
|
||||
|
||||
|
||||
struct CCreatedCoder
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
|
||||
bool IsExternal;
|
||||
bool IsFilter; // = true, if Coder was created from filter
|
||||
UInt32 NumStreams;
|
||||
|
||||
// CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned codecIndex, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned index, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressCoder> &coder);
|
||||
|
||||
HRESULT CreateFilter(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter);
|
||||
|
||||
HRESULT CreateHasher(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId,
|
||||
AString &name,
|
||||
CMyComPtr<IHasher> &hasher);
|
||||
|
||||
#endif
|
||||
// CreateCoder.h
|
||||
|
||||
#ifndef __CREATE_CODER_H
|
||||
#define __CREATE_CODER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "MethodId.h"
|
||||
|
||||
/*
|
||||
if EXTERNAL_CODECS is not defined, the code supports only codecs that
|
||||
are statically linked at compile-time and link-time.
|
||||
|
||||
if EXTERNAL_CODECS is defined, the code supports also codecs from another
|
||||
executable modules, that can be linked dynamically at run-time:
|
||||
- EXE module can use codecs from external DLL files.
|
||||
- DLL module can use codecs from external EXE and DLL files.
|
||||
|
||||
CExternalCodecs contains information about codecs and interfaces to create them.
|
||||
|
||||
The order of codecs:
|
||||
1) Internal codecs
|
||||
2) External codecs
|
||||
*/
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
struct CCodecInfoEx
|
||||
{
|
||||
CMethodId Id;
|
||||
AString Name;
|
||||
UInt32 NumStreams;
|
||||
bool EncoderIsAssigned;
|
||||
bool DecoderIsAssigned;
|
||||
|
||||
CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
|
||||
};
|
||||
|
||||
struct CHasherInfoEx
|
||||
{
|
||||
CMethodId Id;
|
||||
AString Name;
|
||||
};
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
|
||||
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
|
||||
#define IMPL_ISetCompressCodecsInfo2(x) \
|
||||
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
|
||||
COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END }
|
||||
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
|
||||
|
||||
struct CExternalCodecs
|
||||
{
|
||||
CMyComPtr<ICompressCodecsInfo> GetCodecs;
|
||||
CMyComPtr<IHashers> GetHashers;
|
||||
|
||||
CObjectVector<CCodecInfoEx> Codecs;
|
||||
CObjectVector<CHasherInfoEx> Hashers;
|
||||
|
||||
bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; }
|
||||
|
||||
HRESULT Load();
|
||||
|
||||
void ClearAndRelease()
|
||||
{
|
||||
Hashers.Clear();
|
||||
Codecs.Clear();
|
||||
GetHashers.Release();
|
||||
GetCodecs.Release();
|
||||
}
|
||||
|
||||
~CExternalCodecs()
|
||||
{
|
||||
GetHashers.Release();
|
||||
GetCodecs.Release();
|
||||
}
|
||||
};
|
||||
|
||||
extern CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
|
||||
#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,
|
||||
#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs
|
||||
#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
|
||||
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
|
||||
|
||||
#else
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
#define DECL_ISetCompressCodecsInfo
|
||||
#define IMPL_ISetCompressCodecsInfo
|
||||
#define EXTERNAL_CODECS_VARS2
|
||||
#define DECL_EXTERNAL_CODECS_VARS
|
||||
#define EXTERNAL_CODECS_VARS
|
||||
#define EXTERNAL_CODECS_VARS_L
|
||||
#define EXTERNAL_CODECS_VARS_G
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2
|
||||
#define EXTERNAL_CODECS_LOC_VARS2
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
#define EXTERNAL_CODECS_LOC_VARS
|
||||
|
||||
#endif
|
||||
|
||||
int FindMethod_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams);
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId,
|
||||
AString &name);
|
||||
|
||||
bool FindHashMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
CMethodId &methodId);
|
||||
|
||||
void GetHashMethods(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CRecordVector<CMethodId> &methods);
|
||||
|
||||
|
||||
struct CCreatedCoder
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
|
||||
bool IsExternal;
|
||||
bool IsFilter; // = true, if Coder was created from filter
|
||||
UInt32 NumStreams;
|
||||
|
||||
// CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned codecIndex, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned index, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressCoder> &coder);
|
||||
|
||||
HRESULT CreateFilter(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter);
|
||||
|
||||
HRESULT CreateHasher(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId,
|
||||
AString &name,
|
||||
CMyComPtr<IHasher> &hasher);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
// FilePathAutoRename.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Windows/FileFind.h"
|
||||
|
||||
#include "FilePathAutoRename.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static bool MakeAutoName(const FString &name,
|
||||
const FString &extension, UInt32 value, FString &path)
|
||||
{
|
||||
path = name;
|
||||
path.Add_UInt32(value);
|
||||
path += extension;
|
||||
return NFile::NFind::DoesFileOrDirExist(path);
|
||||
}
|
||||
|
||||
bool AutoRenamePath(FString &path)
|
||||
{
|
||||
int dotPos = path.ReverseFind_Dot();
|
||||
int slashPos = path.ReverseFind_PathSepar();
|
||||
|
||||
FString name = path;
|
||||
FString extension;
|
||||
if (dotPos > slashPos + 1)
|
||||
{
|
||||
name.DeleteFrom(dotPos);
|
||||
extension = path.Ptr(dotPos);
|
||||
}
|
||||
name += '_';
|
||||
|
||||
FString temp;
|
||||
|
||||
UInt32 left = 1, right = ((UInt32)1 << 30);
|
||||
while (left != right)
|
||||
{
|
||||
UInt32 mid = (left + right) / 2;
|
||||
if (MakeAutoName(name, extension, mid, temp))
|
||||
left = mid + 1;
|
||||
else
|
||||
right = mid;
|
||||
}
|
||||
return !MakeAutoName(name, extension, right, path);
|
||||
}
|
||||
// FilePathAutoRename.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Windows/FileFind.h"
|
||||
|
||||
#include "FilePathAutoRename.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static bool MakeAutoName(const FString &name,
|
||||
const FString &extension, UInt32 value, FString &path)
|
||||
{
|
||||
path = name;
|
||||
path.Add_UInt32(value);
|
||||
path += extension;
|
||||
return NFile::NFind::DoesFileOrDirExist(path);
|
||||
}
|
||||
|
||||
bool AutoRenamePath(FString &path)
|
||||
{
|
||||
int dotPos = path.ReverseFind_Dot();
|
||||
int slashPos = path.ReverseFind_PathSepar();
|
||||
|
||||
FString name = path;
|
||||
FString extension;
|
||||
if (dotPos > slashPos + 1)
|
||||
{
|
||||
name.DeleteFrom(dotPos);
|
||||
extension = path.Ptr(dotPos);
|
||||
}
|
||||
name += '_';
|
||||
|
||||
FString temp;
|
||||
|
||||
UInt32 left = 1, right = ((UInt32)1 << 30);
|
||||
while (left != right)
|
||||
{
|
||||
UInt32 mid = (left + right) / 2;
|
||||
if (MakeAutoName(name, extension, mid, temp))
|
||||
left = mid + 1;
|
||||
else
|
||||
right = mid;
|
||||
}
|
||||
return !MakeAutoName(name, extension, right, path);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// FilePathAutoRename.h
|
||||
|
||||
#ifndef __FILE_PATH_AUTO_RENAME_H
|
||||
#define __FILE_PATH_AUTO_RENAME_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
bool AutoRenamePath(FString &fullProcessedPath);
|
||||
|
||||
#endif
|
||||
// FilePathAutoRename.h
|
||||
|
||||
#ifndef __FILE_PATH_AUTO_RENAME_H
|
||||
#define __FILE_PATH_AUTO_RENAME_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
bool AutoRenamePath(FString &fullProcessedPath);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,475 +1,475 @@
|
||||
// FileStreams.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../Common/Defs.h"
|
||||
#endif
|
||||
|
||||
#include "FileStreams.h"
|
||||
|
||||
static inline HRESULT ConvertBoolToHRESULT(bool result)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (result)
|
||||
return S_OK;
|
||||
DWORD lastError = ::GetLastError();
|
||||
if (lastError == 0)
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
#else
|
||||
return result ? S_OK: E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static const UInt32 kClusterSize = 1 << 18;
|
||||
CInFileStream::CInFileStream():
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
VirtPos(0),
|
||||
PhyPos(0),
|
||||
Buf(0),
|
||||
BufSize(0),
|
||||
#endif
|
||||
SupportHardLinks(false),
|
||||
Callback(NULL),
|
||||
CallbackRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
CInFileStream::~CInFileStream()
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
MidFree(Buf);
|
||||
#endif
|
||||
|
||||
if (Callback)
|
||||
Callback->InFileStream_On_Destroy(CallbackRef);
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (File.IsDeviceFile)
|
||||
{
|
||||
if (File.SizeDefined)
|
||||
{
|
||||
if (VirtPos >= File.Size)
|
||||
return VirtPos == File.Size ? S_OK : E_FAIL;
|
||||
UInt64 rem = File.Size - VirtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
const UInt32 mask = kClusterSize - 1;
|
||||
const UInt64 mask2 = ~(UInt64)mask;
|
||||
UInt64 alignedPos = VirtPos & mask2;
|
||||
if (BufSize > 0 && BufStartPos == alignedPos)
|
||||
{
|
||||
UInt32 pos = (UInt32)VirtPos & mask;
|
||||
if (pos >= BufSize)
|
||||
return S_OK;
|
||||
UInt32 rem = MyMin(BufSize - pos, size);
|
||||
memcpy(data, Buf + pos, rem);
|
||||
VirtPos += rem;
|
||||
if (processedSize)
|
||||
*processedSize += rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool useBuf = false;
|
||||
if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
|
||||
useBuf = true;
|
||||
else
|
||||
{
|
||||
UInt64 end = VirtPos + size;
|
||||
if ((end & mask) != 0)
|
||||
{
|
||||
end &= mask2;
|
||||
if (end <= VirtPos)
|
||||
useBuf = true;
|
||||
else
|
||||
size = (UInt32)(end - VirtPos);
|
||||
}
|
||||
}
|
||||
if (!useBuf)
|
||||
break;
|
||||
if (alignedPos != PhyPos)
|
||||
{
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
PhyPos = realNewPosition;
|
||||
}
|
||||
|
||||
BufStartPos = alignedPos;
|
||||
UInt32 readSize = kClusterSize;
|
||||
if (File.SizeDefined)
|
||||
readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);
|
||||
|
||||
if (!Buf)
|
||||
{
|
||||
Buf = (Byte *)MidAlloc(kClusterSize);
|
||||
if (!Buf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
bool result = File.Read1(Buf, readSize, BufSize);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
if (BufSize == 0)
|
||||
return S_OK;
|
||||
PhyPos += BufSize;
|
||||
}
|
||||
|
||||
if (VirtPos != PhyPos)
|
||||
{
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
PhyPos = VirtPos = realNewPosition;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
bool result = File.ReadPart(data, size, realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
VirtPos += realProcessedSize;
|
||||
PhyPos += realProcessedSize;
|
||||
#endif
|
||||
|
||||
if (result)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
DWORD error = ::GetLastError();
|
||||
|
||||
if (Callback)
|
||||
return Callback->InFileStream_On_Error(CallbackRef, error);
|
||||
if (error == 0)
|
||||
return E_FAIL;
|
||||
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res = File.Read(data, (size_t)size);
|
||||
if (res == -1)
|
||||
{
|
||||
if (Callback)
|
||||
return Callback->InFileStream_On_Error(CallbackRef, E_FAIL);
|
||||
return E_FAIL;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t s2 = fread(data, 1, size, stdin);
|
||||
int error = ferror(stdin);
|
||||
if (processedSize)
|
||||
*processedSize = s2;
|
||||
if (s2 <= size && error == 0)
|
||||
return S_OK;
|
||||
return E_FAIL;
|
||||
}
|
||||
#else
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD realProcessedSize;
|
||||
UInt32 sizeTemp = (1 << 20);
|
||||
if (sizeTemp > size)
|
||||
sizeTemp = size;
|
||||
BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
|
||||
return S_OK;
|
||||
return ConvertBoolToHRESULT(res != FALSE);
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res;
|
||||
do
|
||||
{
|
||||
res = read(0, data, (size_t)size);
|
||||
}
|
||||
while (res < 0 && (errno == EINTR));
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += VirtPos; break;
|
||||
case STREAM_SEEK_END: offset += File.Size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
VirtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(offset, seekOrigin, realNewPosition);
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
PhyPos = VirtPos = realNewPosition;
|
||||
#endif
|
||||
|
||||
if (newPosition)
|
||||
*newPosition = realNewPosition;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
off_t res = File.Seek((off_t)offset, seekOrigin);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.GetLength(*size));
|
||||
}
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (File.GetFileInformation(&info))
|
||||
{
|
||||
if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
if (cTime) *cTime = info.ftCreationTime;
|
||||
if (aTime) *aTime = info.ftLastAccessTime;
|
||||
if (mTime) *mTime = info.ftLastWriteTime;
|
||||
if (attrib) *attrib = info.dwFileAttributes;
|
||||
return S_OK;
|
||||
}
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (File.GetFileInformation(&info))
|
||||
{
|
||||
props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
props->VolID = info.dwVolumeSerialNumber;
|
||||
props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
|
||||
props->FileID_High = 0;
|
||||
props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
|
||||
props->Attrib = info.dwFileAttributes;
|
||||
props->CTime = info.ftCreationTime;
|
||||
props->ATime = info.ftLastAccessTime;
|
||||
props->MTime = info.ftLastWriteTime;
|
||||
return S_OK;
|
||||
}
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////
|
||||
// COutFileStream
|
||||
|
||||
HRESULT COutFileStream::Close()
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.Close());
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
bool result = File.Write(data, size, realProcessedSize);
|
||||
ProcessedSize += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res = File.Write(data, (size_t)size);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
ProcessedSize += res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(offset, seekOrigin, realNewPosition);
|
||||
if (newPosition)
|
||||
*newPosition = realNewPosition;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
off_t res = File.Seek((off_t)offset, seekOrigin);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt64 currentPos;
|
||||
if (!File.Seek(0, FILE_CURRENT, currentPos))
|
||||
return E_FAIL;
|
||||
bool result = File.SetLength(newSize);
|
||||
UInt64 currentPos2;
|
||||
result = result && File.Seek(currentPos, currentPos2);
|
||||
return result ? S_OK : E_FAIL;
|
||||
|
||||
#else
|
||||
|
||||
return E_FAIL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT COutFileStream::GetSize(UInt64 *size)
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.GetLength(*size));
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t s2 = fwrite(data, 1, size, stdout);
|
||||
if (processedSize)
|
||||
*processedSize = s2;
|
||||
return (s2 == size) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
BOOL res = TRUE;
|
||||
if (size > 0)
|
||||
{
|
||||
// Seems that Windows doesn't like big amounts writing to stdout.
|
||||
// So we limit portions by 32KB.
|
||||
UInt32 sizeTemp = (1 << 15);
|
||||
if (sizeTemp > size)
|
||||
sizeTemp = size;
|
||||
res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
|
||||
_size += realProcessedSize;
|
||||
size -= realProcessedSize;
|
||||
data = (const void *)((const Byte *)data + realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize += realProcessedSize;
|
||||
}
|
||||
return ConvertBoolToHRESULT(res != FALSE);
|
||||
|
||||
#else
|
||||
|
||||
ssize_t res;
|
||||
|
||||
do
|
||||
{
|
||||
res = write(1, data, (size_t)size);
|
||||
}
|
||||
while (res < 0 && (errno == EINTR));
|
||||
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
|
||||
_size += (size_t)res;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
// FileStreams.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../Common/Defs.h"
|
||||
#endif
|
||||
|
||||
#include "FileStreams.h"
|
||||
|
||||
static inline HRESULT ConvertBoolToHRESULT(bool result)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (result)
|
||||
return S_OK;
|
||||
DWORD lastError = ::GetLastError();
|
||||
if (lastError == 0)
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
#else
|
||||
return result ? S_OK: E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static const UInt32 kClusterSize = 1 << 18;
|
||||
CInFileStream::CInFileStream():
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
VirtPos(0),
|
||||
PhyPos(0),
|
||||
Buf(0),
|
||||
BufSize(0),
|
||||
#endif
|
||||
SupportHardLinks(false),
|
||||
Callback(NULL),
|
||||
CallbackRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
CInFileStream::~CInFileStream()
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
MidFree(Buf);
|
||||
#endif
|
||||
|
||||
if (Callback)
|
||||
Callback->InFileStream_On_Destroy(CallbackRef);
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (File.IsDeviceFile)
|
||||
{
|
||||
if (File.SizeDefined)
|
||||
{
|
||||
if (VirtPos >= File.Size)
|
||||
return VirtPos == File.Size ? S_OK : E_FAIL;
|
||||
UInt64 rem = File.Size - VirtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
const UInt32 mask = kClusterSize - 1;
|
||||
const UInt64 mask2 = ~(UInt64)mask;
|
||||
UInt64 alignedPos = VirtPos & mask2;
|
||||
if (BufSize > 0 && BufStartPos == alignedPos)
|
||||
{
|
||||
UInt32 pos = (UInt32)VirtPos & mask;
|
||||
if (pos >= BufSize)
|
||||
return S_OK;
|
||||
UInt32 rem = MyMin(BufSize - pos, size);
|
||||
memcpy(data, Buf + pos, rem);
|
||||
VirtPos += rem;
|
||||
if (processedSize)
|
||||
*processedSize += rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool useBuf = false;
|
||||
if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
|
||||
useBuf = true;
|
||||
else
|
||||
{
|
||||
UInt64 end = VirtPos + size;
|
||||
if ((end & mask) != 0)
|
||||
{
|
||||
end &= mask2;
|
||||
if (end <= VirtPos)
|
||||
useBuf = true;
|
||||
else
|
||||
size = (UInt32)(end - VirtPos);
|
||||
}
|
||||
}
|
||||
if (!useBuf)
|
||||
break;
|
||||
if (alignedPos != PhyPos)
|
||||
{
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
PhyPos = realNewPosition;
|
||||
}
|
||||
|
||||
BufStartPos = alignedPos;
|
||||
UInt32 readSize = kClusterSize;
|
||||
if (File.SizeDefined)
|
||||
readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);
|
||||
|
||||
if (!Buf)
|
||||
{
|
||||
Buf = (Byte *)MidAlloc(kClusterSize);
|
||||
if (!Buf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
bool result = File.Read1(Buf, readSize, BufSize);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
if (BufSize == 0)
|
||||
return S_OK;
|
||||
PhyPos += BufSize;
|
||||
}
|
||||
|
||||
if (VirtPos != PhyPos)
|
||||
{
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
PhyPos = VirtPos = realNewPosition;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
bool result = File.ReadPart(data, size, realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
VirtPos += realProcessedSize;
|
||||
PhyPos += realProcessedSize;
|
||||
#endif
|
||||
|
||||
if (result)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
DWORD error = ::GetLastError();
|
||||
|
||||
if (Callback)
|
||||
return Callback->InFileStream_On_Error(CallbackRef, error);
|
||||
if (error == 0)
|
||||
return E_FAIL;
|
||||
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res = File.Read(data, (size_t)size);
|
||||
if (res == -1)
|
||||
{
|
||||
if (Callback)
|
||||
return Callback->InFileStream_On_Error(CallbackRef, E_FAIL);
|
||||
return E_FAIL;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t s2 = fread(data, 1, size, stdin);
|
||||
int error = ferror(stdin);
|
||||
if (processedSize)
|
||||
*processedSize = s2;
|
||||
if (s2 <= size && error == 0)
|
||||
return S_OK;
|
||||
return E_FAIL;
|
||||
}
|
||||
#else
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD realProcessedSize;
|
||||
UInt32 sizeTemp = (1 << 20);
|
||||
if (sizeTemp > size)
|
||||
sizeTemp = size;
|
||||
BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
|
||||
return S_OK;
|
||||
return ConvertBoolToHRESULT(res != FALSE);
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res;
|
||||
do
|
||||
{
|
||||
res = read(0, data, (size_t)size);
|
||||
}
|
||||
while (res < 0 && (errno == EINTR));
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += VirtPos; break;
|
||||
case STREAM_SEEK_END: offset += File.Size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
VirtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(offset, seekOrigin, realNewPosition);
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
PhyPos = VirtPos = realNewPosition;
|
||||
#endif
|
||||
|
||||
if (newPosition)
|
||||
*newPosition = realNewPosition;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
off_t res = File.Seek((off_t)offset, seekOrigin);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.GetLength(*size));
|
||||
}
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (File.GetFileInformation(&info))
|
||||
{
|
||||
if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
if (cTime) *cTime = info.ftCreationTime;
|
||||
if (aTime) *aTime = info.ftLastAccessTime;
|
||||
if (mTime) *mTime = info.ftLastWriteTime;
|
||||
if (attrib) *attrib = info.dwFileAttributes;
|
||||
return S_OK;
|
||||
}
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (File.GetFileInformation(&info))
|
||||
{
|
||||
props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
props->VolID = info.dwVolumeSerialNumber;
|
||||
props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
|
||||
props->FileID_High = 0;
|
||||
props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
|
||||
props->Attrib = info.dwFileAttributes;
|
||||
props->CTime = info.ftCreationTime;
|
||||
props->ATime = info.ftLastAccessTime;
|
||||
props->MTime = info.ftLastWriteTime;
|
||||
return S_OK;
|
||||
}
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////
|
||||
// COutFileStream
|
||||
|
||||
HRESULT COutFileStream::Close()
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.Close());
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
bool result = File.Write(data, size, realProcessedSize);
|
||||
ProcessedSize += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
ssize_t res = File.Write(data, (size_t)size);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
ProcessedSize += res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek(offset, seekOrigin, realNewPosition);
|
||||
if (newPosition)
|
||||
*newPosition = realNewPosition;
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
#else
|
||||
|
||||
off_t res = File.Seek((off_t)offset, seekOrigin);
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
|
||||
UInt64 currentPos;
|
||||
if (!File.Seek(0, FILE_CURRENT, currentPos))
|
||||
return E_FAIL;
|
||||
bool result = File.SetLength(newSize);
|
||||
UInt64 currentPos2;
|
||||
result = result && File.Seek(currentPos, currentPos2);
|
||||
return result ? S_OK : E_FAIL;
|
||||
|
||||
#else
|
||||
|
||||
return E_FAIL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT COutFileStream::GetSize(UInt64 *size)
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.GetLength(*size));
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t s2 = fwrite(data, 1, size, stdout);
|
||||
if (processedSize)
|
||||
*processedSize = s2;
|
||||
return (s2 == size) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
BOOL res = TRUE;
|
||||
if (size > 0)
|
||||
{
|
||||
// Seems that Windows doesn't like big amounts writing to stdout.
|
||||
// So we limit portions by 32KB.
|
||||
UInt32 sizeTemp = (1 << 15);
|
||||
if (sizeTemp > size)
|
||||
sizeTemp = size;
|
||||
res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
|
||||
_size += realProcessedSize;
|
||||
size -= realProcessedSize;
|
||||
data = (const void *)((const Byte *)data + realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize += realProcessedSize;
|
||||
}
|
||||
return ConvertBoolToHRESULT(res != FALSE);
|
||||
|
||||
#else
|
||||
|
||||
ssize_t res;
|
||||
|
||||
do
|
||||
{
|
||||
res = write(1, data, (size_t)size);
|
||||
}
|
||||
while (res < 0 && (errno == EINTR));
|
||||
|
||||
if (res == -1)
|
||||
return E_FAIL;
|
||||
|
||||
_size += (size_t)res;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,166 +1,166 @@
|
||||
// FileStreams.h
|
||||
|
||||
#ifndef __FILE_STREAMS_H
|
||||
#define __FILE_STREAMS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WIN_FILE
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#include "../../Windows/FileIO.h"
|
||||
#else
|
||||
#include "../../Common/C_FileIO.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR My_UINT_PTR;
|
||||
#else
|
||||
typedef UINT My_UINT_PTR;
|
||||
#endif
|
||||
|
||||
struct IInFileStream_Callback
|
||||
{
|
||||
virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0;
|
||||
virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0;
|
||||
};
|
||||
|
||||
class CInFileStream:
|
||||
public IInStream,
|
||||
public IStreamGetSize,
|
||||
#ifdef USE_WIN_FILE
|
||||
public IStreamGetProps,
|
||||
public IStreamGetProps2,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#ifdef USE_WIN_FILE
|
||||
NWindows::NFile::NIO::CInFile File;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
UInt64 VirtPos;
|
||||
UInt64 PhyPos;
|
||||
UInt64 BufStartPos;
|
||||
Byte *Buf;
|
||||
UInt32 BufSize;
|
||||
#endif
|
||||
|
||||
#else
|
||||
NC::NFile::NIO::CInFile File;
|
||||
#endif
|
||||
|
||||
bool SupportHardLinks;
|
||||
|
||||
IInFileStream_Callback *Callback;
|
||||
My_UINT_PTR CallbackRef;
|
||||
|
||||
virtual ~CInFileStream();
|
||||
|
||||
CInFileStream();
|
||||
|
||||
bool Open(CFSTR fileName)
|
||||
{
|
||||
return File.Open(fileName);
|
||||
}
|
||||
|
||||
bool OpenShared(CFSTR fileName, bool shareForWrite)
|
||||
{
|
||||
return File.OpenShared(fileName, shareForWrite);
|
||||
}
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetSize)
|
||||
#ifdef USE_WIN_FILE
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps2)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
STDMETHOD(GetSize)(UInt64 *size);
|
||||
#ifdef USE_WIN_FILE
|
||||
STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib);
|
||||
STDMETHOD(GetProps2)(CStreamFileProps *props);
|
||||
#endif
|
||||
};
|
||||
|
||||
class CStdInFileStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
virtual ~CStdInFileStream() {}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class COutFileStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#ifdef USE_WIN_FILE
|
||||
NWindows::NFile::NIO::COutFile File;
|
||||
#else
|
||||
NC::NFile::NIO::COutFile File;
|
||||
#endif
|
||||
virtual ~COutFileStream() {}
|
||||
bool Create(CFSTR fileName, bool createAlways)
|
||||
{
|
||||
ProcessedSize = 0;
|
||||
return File.Create(fileName, createAlways);
|
||||
}
|
||||
bool Open(CFSTR fileName, DWORD creationDisposition)
|
||||
{
|
||||
ProcessedSize = 0;
|
||||
return File.Open(fileName, creationDisposition);
|
||||
}
|
||||
|
||||
HRESULT Close();
|
||||
|
||||
UInt64 ProcessedSize;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{
|
||||
return File.SetTime(cTime, aTime, mTime);
|
||||
}
|
||||
bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); }
|
||||
#endif
|
||||
|
||||
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
|
||||
HRESULT GetSize(UInt64 *size);
|
||||
};
|
||||
|
||||
class CStdOutFileStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _size;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
UInt64 GetSize() const { return _size; }
|
||||
CStdOutFileStream(): _size(0) {}
|
||||
virtual ~CStdOutFileStream() {}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// FileStreams.h
|
||||
|
||||
#ifndef __FILE_STREAMS_H
|
||||
#define __FILE_STREAMS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WIN_FILE
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#include "../../Windows/FileIO.h"
|
||||
#else
|
||||
#include "../../Common/C_FileIO.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR My_UINT_PTR;
|
||||
#else
|
||||
typedef UINT My_UINT_PTR;
|
||||
#endif
|
||||
|
||||
struct IInFileStream_Callback
|
||||
{
|
||||
virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0;
|
||||
virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0;
|
||||
};
|
||||
|
||||
class CInFileStream:
|
||||
public IInStream,
|
||||
public IStreamGetSize,
|
||||
#ifdef USE_WIN_FILE
|
||||
public IStreamGetProps,
|
||||
public IStreamGetProps2,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#ifdef USE_WIN_FILE
|
||||
NWindows::NFile::NIO::CInFile File;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
UInt64 VirtPos;
|
||||
UInt64 PhyPos;
|
||||
UInt64 BufStartPos;
|
||||
Byte *Buf;
|
||||
UInt32 BufSize;
|
||||
#endif
|
||||
|
||||
#else
|
||||
NC::NFile::NIO::CInFile File;
|
||||
#endif
|
||||
|
||||
bool SupportHardLinks;
|
||||
|
||||
IInFileStream_Callback *Callback;
|
||||
My_UINT_PTR CallbackRef;
|
||||
|
||||
virtual ~CInFileStream();
|
||||
|
||||
CInFileStream();
|
||||
|
||||
bool Open(CFSTR fileName)
|
||||
{
|
||||
return File.Open(fileName);
|
||||
}
|
||||
|
||||
bool OpenShared(CFSTR fileName, bool shareForWrite)
|
||||
{
|
||||
return File.OpenShared(fileName, shareForWrite);
|
||||
}
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetSize)
|
||||
#ifdef USE_WIN_FILE
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps2)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
STDMETHOD(GetSize)(UInt64 *size);
|
||||
#ifdef USE_WIN_FILE
|
||||
STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib);
|
||||
STDMETHOD(GetProps2)(CStreamFileProps *props);
|
||||
#endif
|
||||
};
|
||||
|
||||
class CStdInFileStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
virtual ~CStdInFileStream() {}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class COutFileStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#ifdef USE_WIN_FILE
|
||||
NWindows::NFile::NIO::COutFile File;
|
||||
#else
|
||||
NC::NFile::NIO::COutFile File;
|
||||
#endif
|
||||
virtual ~COutFileStream() {}
|
||||
bool Create(CFSTR fileName, bool createAlways)
|
||||
{
|
||||
ProcessedSize = 0;
|
||||
return File.Create(fileName, createAlways);
|
||||
}
|
||||
bool Open(CFSTR fileName, DWORD creationDisposition)
|
||||
{
|
||||
ProcessedSize = 0;
|
||||
return File.Open(fileName, creationDisposition);
|
||||
}
|
||||
|
||||
HRESULT Close();
|
||||
|
||||
UInt64 ProcessedSize;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{
|
||||
return File.SetTime(cTime, aTime, mTime);
|
||||
}
|
||||
bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); }
|
||||
#endif
|
||||
|
||||
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
|
||||
HRESULT GetSize(UInt64 *size);
|
||||
};
|
||||
|
||||
class CStdOutFileStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _size;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
UInt64 GetSize() const { return _size; }
|
||||
CStdOutFileStream(): _size(0) {}
|
||||
virtual ~CStdOutFileStream() {}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,435 +1,435 @@
|
||||
// FilterCoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "FilterCoder.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define alignedMidBuffer_Alloc g_MidAlloc
|
||||
#else
|
||||
#define alignedMidBuffer_Alloc g_AlignedAlloc
|
||||
#endif
|
||||
|
||||
CAlignedMidBuffer::~CAlignedMidBuffer()
|
||||
{
|
||||
ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);
|
||||
}
|
||||
|
||||
void CAlignedMidBuffer::AllocAligned(size_t size)
|
||||
{
|
||||
ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);
|
||||
_buf = (Byte *)ISzAlloc_Alloc(&alignedMidBuffer_Alloc, size);
|
||||
}
|
||||
|
||||
/*
|
||||
AES filters need 16-bytes alignment for HARDWARE-AES instructions.
|
||||
So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block.
|
||||
|
||||
AES-CBC filters need data size aligned for 16-bytes.
|
||||
So the encoder can add zeros to the end of original stream.
|
||||
|
||||
Some filters (BCJ and others) don't process data at the end of stream in some cases.
|
||||
So the encoder and decoder write such last bytes without change.
|
||||
*/
|
||||
|
||||
|
||||
static const UInt32 kBufSize = 1 << 20;
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
|
||||
|
||||
HRESULT CFilterCoder::Alloc()
|
||||
{
|
||||
UInt32 size = MyMin(_inBufSize, _outBufSize);
|
||||
/* minimal bufSize is 16 bytes for AES and IA64 filter.
|
||||
bufSize for AES must be aligned for 16 bytes.
|
||||
We use (1 << 12) min size to support future aligned filters. */
|
||||
const UInt32 kMinSize = 1 << 12;
|
||||
size &= ~(UInt32)(kMinSize - 1);
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
if (!_buf || _bufSize != size)
|
||||
{
|
||||
AllocAligned(size);
|
||||
if (!_buf)
|
||||
return E_OUTOFMEMORY;
|
||||
_bufSize = size;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Init_and_Alloc()
|
||||
{
|
||||
RINOK(Filter->Init());
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
CFilterCoder::CFilterCoder(bool encodeMode):
|
||||
_bufSize(0),
|
||||
_inBufSize(kBufSize),
|
||||
_outBufSize(kBufSize),
|
||||
_encodeMode(encodeMode),
|
||||
_outSizeIsDefined(false),
|
||||
_outSize(0),
|
||||
_nowPos64(0)
|
||||
{}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(Init_and_Alloc());
|
||||
|
||||
UInt64 nowPos64 = 0;
|
||||
bool inputFinished = false;
|
||||
UInt32 pos = 0;
|
||||
|
||||
while (!outSize || nowPos64 < *outSize)
|
||||
{
|
||||
UInt32 endPos = pos;
|
||||
|
||||
if (!inputFinished)
|
||||
{
|
||||
size_t processedSize = _bufSize - pos;
|
||||
RINOK(ReadStream(inStream, _buf + pos, &processedSize));
|
||||
endPos = pos + (UInt32)processedSize;
|
||||
inputFinished = (endPos != _bufSize);
|
||||
}
|
||||
|
||||
pos = Filter->Filter(_buf, endPos);
|
||||
|
||||
if (pos > endPos)
|
||||
{
|
||||
// AES
|
||||
if (!inputFinished || pos > _bufSize)
|
||||
return E_FAIL;
|
||||
if (!_encodeMode)
|
||||
return S_FALSE;
|
||||
|
||||
do
|
||||
_buf[endPos] = 0;
|
||||
while (++endPos != pos);
|
||||
|
||||
if (pos != Filter->Filter(_buf, pos))
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (endPos == 0)
|
||||
return S_OK;
|
||||
|
||||
UInt32 size = (pos != 0 ? pos : endPos);
|
||||
if (outSize)
|
||||
{
|
||||
UInt64 remSize = *outSize - nowPos64;
|
||||
if (size > remSize)
|
||||
size = (UInt32)remSize;
|
||||
}
|
||||
|
||||
RINOK(WriteStream(outStream, _buf, size));
|
||||
nowPos64 += size;
|
||||
|
||||
if (pos == 0)
|
||||
return S_OK;
|
||||
|
||||
if (progress)
|
||||
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
|
||||
|
||||
UInt32 i = 0;
|
||||
while (pos < endPos)
|
||||
_buf[i++] = _buf[pos++];
|
||||
pos = i;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Write to Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
_outStream = outStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseOutStream()
|
||||
{
|
||||
_outStream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Flush2()
|
||||
{
|
||||
while (_convSize != 0)
|
||||
{
|
||||
UInt32 num = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
if (num > rem)
|
||||
num = (UInt32)rem;
|
||||
if (num == 0)
|
||||
return k_My_HRESULT_WritingWasCut;
|
||||
}
|
||||
|
||||
UInt32 processed = 0;
|
||||
HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);
|
||||
if (processed == 0)
|
||||
return res != S_OK ? res : E_FAIL;
|
||||
|
||||
_convPos += processed;
|
||||
_convSize -= processed;
|
||||
_nowPos64 += processed;
|
||||
RINOK(res);
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
|
||||
// _convSize is 0
|
||||
// _convPos is 0
|
||||
// _bufPos is small
|
||||
|
||||
if (_bufPos != _bufSize)
|
||||
{
|
||||
UInt32 num = MyMin(size, _bufSize - _bufPos);
|
||||
memcpy(_buf + _bufPos, data, num);
|
||||
size -= num;
|
||||
data = (const Byte *)data + num;
|
||||
if (processedSize)
|
||||
*processedSize += num;
|
||||
_bufPos += num;
|
||||
if (_bufPos != _bufSize)
|
||||
continue;
|
||||
}
|
||||
|
||||
// _bufPos == _bufSize
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
|
||||
if (_convSize == 0)
|
||||
break;
|
||||
if (_convSize > _bufPos)
|
||||
{
|
||||
// that case is not possible.
|
||||
_convSize = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::OutStreamFinish()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
if (_bufPos == 0)
|
||||
break;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
if (_convSize == 0)
|
||||
_convSize = _bufPos;
|
||||
else if (_convSize > _bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
{
|
||||
_convSize = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!_encodeMode)
|
||||
{
|
||||
_convSize = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
for (; _bufPos < _convSize; _bufPos++)
|
||||
_buf[_bufPos] = 0;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
CMyComPtr<IOutStreamFinish> finish;
|
||||
_outStream.QueryInterface(IID_IOutStreamFinish, &finish);
|
||||
if (finish)
|
||||
return finish->OutStreamFinish();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ---------- Init functions ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::InitEncoder()
|
||||
{
|
||||
InitSpecVars();
|
||||
return Init_and_Alloc();
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Init_NoSubFilterInit()
|
||||
{
|
||||
InitSpecVars();
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
InitSpecVars();
|
||||
if (outSize)
|
||||
{
|
||||
_outSize = *outSize;
|
||||
_outSizeIsDefined = true;
|
||||
}
|
||||
return Init_and_Alloc();
|
||||
}
|
||||
|
||||
// ---------- Read from Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
|
||||
{
|
||||
_inStream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseInStream()
|
||||
{
|
||||
_inStream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (_convSize != 0)
|
||||
{
|
||||
if (size > _convSize)
|
||||
size = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
memcpy(data, _buf + _convPos, size);
|
||||
_convPos += size;
|
||||
_convSize -= size;
|
||||
_nowPos64 += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
|
||||
{
|
||||
size_t readSize = _bufSize - _bufPos;
|
||||
HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);
|
||||
_bufPos += (UInt32)readSize;
|
||||
RINOK(res);
|
||||
}
|
||||
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
|
||||
if (_convSize == 0)
|
||||
{
|
||||
if (_bufPos == 0)
|
||||
break;
|
||||
// BCJ
|
||||
_convSize = _bufPos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_convSize > _bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
return E_FAIL;
|
||||
if (!_encodeMode)
|
||||
return S_FALSE;
|
||||
|
||||
do
|
||||
_buf[_bufPos] = 0;
|
||||
while (++_bufPos != _convSize);
|
||||
|
||||
_convSize = Filter->Filter(_buf, _convSize);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{ return _SetPassword->CryptoSetPassword(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetKey(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetInitVector(data, size); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties)
|
||||
{ return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{ return _WriteCoderProperties->WriteCoderProperties(outStream); }
|
||||
|
||||
/*
|
||||
STDMETHODIMP CFilterCoder::ResetSalt()
|
||||
{ return _CryptoResetSalt->ResetSalt(); }
|
||||
*/
|
||||
|
||||
STDMETHODIMP CFilterCoder::ResetInitVector()
|
||||
{ return _CryptoResetInitVector->ResetInitVector(); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{ return _SetDecoderProperties2->SetDecoderProperties2(data, size); }
|
||||
// FilterCoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "FilterCoder.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define alignedMidBuffer_Alloc g_MidAlloc
|
||||
#else
|
||||
#define alignedMidBuffer_Alloc g_AlignedAlloc
|
||||
#endif
|
||||
|
||||
CAlignedMidBuffer::~CAlignedMidBuffer()
|
||||
{
|
||||
ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);
|
||||
}
|
||||
|
||||
void CAlignedMidBuffer::AllocAligned(size_t size)
|
||||
{
|
||||
ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);
|
||||
_buf = (Byte *)ISzAlloc_Alloc(&alignedMidBuffer_Alloc, size);
|
||||
}
|
||||
|
||||
/*
|
||||
AES filters need 16-bytes alignment for HARDWARE-AES instructions.
|
||||
So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block.
|
||||
|
||||
AES-CBC filters need data size aligned for 16-bytes.
|
||||
So the encoder can add zeros to the end of original stream.
|
||||
|
||||
Some filters (BCJ and others) don't process data at the end of stream in some cases.
|
||||
So the encoder and decoder write such last bytes without change.
|
||||
*/
|
||||
|
||||
|
||||
static const UInt32 kBufSize = 1 << 20;
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
|
||||
|
||||
HRESULT CFilterCoder::Alloc()
|
||||
{
|
||||
UInt32 size = MyMin(_inBufSize, _outBufSize);
|
||||
/* minimal bufSize is 16 bytes for AES and IA64 filter.
|
||||
bufSize for AES must be aligned for 16 bytes.
|
||||
We use (1 << 12) min size to support future aligned filters. */
|
||||
const UInt32 kMinSize = 1 << 12;
|
||||
size &= ~(UInt32)(kMinSize - 1);
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
if (!_buf || _bufSize != size)
|
||||
{
|
||||
AllocAligned(size);
|
||||
if (!_buf)
|
||||
return E_OUTOFMEMORY;
|
||||
_bufSize = size;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Init_and_Alloc()
|
||||
{
|
||||
RINOK(Filter->Init());
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
CFilterCoder::CFilterCoder(bool encodeMode):
|
||||
_bufSize(0),
|
||||
_inBufSize(kBufSize),
|
||||
_outBufSize(kBufSize),
|
||||
_encodeMode(encodeMode),
|
||||
_outSizeIsDefined(false),
|
||||
_outSize(0),
|
||||
_nowPos64(0)
|
||||
{}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(Init_and_Alloc());
|
||||
|
||||
UInt64 nowPos64 = 0;
|
||||
bool inputFinished = false;
|
||||
UInt32 pos = 0;
|
||||
|
||||
while (!outSize || nowPos64 < *outSize)
|
||||
{
|
||||
UInt32 endPos = pos;
|
||||
|
||||
if (!inputFinished)
|
||||
{
|
||||
size_t processedSize = _bufSize - pos;
|
||||
RINOK(ReadStream(inStream, _buf + pos, &processedSize));
|
||||
endPos = pos + (UInt32)processedSize;
|
||||
inputFinished = (endPos != _bufSize);
|
||||
}
|
||||
|
||||
pos = Filter->Filter(_buf, endPos);
|
||||
|
||||
if (pos > endPos)
|
||||
{
|
||||
// AES
|
||||
if (!inputFinished || pos > _bufSize)
|
||||
return E_FAIL;
|
||||
if (!_encodeMode)
|
||||
return S_FALSE;
|
||||
|
||||
do
|
||||
_buf[endPos] = 0;
|
||||
while (++endPos != pos);
|
||||
|
||||
if (pos != Filter->Filter(_buf, pos))
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (endPos == 0)
|
||||
return S_OK;
|
||||
|
||||
UInt32 size = (pos != 0 ? pos : endPos);
|
||||
if (outSize)
|
||||
{
|
||||
UInt64 remSize = *outSize - nowPos64;
|
||||
if (size > remSize)
|
||||
size = (UInt32)remSize;
|
||||
}
|
||||
|
||||
RINOK(WriteStream(outStream, _buf, size));
|
||||
nowPos64 += size;
|
||||
|
||||
if (pos == 0)
|
||||
return S_OK;
|
||||
|
||||
if (progress)
|
||||
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
|
||||
|
||||
UInt32 i = 0;
|
||||
while (pos < endPos)
|
||||
_buf[i++] = _buf[pos++];
|
||||
pos = i;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Write to Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
_outStream = outStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseOutStream()
|
||||
{
|
||||
_outStream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Flush2()
|
||||
{
|
||||
while (_convSize != 0)
|
||||
{
|
||||
UInt32 num = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
if (num > rem)
|
||||
num = (UInt32)rem;
|
||||
if (num == 0)
|
||||
return k_My_HRESULT_WritingWasCut;
|
||||
}
|
||||
|
||||
UInt32 processed = 0;
|
||||
HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);
|
||||
if (processed == 0)
|
||||
return res != S_OK ? res : E_FAIL;
|
||||
|
||||
_convPos += processed;
|
||||
_convSize -= processed;
|
||||
_nowPos64 += processed;
|
||||
RINOK(res);
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
|
||||
// _convSize is 0
|
||||
// _convPos is 0
|
||||
// _bufPos is small
|
||||
|
||||
if (_bufPos != _bufSize)
|
||||
{
|
||||
UInt32 num = MyMin(size, _bufSize - _bufPos);
|
||||
memcpy(_buf + _bufPos, data, num);
|
||||
size -= num;
|
||||
data = (const Byte *)data + num;
|
||||
if (processedSize)
|
||||
*processedSize += num;
|
||||
_bufPos += num;
|
||||
if (_bufPos != _bufSize)
|
||||
continue;
|
||||
}
|
||||
|
||||
// _bufPos == _bufSize
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
|
||||
if (_convSize == 0)
|
||||
break;
|
||||
if (_convSize > _bufPos)
|
||||
{
|
||||
// that case is not possible.
|
||||
_convSize = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::OutStreamFinish()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
if (_bufPos == 0)
|
||||
break;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
if (_convSize == 0)
|
||||
_convSize = _bufPos;
|
||||
else if (_convSize > _bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
{
|
||||
_convSize = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!_encodeMode)
|
||||
{
|
||||
_convSize = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
for (; _bufPos < _convSize; _bufPos++)
|
||||
_buf[_bufPos] = 0;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
CMyComPtr<IOutStreamFinish> finish;
|
||||
_outStream.QueryInterface(IID_IOutStreamFinish, &finish);
|
||||
if (finish)
|
||||
return finish->OutStreamFinish();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ---------- Init functions ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::InitEncoder()
|
||||
{
|
||||
InitSpecVars();
|
||||
return Init_and_Alloc();
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Init_NoSubFilterInit()
|
||||
{
|
||||
InitSpecVars();
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
InitSpecVars();
|
||||
if (outSize)
|
||||
{
|
||||
_outSize = *outSize;
|
||||
_outSizeIsDefined = true;
|
||||
}
|
||||
return Init_and_Alloc();
|
||||
}
|
||||
|
||||
// ---------- Read from Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
|
||||
{
|
||||
_inStream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseInStream()
|
||||
{
|
||||
_inStream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (_convSize != 0)
|
||||
{
|
||||
if (size > _convSize)
|
||||
size = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
memcpy(data, _buf + _convPos, size);
|
||||
_convPos += size;
|
||||
_convSize -= size;
|
||||
_nowPos64 += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
|
||||
{
|
||||
size_t readSize = _bufSize - _bufPos;
|
||||
HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);
|
||||
_bufPos += (UInt32)readSize;
|
||||
RINOK(res);
|
||||
}
|
||||
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
|
||||
if (_convSize == 0)
|
||||
{
|
||||
if (_bufPos == 0)
|
||||
break;
|
||||
// BCJ
|
||||
_convSize = _bufPos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_convSize > _bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
return E_FAIL;
|
||||
if (!_encodeMode)
|
||||
return S_FALSE;
|
||||
|
||||
do
|
||||
_buf[_bufPos] = 0;
|
||||
while (++_bufPos != _convSize);
|
||||
|
||||
_convSize = Filter->Filter(_buf, _convSize);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{ return _SetPassword->CryptoSetPassword(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetKey(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetInitVector(data, size); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties)
|
||||
{ return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{ return _WriteCoderProperties->WriteCoderProperties(outStream); }
|
||||
|
||||
/*
|
||||
STDMETHODIMP CFilterCoder::ResetSalt()
|
||||
{ return _CryptoResetSalt->ResetSalt(); }
|
||||
*/
|
||||
|
||||
STDMETHODIMP CFilterCoder::ResetInitVector()
|
||||
{ return _CryptoResetInitVector->ResetInitVector(); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{ return _SetDecoderProperties2->SetDecoderProperties2(data, size); }
|
||||
|
||||
@@ -1,205 +1,205 @@
|
||||
// FilterCoder.h
|
||||
|
||||
#ifndef __FILTER_CODER_H
|
||||
#define __FILTER_CODER_H
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#include "../IPassword.h"
|
||||
#endif
|
||||
|
||||
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \
|
||||
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
|
||||
*outObject = (void *)(i *)this; }
|
||||
|
||||
|
||||
struct CAlignedMidBuffer
|
||||
{
|
||||
Byte *_buf;
|
||||
|
||||
CAlignedMidBuffer(): _buf(NULL) {}
|
||||
~CAlignedMidBuffer();
|
||||
void AllocAligned(size_t size);
|
||||
};
|
||||
|
||||
class CFilterCoder:
|
||||
public ICompressCoder,
|
||||
|
||||
public ICompressSetOutStreamSize,
|
||||
public ICompressInitEncoder,
|
||||
|
||||
public ICompressSetInStream,
|
||||
public ISequentialInStream,
|
||||
|
||||
public ICompressSetOutStream,
|
||||
public ISequentialOutStream,
|
||||
public IOutStreamFinish,
|
||||
|
||||
public ICompressSetBufSize,
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoSetPassword,
|
||||
public ICryptoProperties,
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressWriteCoderProperties,
|
||||
// public ICryptoResetSalt,
|
||||
public ICryptoResetInitVector,
|
||||
#endif
|
||||
|
||||
public ICompressSetDecoderProperties2,
|
||||
public CMyUnknownImp,
|
||||
public CAlignedMidBuffer
|
||||
{
|
||||
UInt32 _bufSize;
|
||||
UInt32 _inBufSize;
|
||||
UInt32 _outBufSize;
|
||||
|
||||
bool _encodeMode;
|
||||
bool _outSizeIsDefined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _nowPos64;
|
||||
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
UInt32 _bufPos;
|
||||
UInt32 _convPos; // current pos in buffer for converted data
|
||||
UInt32 _convSize; // size of converted data starting from _convPos
|
||||
|
||||
void InitSpecVars()
|
||||
{
|
||||
_bufPos = 0;
|
||||
_convPos = 0;
|
||||
_convSize = 0;
|
||||
|
||||
_outSizeIsDefined = false;
|
||||
_outSize = 0;
|
||||
_nowPos64 = 0;
|
||||
}
|
||||
|
||||
HRESULT Alloc();
|
||||
HRESULT Init_and_Alloc();
|
||||
HRESULT Flush2();
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoSetPassword> _SetPassword;
|
||||
CMyComPtr<ICryptoProperties> _CryptoProperties;
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
|
||||
CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;
|
||||
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
|
||||
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
|
||||
#endif
|
||||
|
||||
CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;
|
||||
|
||||
public:
|
||||
CMyComPtr<ICompressFilter> Filter;
|
||||
|
||||
CFilterCoder(bool encodeMode);
|
||||
~CFilterCoder();
|
||||
|
||||
class C_InStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_InStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
|
||||
};
|
||||
|
||||
class C_OutStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_OutStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
|
||||
};
|
||||
|
||||
class C_Filter_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_Filter_Releaser(): FilterCoder(NULL) {}
|
||||
~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }
|
||||
};
|
||||
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutStreamFinish)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties)
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties)
|
||||
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(InitEncoder)();
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(OutStreamFinish)();
|
||||
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties);
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
// STDMETHOD(ResetSalt)();
|
||||
STDMETHOD(ResetInitVector)();
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
|
||||
|
||||
HRESULT Init_NoSubFilterInit();
|
||||
};
|
||||
|
||||
#endif
|
||||
// FilterCoder.h
|
||||
|
||||
#ifndef __FILTER_CODER_H
|
||||
#define __FILTER_CODER_H
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#include "../IPassword.h"
|
||||
#endif
|
||||
|
||||
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \
|
||||
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
|
||||
*outObject = (void *)(i *)this; }
|
||||
|
||||
|
||||
struct CAlignedMidBuffer
|
||||
{
|
||||
Byte *_buf;
|
||||
|
||||
CAlignedMidBuffer(): _buf(NULL) {}
|
||||
~CAlignedMidBuffer();
|
||||
void AllocAligned(size_t size);
|
||||
};
|
||||
|
||||
class CFilterCoder:
|
||||
public ICompressCoder,
|
||||
|
||||
public ICompressSetOutStreamSize,
|
||||
public ICompressInitEncoder,
|
||||
|
||||
public ICompressSetInStream,
|
||||
public ISequentialInStream,
|
||||
|
||||
public ICompressSetOutStream,
|
||||
public ISequentialOutStream,
|
||||
public IOutStreamFinish,
|
||||
|
||||
public ICompressSetBufSize,
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoSetPassword,
|
||||
public ICryptoProperties,
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressWriteCoderProperties,
|
||||
// public ICryptoResetSalt,
|
||||
public ICryptoResetInitVector,
|
||||
#endif
|
||||
|
||||
public ICompressSetDecoderProperties2,
|
||||
public CMyUnknownImp,
|
||||
public CAlignedMidBuffer
|
||||
{
|
||||
UInt32 _bufSize;
|
||||
UInt32 _inBufSize;
|
||||
UInt32 _outBufSize;
|
||||
|
||||
bool _encodeMode;
|
||||
bool _outSizeIsDefined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _nowPos64;
|
||||
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
UInt32 _bufPos;
|
||||
UInt32 _convPos; // current pos in buffer for converted data
|
||||
UInt32 _convSize; // size of converted data starting from _convPos
|
||||
|
||||
void InitSpecVars()
|
||||
{
|
||||
_bufPos = 0;
|
||||
_convPos = 0;
|
||||
_convSize = 0;
|
||||
|
||||
_outSizeIsDefined = false;
|
||||
_outSize = 0;
|
||||
_nowPos64 = 0;
|
||||
}
|
||||
|
||||
HRESULT Alloc();
|
||||
HRESULT Init_and_Alloc();
|
||||
HRESULT Flush2();
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoSetPassword> _SetPassword;
|
||||
CMyComPtr<ICryptoProperties> _CryptoProperties;
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
|
||||
CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;
|
||||
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
|
||||
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
|
||||
#endif
|
||||
|
||||
CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;
|
||||
|
||||
public:
|
||||
CMyComPtr<ICompressFilter> Filter;
|
||||
|
||||
CFilterCoder(bool encodeMode);
|
||||
~CFilterCoder();
|
||||
|
||||
class C_InStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_InStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
|
||||
};
|
||||
|
||||
class C_OutStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_OutStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
|
||||
};
|
||||
|
||||
class C_Filter_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_Filter_Releaser(): FilterCoder(NULL) {}
|
||||
~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }
|
||||
};
|
||||
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutStreamFinish)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties)
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties)
|
||||
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(InitEncoder)();
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(OutStreamFinish)();
|
||||
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties);
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
// STDMETHOD(ResetSalt)();
|
||||
STDMETHOD(ResetInitVector)();
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
|
||||
|
||||
HRESULT Init_NoSubFilterInit();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,163 +1,163 @@
|
||||
// InBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "InBuffer.h"
|
||||
|
||||
CInBufferBase::CInBufferBase() throw():
|
||||
_buf(0),
|
||||
_bufLim(0),
|
||||
_bufBase(0),
|
||||
_stream(0),
|
||||
_processedSize(0),
|
||||
_bufSize(0),
|
||||
_wasFinished(false),
|
||||
NumExtraBytes(0)
|
||||
{}
|
||||
|
||||
bool CInBuffer::Create(size_t bufSize) throw()
|
||||
{
|
||||
const unsigned kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_bufBase != 0 && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_bufBase = (Byte *)::MidAlloc(bufSize);
|
||||
return (_bufBase != 0);
|
||||
}
|
||||
|
||||
void CInBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_bufBase);
|
||||
_bufBase = 0;
|
||||
}
|
||||
|
||||
void CInBufferBase::Init() throw()
|
||||
{
|
||||
_processedSize = 0;
|
||||
_buf = _bufBase;
|
||||
_bufLim = _buf;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
}
|
||||
|
||||
bool CInBufferBase::ReadBlock()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return false;
|
||||
#endif
|
||||
if (_wasFinished)
|
||||
return false;
|
||||
_processedSize += (_buf - _bufBase);
|
||||
_buf = _bufBase;
|
||||
_bufLim = _bufBase;
|
||||
UInt32 processed;
|
||||
// FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
|
||||
HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
throw CInBufferException(result);
|
||||
#endif
|
||||
_bufLim = _buf + processed;
|
||||
_wasFinished = (processed == 0);
|
||||
return !_wasFinished;
|
||||
}
|
||||
|
||||
bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
|
||||
{
|
||||
if (!ReadBlock())
|
||||
{
|
||||
NumExtraBytes++;
|
||||
b = 0xFF;
|
||||
return false;
|
||||
}
|
||||
b = *_buf++;
|
||||
return true;
|
||||
}
|
||||
|
||||
Byte CInBufferBase::ReadByte_FromNewBlock()
|
||||
{
|
||||
if (!ReadBlock())
|
||||
{
|
||||
NumExtraBytes++;
|
||||
return 0xFF;
|
||||
}
|
||||
return *_buf++;
|
||||
}
|
||||
|
||||
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (;;)
|
||||
{
|
||||
const size_t rem = _bufLim - _buf;
|
||||
if (size <= rem)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(buf, _buf, size);
|
||||
_buf += size;
|
||||
num += size;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
if (rem != 0)
|
||||
{
|
||||
memcpy(buf, _buf, rem);
|
||||
_buf += rem;
|
||||
buf += rem;
|
||||
num += rem;
|
||||
size -= rem;
|
||||
}
|
||||
if (!ReadBlock())
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
if ((size_t)(_bufLim - _buf) >= size)
|
||||
{
|
||||
const Byte *src = _buf;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buf[i] = src[i];
|
||||
_buf += size;
|
||||
return size;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
if (!ReadBlock())
|
||||
return i;
|
||||
buf[i] = *_buf++;
|
||||
}
|
||||
return size;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CInBufferBase::Skip(size_t size)
|
||||
{
|
||||
size_t processed = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t rem = (_bufLim - _buf);
|
||||
if (rem >= size)
|
||||
{
|
||||
_buf += size;
|
||||
return processed + size;
|
||||
}
|
||||
_buf += rem;
|
||||
processed += rem;
|
||||
size -= rem;
|
||||
if (!ReadBlock())
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
// InBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "InBuffer.h"
|
||||
|
||||
CInBufferBase::CInBufferBase() throw():
|
||||
_buf(0),
|
||||
_bufLim(0),
|
||||
_bufBase(0),
|
||||
_stream(0),
|
||||
_processedSize(0),
|
||||
_bufSize(0),
|
||||
_wasFinished(false),
|
||||
NumExtraBytes(0)
|
||||
{}
|
||||
|
||||
bool CInBuffer::Create(size_t bufSize) throw()
|
||||
{
|
||||
const unsigned kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_bufBase != 0 && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_bufBase = (Byte *)::MidAlloc(bufSize);
|
||||
return (_bufBase != 0);
|
||||
}
|
||||
|
||||
void CInBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_bufBase);
|
||||
_bufBase = 0;
|
||||
}
|
||||
|
||||
void CInBufferBase::Init() throw()
|
||||
{
|
||||
_processedSize = 0;
|
||||
_buf = _bufBase;
|
||||
_bufLim = _buf;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
}
|
||||
|
||||
bool CInBufferBase::ReadBlock()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return false;
|
||||
#endif
|
||||
if (_wasFinished)
|
||||
return false;
|
||||
_processedSize += (_buf - _bufBase);
|
||||
_buf = _bufBase;
|
||||
_bufLim = _bufBase;
|
||||
UInt32 processed;
|
||||
// FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
|
||||
HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
throw CInBufferException(result);
|
||||
#endif
|
||||
_bufLim = _buf + processed;
|
||||
_wasFinished = (processed == 0);
|
||||
return !_wasFinished;
|
||||
}
|
||||
|
||||
bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
|
||||
{
|
||||
if (!ReadBlock())
|
||||
{
|
||||
NumExtraBytes++;
|
||||
b = 0xFF;
|
||||
return false;
|
||||
}
|
||||
b = *_buf++;
|
||||
return true;
|
||||
}
|
||||
|
||||
Byte CInBufferBase::ReadByte_FromNewBlock()
|
||||
{
|
||||
if (!ReadBlock())
|
||||
{
|
||||
NumExtraBytes++;
|
||||
return 0xFF;
|
||||
}
|
||||
return *_buf++;
|
||||
}
|
||||
|
||||
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (;;)
|
||||
{
|
||||
const size_t rem = _bufLim - _buf;
|
||||
if (size <= rem)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(buf, _buf, size);
|
||||
_buf += size;
|
||||
num += size;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
if (rem != 0)
|
||||
{
|
||||
memcpy(buf, _buf, rem);
|
||||
_buf += rem;
|
||||
buf += rem;
|
||||
num += rem;
|
||||
size -= rem;
|
||||
}
|
||||
if (!ReadBlock())
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
if ((size_t)(_bufLim - _buf) >= size)
|
||||
{
|
||||
const Byte *src = _buf;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buf[i] = src[i];
|
||||
_buf += size;
|
||||
return size;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
if (!ReadBlock())
|
||||
return i;
|
||||
buf[i] = *_buf++;
|
||||
}
|
||||
return size;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CInBufferBase::Skip(size_t size)
|
||||
{
|
||||
size_t processed = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t rem = (_bufLim - _buf);
|
||||
if (rem >= size)
|
||||
{
|
||||
_buf += size;
|
||||
return processed + size;
|
||||
}
|
||||
_buf += rem;
|
||||
processed += rem;
|
||||
size -= rem;
|
||||
if (!ReadBlock())
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
// InBuffer.h
|
||||
|
||||
#ifndef __IN_BUFFER_H
|
||||
#define __IN_BUFFER_H
|
||||
|
||||
#include "../../Common/MyException.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
struct CInBufferException: public CSystemException
|
||||
{
|
||||
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class CInBufferBase
|
||||
{
|
||||
protected:
|
||||
Byte *_buf;
|
||||
Byte *_bufLim;
|
||||
Byte *_bufBase;
|
||||
|
||||
ISequentialInStream *_stream;
|
||||
UInt64 _processedSize;
|
||||
size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger
|
||||
// only up to 32-bits values now are supported!
|
||||
bool _wasFinished;
|
||||
|
||||
bool ReadBlock();
|
||||
bool ReadByte_FromNewBlock(Byte &b);
|
||||
Byte ReadByte_FromNewBlock();
|
||||
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
UInt32 NumExtraBytes;
|
||||
|
||||
CInBufferBase() throw();
|
||||
|
||||
UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); }
|
||||
UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
|
||||
void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)
|
||||
{
|
||||
_bufBase = buf;
|
||||
_bufSize = bufSize;
|
||||
_processedSize = 0;
|
||||
_buf = buf + pos;
|
||||
_bufLim = buf + end;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
}
|
||||
|
||||
void Init() throw();
|
||||
|
||||
MY_FORCE_INLINE
|
||||
bool ReadByte(Byte &b)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
return ReadByte_FromNewBlock(b);
|
||||
b = *_buf++;
|
||||
return true;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
return ReadByte_FromNewBlock();
|
||||
return *_buf++;
|
||||
}
|
||||
|
||||
size_t ReadBytes(Byte *buf, size_t size);
|
||||
size_t Skip(size_t size);
|
||||
};
|
||||
|
||||
class CInBuffer: public CInBufferBase
|
||||
{
|
||||
public:
|
||||
~CInBuffer() { Free(); }
|
||||
bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported!
|
||||
void Free() throw();
|
||||
};
|
||||
|
||||
#endif
|
||||
// InBuffer.h
|
||||
|
||||
#ifndef __IN_BUFFER_H
|
||||
#define __IN_BUFFER_H
|
||||
|
||||
#include "../../Common/MyException.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
struct CInBufferException: public CSystemException
|
||||
{
|
||||
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class CInBufferBase
|
||||
{
|
||||
protected:
|
||||
Byte *_buf;
|
||||
Byte *_bufLim;
|
||||
Byte *_bufBase;
|
||||
|
||||
ISequentialInStream *_stream;
|
||||
UInt64 _processedSize;
|
||||
size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger
|
||||
// only up to 32-bits values now are supported!
|
||||
bool _wasFinished;
|
||||
|
||||
bool ReadBlock();
|
||||
bool ReadByte_FromNewBlock(Byte &b);
|
||||
Byte ReadByte_FromNewBlock();
|
||||
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
UInt32 NumExtraBytes;
|
||||
|
||||
CInBufferBase() throw();
|
||||
|
||||
UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); }
|
||||
UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
|
||||
void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)
|
||||
{
|
||||
_bufBase = buf;
|
||||
_bufSize = bufSize;
|
||||
_processedSize = 0;
|
||||
_buf = buf + pos;
|
||||
_bufLim = buf + end;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
}
|
||||
|
||||
void Init() throw();
|
||||
|
||||
MY_FORCE_INLINE
|
||||
bool ReadByte(Byte &b)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
return ReadByte_FromNewBlock(b);
|
||||
b = *_buf++;
|
||||
return true;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
return ReadByte_FromNewBlock();
|
||||
return *_buf++;
|
||||
}
|
||||
|
||||
size_t ReadBytes(Byte *buf, size_t size);
|
||||
size_t Skip(size_t size);
|
||||
};
|
||||
|
||||
class CInBuffer: public CInBufferBase
|
||||
{
|
||||
public:
|
||||
~CInBuffer() { Free(); }
|
||||
bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported!
|
||||
void Free() throw();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
// InOutTempBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "InOutTempBuffer.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static const size_t kTempBufSize = (1 << 20);
|
||||
|
||||
#define kTempFilePrefixString FTEXT("7zt")
|
||||
|
||||
CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
|
||||
|
||||
void CInOutTempBuffer::Create()
|
||||
{
|
||||
if (!_buf)
|
||||
_buf = new Byte[kTempBufSize];
|
||||
}
|
||||
|
||||
CInOutTempBuffer::~CInOutTempBuffer()
|
||||
{
|
||||
delete []_buf;
|
||||
}
|
||||
|
||||
void CInOutTempBuffer::InitWriting()
|
||||
{
|
||||
_bufPos = 0;
|
||||
_tempFileCreated = false;
|
||||
_size = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return true;
|
||||
if (!_tempFileCreated)
|
||||
{
|
||||
if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
|
||||
return false;
|
||||
_tempFileCreated = true;
|
||||
}
|
||||
UInt32 processed;
|
||||
if (!_outFile.Write(data, size, processed))
|
||||
return false;
|
||||
_crc = CrcUpdate(_crc, data, processed);
|
||||
_size += processed;
|
||||
return (processed == size);
|
||||
}
|
||||
|
||||
bool CInOutTempBuffer::Write(const void *data, UInt32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return true;
|
||||
size_t cur = kTempBufSize - _bufPos;
|
||||
if (cur != 0)
|
||||
{
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy(_buf + _bufPos, data, cur);
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
_bufPos += cur;
|
||||
_size += cur;
|
||||
size -= (UInt32)cur;
|
||||
data = ((const Byte *)data) + cur;
|
||||
}
|
||||
return WriteToFile(data, size);
|
||||
}
|
||||
|
||||
HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
|
||||
{
|
||||
if (!_outFile.Close())
|
||||
return E_FAIL;
|
||||
|
||||
UInt64 size = 0;
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
|
||||
if (_bufPos != 0)
|
||||
{
|
||||
RINOK(WriteStream(stream, _buf, _bufPos));
|
||||
crc = CrcUpdate(crc, _buf, _bufPos);
|
||||
size += _bufPos;
|
||||
}
|
||||
|
||||
if (_tempFileCreated)
|
||||
{
|
||||
NIO::CInFile inFile;
|
||||
if (!inFile.Open(_tempFile.GetPath()))
|
||||
return E_FAIL;
|
||||
while (size < _size)
|
||||
{
|
||||
UInt32 processed;
|
||||
if (!inFile.ReadPart(_buf, kTempBufSize, processed))
|
||||
return E_FAIL;
|
||||
if (processed == 0)
|
||||
break;
|
||||
RINOK(WriteStream(stream, _buf, processed));
|
||||
crc = CrcUpdate(crc, _buf, processed);
|
||||
size += processed;
|
||||
}
|
||||
}
|
||||
|
||||
return (_crc == crc && size == _size) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (processed)
|
||||
*processed = size;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
// InOutTempBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "InOutTempBuffer.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static const size_t kTempBufSize = (1 << 20);
|
||||
|
||||
#define kTempFilePrefixString FTEXT("7zt")
|
||||
|
||||
CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
|
||||
|
||||
void CInOutTempBuffer::Create()
|
||||
{
|
||||
if (!_buf)
|
||||
_buf = new Byte[kTempBufSize];
|
||||
}
|
||||
|
||||
CInOutTempBuffer::~CInOutTempBuffer()
|
||||
{
|
||||
delete []_buf;
|
||||
}
|
||||
|
||||
void CInOutTempBuffer::InitWriting()
|
||||
{
|
||||
_bufPos = 0;
|
||||
_tempFileCreated = false;
|
||||
_size = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return true;
|
||||
if (!_tempFileCreated)
|
||||
{
|
||||
if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
|
||||
return false;
|
||||
_tempFileCreated = true;
|
||||
}
|
||||
UInt32 processed;
|
||||
if (!_outFile.Write(data, size, processed))
|
||||
return false;
|
||||
_crc = CrcUpdate(_crc, data, processed);
|
||||
_size += processed;
|
||||
return (processed == size);
|
||||
}
|
||||
|
||||
bool CInOutTempBuffer::Write(const void *data, UInt32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return true;
|
||||
size_t cur = kTempBufSize - _bufPos;
|
||||
if (cur != 0)
|
||||
{
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy(_buf + _bufPos, data, cur);
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
_bufPos += cur;
|
||||
_size += cur;
|
||||
size -= (UInt32)cur;
|
||||
data = ((const Byte *)data) + cur;
|
||||
}
|
||||
return WriteToFile(data, size);
|
||||
}
|
||||
|
||||
HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
|
||||
{
|
||||
if (!_outFile.Close())
|
||||
return E_FAIL;
|
||||
|
||||
UInt64 size = 0;
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
|
||||
if (_bufPos != 0)
|
||||
{
|
||||
RINOK(WriteStream(stream, _buf, _bufPos));
|
||||
crc = CrcUpdate(crc, _buf, _bufPos);
|
||||
size += _bufPos;
|
||||
}
|
||||
|
||||
if (_tempFileCreated)
|
||||
{
|
||||
NIO::CInFile inFile;
|
||||
if (!inFile.Open(_tempFile.GetPath()))
|
||||
return E_FAIL;
|
||||
while (size < _size)
|
||||
{
|
||||
UInt32 processed;
|
||||
if (!inFile.ReadPart(_buf, kTempBufSize, processed))
|
||||
return E_FAIL;
|
||||
if (processed == 0)
|
||||
break;
|
||||
RINOK(WriteStream(stream, _buf, processed));
|
||||
crc = CrcUpdate(crc, _buf, processed);
|
||||
size += processed;
|
||||
}
|
||||
}
|
||||
|
||||
return (_crc == crc && size == _size) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (processed)
|
||||
*processed = size;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
// InOutTempBuffer.h
|
||||
|
||||
#ifndef __IN_OUT_TEMP_BUFFER_H
|
||||
#define __IN_OUT_TEMP_BUFFER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Windows/FileDir.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CInOutTempBuffer
|
||||
{
|
||||
NWindows::NFile::NDir::CTempFile _tempFile;
|
||||
NWindows::NFile::NIO::COutFile _outFile;
|
||||
Byte *_buf;
|
||||
size_t _bufPos;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
bool _tempFileCreated;
|
||||
|
||||
bool WriteToFile(const void *data, UInt32 size);
|
||||
public:
|
||||
CInOutTempBuffer();
|
||||
~CInOutTempBuffer();
|
||||
void Create();
|
||||
|
||||
void InitWriting();
|
||||
bool Write(const void *data, UInt32 size);
|
||||
|
||||
HRESULT WriteToStream(ISequentialOutStream *stream);
|
||||
UInt64 GetDataSize() const { return _size; }
|
||||
};
|
||||
|
||||
/*
|
||||
class CSequentialOutTempBufferImp:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CInOutTempBuffer *_buf;
|
||||
public:
|
||||
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
// InOutTempBuffer.h
|
||||
|
||||
#ifndef __IN_OUT_TEMP_BUFFER_H
|
||||
#define __IN_OUT_TEMP_BUFFER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Windows/FileDir.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CInOutTempBuffer
|
||||
{
|
||||
NWindows::NFile::NDir::CTempFile _tempFile;
|
||||
NWindows::NFile::NIO::COutFile _outFile;
|
||||
Byte *_buf;
|
||||
size_t _bufPos;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
bool _tempFileCreated;
|
||||
|
||||
bool WriteToFile(const void *data, UInt32 size);
|
||||
public:
|
||||
CInOutTempBuffer();
|
||||
~CInOutTempBuffer();
|
||||
void Create();
|
||||
|
||||
void InitWriting();
|
||||
bool Write(const void *data, UInt32 size);
|
||||
|
||||
HRESULT WriteToStream(ISequentialOutStream *stream);
|
||||
UInt64 GetDataSize() const { return _size; }
|
||||
};
|
||||
|
||||
/*
|
||||
class CSequentialOutTempBufferImp:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CInOutTempBuffer *_buf;
|
||||
public:
|
||||
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,367 +1,367 @@
|
||||
// LimitedStreams.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "LimitedStreams.h"
|
||||
|
||||
STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
{
|
||||
const UInt64 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
HRESULT result = S_OK;
|
||||
if (size != 0)
|
||||
{
|
||||
result = _stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
if (realProcessedSize == 0)
|
||||
_wasFinished = true;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= _size)
|
||||
{
|
||||
// 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
|
||||
return S_OK;
|
||||
// return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
|
||||
}
|
||||
{
|
||||
const UInt64 rem = _size - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
UInt64 newPos = _startOffset + _virtPos;
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
HRESULT res = _stream->Read(data, size, &size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_physPos += size;
|
||||
_virtPos += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)
|
||||
{
|
||||
*resStream = 0;
|
||||
CLimitedInStream *streamSpec = new CLimitedInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->SetStream(inStream);
|
||||
RINOK(streamSpec->InitAndSeek(pos, size));
|
||||
streamSpec->SeekToStart();
|
||||
*resStream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= Size)
|
||||
return S_OK;
|
||||
{
|
||||
UInt64 rem = Size - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (_curRem == 0)
|
||||
{
|
||||
const UInt32 blockSize = (UInt32)1 << BlockSizeLog;
|
||||
const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
|
||||
const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
|
||||
const UInt32 phyBlock = Vector[virtBlock];
|
||||
|
||||
UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
|
||||
_curRem = blockSize - offsetInBlock;
|
||||
|
||||
for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
|
||||
_curRem += (UInt32)1 << BlockSizeLog;
|
||||
}
|
||||
|
||||
if (size > _curRem)
|
||||
size = _curRem;
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_physPos += size;
|
||||
_virtPos += size;
|
||||
_curRem -= size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += Size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
if (_virtPos != (UInt64)offset)
|
||||
_curRem = 0;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= Extents.Back().Virt)
|
||||
return S_OK;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
unsigned left = 0, right = Extents.Size() - 1;
|
||||
for (;;)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
if (mid == left)
|
||||
break;
|
||||
if (_virtPos < Extents[mid].Virt)
|
||||
right = mid;
|
||||
else
|
||||
left = mid;
|
||||
}
|
||||
|
||||
const CSeekExtent &extent = Extents[left];
|
||||
UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);
|
||||
if (_needStartSeek || _phyPos != phyPos)
|
||||
{
|
||||
_needStartSeek = false;
|
||||
_phyPos = phyPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
|
||||
UInt64 rem = Extents[left + 1].Virt - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
_phyPos += size;
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += Extents.Back().Virt; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size > _size)
|
||||
{
|
||||
if (_size == 0)
|
||||
{
|
||||
_overflow = true;
|
||||
if (!_overflowIsAllowed)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
size = (UInt32)_size;
|
||||
}
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
_size -= size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Read(data, size, &cur);
|
||||
if (processedSize)
|
||||
*processedSize = cur;
|
||||
_virtPos += cur;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END:
|
||||
{
|
||||
UInt64 pos = 0;
|
||||
RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos));
|
||||
if (pos < Offset)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = pos - Offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= _size)
|
||||
{
|
||||
// 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
|
||||
return S_OK;
|
||||
// return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
|
||||
}
|
||||
UInt64 rem = _size - _virtPos;
|
||||
if (rem < size)
|
||||
size = (UInt32)rem;
|
||||
|
||||
UInt64 newPos = _startOffset + _virtPos;
|
||||
UInt64 offsetInCache = newPos - _cachePhyPos;
|
||||
HRESULT res = S_OK;
|
||||
if (newPos >= _cachePhyPos &&
|
||||
offsetInCache <= _cacheSize &&
|
||||
size <= _cacheSize - (size_t)offsetInCache)
|
||||
{
|
||||
if (size != 0)
|
||||
memcpy(data, _cache + (size_t)offsetInCache, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
res = _stream->Read(data, size, &size);
|
||||
_physPos += size;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_virtPos += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Write(data, size, &cur);
|
||||
if (processedSize)
|
||||
*processedSize = cur;
|
||||
_virtPos += cur;
|
||||
if (_virtSize < _virtPos)
|
||||
_virtSize = _virtPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _virtSize; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
_virtSize = newSize;
|
||||
return Stream->SetSize(Offset + newSize);
|
||||
}
|
||||
// LimitedStreams.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "LimitedStreams.h"
|
||||
|
||||
STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
{
|
||||
const UInt64 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
HRESULT result = S_OK;
|
||||
if (size != 0)
|
||||
{
|
||||
result = _stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
if (realProcessedSize == 0)
|
||||
_wasFinished = true;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= _size)
|
||||
{
|
||||
// 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
|
||||
return S_OK;
|
||||
// return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
|
||||
}
|
||||
{
|
||||
const UInt64 rem = _size - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
UInt64 newPos = _startOffset + _virtPos;
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
HRESULT res = _stream->Read(data, size, &size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_physPos += size;
|
||||
_virtPos += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)
|
||||
{
|
||||
*resStream = 0;
|
||||
CLimitedInStream *streamSpec = new CLimitedInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->SetStream(inStream);
|
||||
RINOK(streamSpec->InitAndSeek(pos, size));
|
||||
streamSpec->SeekToStart();
|
||||
*resStream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= Size)
|
||||
return S_OK;
|
||||
{
|
||||
UInt64 rem = Size - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (_curRem == 0)
|
||||
{
|
||||
const UInt32 blockSize = (UInt32)1 << BlockSizeLog;
|
||||
const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
|
||||
const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
|
||||
const UInt32 phyBlock = Vector[virtBlock];
|
||||
|
||||
UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
|
||||
_curRem = blockSize - offsetInBlock;
|
||||
|
||||
for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
|
||||
_curRem += (UInt32)1 << BlockSizeLog;
|
||||
}
|
||||
|
||||
if (size > _curRem)
|
||||
size = _curRem;
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_physPos += size;
|
||||
_virtPos += size;
|
||||
_curRem -= size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += Size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
if (_virtPos != (UInt64)offset)
|
||||
_curRem = 0;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= Extents.Back().Virt)
|
||||
return S_OK;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
unsigned left = 0, right = Extents.Size() - 1;
|
||||
for (;;)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
if (mid == left)
|
||||
break;
|
||||
if (_virtPos < Extents[mid].Virt)
|
||||
right = mid;
|
||||
else
|
||||
left = mid;
|
||||
}
|
||||
|
||||
const CSeekExtent &extent = Extents[left];
|
||||
UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);
|
||||
if (_needStartSeek || _phyPos != phyPos)
|
||||
{
|
||||
_needStartSeek = false;
|
||||
_phyPos = phyPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
|
||||
UInt64 rem = Extents[left + 1].Virt - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
_phyPos += size;
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += Extents.Back().Virt; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size > _size)
|
||||
{
|
||||
if (_size == 0)
|
||||
{
|
||||
_overflow = true;
|
||||
if (!_overflowIsAllowed)
|
||||
return E_FAIL;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
size = (UInt32)_size;
|
||||
}
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
_size -= size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Read(data, size, &cur);
|
||||
if (processedSize)
|
||||
*processedSize = cur;
|
||||
_virtPos += cur;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END:
|
||||
{
|
||||
UInt64 pos = 0;
|
||||
RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos));
|
||||
if (pos < Offset)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = pos - Offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (_virtPos >= _size)
|
||||
{
|
||||
// 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
|
||||
return S_OK;
|
||||
// return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
|
||||
}
|
||||
UInt64 rem = _size - _virtPos;
|
||||
if (rem < size)
|
||||
size = (UInt32)rem;
|
||||
|
||||
UInt64 newPos = _startOffset + _virtPos;
|
||||
UInt64 offsetInCache = newPos - _cachePhyPos;
|
||||
HRESULT res = S_OK;
|
||||
if (newPos >= _cachePhyPos &&
|
||||
offsetInCache <= _cacheSize &&
|
||||
size <= _cacheSize - (size_t)offsetInCache)
|
||||
{
|
||||
if (size != 0)
|
||||
memcpy(data, _cache + (size_t)offsetInCache, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
}
|
||||
res = _stream->Read(data, size, &size);
|
||||
_physPos += size;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_virtPos += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Write(data, size, &cur);
|
||||
if (processedSize)
|
||||
*processedSize = cur;
|
||||
_virtPos += cur;
|
||||
if (_virtSize < _virtPos)
|
||||
_virtSize = _virtPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += _virtSize; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
_virtSize = newSize;
|
||||
return Stream->SetSize(Offset + newSize);
|
||||
}
|
||||
|
||||
@@ -1,252 +1,252 @@
|
||||
// LimitedStreams.h
|
||||
|
||||
#ifndef __LIMITED_STREAMS_H
|
||||
#define __LIMITED_STREAMS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
class CLimitedSequentialInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt64 _pos;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(UInt64 streamSize)
|
||||
{
|
||||
_size = streamSize;
|
||||
_pos = 0;
|
||||
_wasFinished = false;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
UInt64 GetSize() const { return _pos; }
|
||||
UInt64 GetRem() const { return _size - _pos; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
class CLimitedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt64 _size;
|
||||
UInt64 _startOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
public:
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_physPos = startOffset;
|
||||
_virtPos = 0;
|
||||
_size = size;
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);
|
||||
|
||||
class CClusterInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt32 _curRem;
|
||||
public:
|
||||
unsigned BlockSizeLog;
|
||||
UInt64 Size;
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CRecordVector<UInt32> Vector;
|
||||
UInt64 StartOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
|
||||
HRESULT InitAndSeek()
|
||||
{
|
||||
_curRem = 0;
|
||||
_virtPos = 0;
|
||||
_physPos = StartOffset;
|
||||
if (Vector.Size() > 0)
|
||||
{
|
||||
_physPos = StartOffset + (Vector[0] << BlockSizeLog);
|
||||
return SeekToPhys();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
struct CSeekExtent
|
||||
{
|
||||
UInt64 Phy;
|
||||
UInt64 Virt;
|
||||
};
|
||||
|
||||
class CExtentsStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _phyPos;
|
||||
UInt64 _virtPos;
|
||||
bool _needStartSeek;
|
||||
|
||||
HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }
|
||||
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CRecordVector<CSeekExtent> Extents;
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
void ReleaseStream() { Stream.Release(); }
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_phyPos = 0;
|
||||
_needStartSeek = true;
|
||||
}
|
||||
};
|
||||
|
||||
class CLimitedSequentialOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
bool _overflow;
|
||||
bool _overflowIsAllowed;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(UInt64 size, bool overflowIsAllowed = false)
|
||||
{
|
||||
_size = size;
|
||||
_overflow = false;
|
||||
_overflowIsAllowed = overflowIsAllowed;
|
||||
}
|
||||
bool IsFinishedOK() const { return (_size == 0 && !_overflow); }
|
||||
UInt64 GetRem() const { return _size; }
|
||||
};
|
||||
|
||||
|
||||
class CTailInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Offset;
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
class CLimitedCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt64 _size;
|
||||
UInt64 _startOffset;
|
||||
|
||||
const Byte *_cache;
|
||||
size_t _cacheSize;
|
||||
size_t _cachePhyPos;
|
||||
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
public:
|
||||
CByteBuffer Buffer;
|
||||
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
void SetCache(size_t cacheSize, size_t cachePos)
|
||||
{
|
||||
_cache = Buffer;
|
||||
_cacheSize = cacheSize;
|
||||
_cachePhyPos = cachePos;
|
||||
}
|
||||
|
||||
HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_physPos = startOffset;
|
||||
_virtPos = 0;
|
||||
_size = size;
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
class CTailOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
UInt64 _virtSize;
|
||||
public:
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
UInt64 Offset;
|
||||
|
||||
virtual ~CTailOutStream() {}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_virtSize = 0;
|
||||
}
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// LimitedStreams.h
|
||||
|
||||
#ifndef __LIMITED_STREAMS_H
|
||||
#define __LIMITED_STREAMS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
class CLimitedSequentialInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt64 _pos;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(UInt64 streamSize)
|
||||
{
|
||||
_size = streamSize;
|
||||
_pos = 0;
|
||||
_wasFinished = false;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
UInt64 GetSize() const { return _pos; }
|
||||
UInt64 GetRem() const { return _size - _pos; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
class CLimitedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt64 _size;
|
||||
UInt64 _startOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
public:
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_physPos = startOffset;
|
||||
_virtPos = 0;
|
||||
_size = size;
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);
|
||||
|
||||
class CClusterInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt32 _curRem;
|
||||
public:
|
||||
unsigned BlockSizeLog;
|
||||
UInt64 Size;
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CRecordVector<UInt32> Vector;
|
||||
UInt64 StartOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
|
||||
HRESULT InitAndSeek()
|
||||
{
|
||||
_curRem = 0;
|
||||
_virtPos = 0;
|
||||
_physPos = StartOffset;
|
||||
if (Vector.Size() > 0)
|
||||
{
|
||||
_physPos = StartOffset + (Vector[0] << BlockSizeLog);
|
||||
return SeekToPhys();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
struct CSeekExtent
|
||||
{
|
||||
UInt64 Phy;
|
||||
UInt64 Virt;
|
||||
};
|
||||
|
||||
class CExtentsStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _phyPos;
|
||||
UInt64 _virtPos;
|
||||
bool _needStartSeek;
|
||||
|
||||
HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }
|
||||
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CRecordVector<CSeekExtent> Extents;
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
void ReleaseStream() { Stream.Release(); }
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_phyPos = 0;
|
||||
_needStartSeek = true;
|
||||
}
|
||||
};
|
||||
|
||||
class CLimitedSequentialOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
bool _overflow;
|
||||
bool _overflowIsAllowed;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(UInt64 size, bool overflowIsAllowed = false)
|
||||
{
|
||||
_size = size;
|
||||
_overflow = false;
|
||||
_overflowIsAllowed = overflowIsAllowed;
|
||||
}
|
||||
bool IsFinishedOK() const { return (_size == 0 && !_overflow); }
|
||||
UInt64 GetRem() const { return _size; }
|
||||
};
|
||||
|
||||
|
||||
class CTailInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Offset;
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
class CLimitedCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt64 _size;
|
||||
UInt64 _startOffset;
|
||||
|
||||
const Byte *_cache;
|
||||
size_t _cacheSize;
|
||||
size_t _cachePhyPos;
|
||||
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
|
||||
public:
|
||||
CByteBuffer Buffer;
|
||||
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
void SetCache(size_t cacheSize, size_t cachePos)
|
||||
{
|
||||
_cache = Buffer;
|
||||
_cacheSize = cacheSize;
|
||||
_cachePhyPos = cachePos;
|
||||
}
|
||||
|
||||
HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_physPos = startOffset;
|
||||
_virtPos = 0;
|
||||
_size = size;
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
class CTailOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _virtPos;
|
||||
UInt64 _virtSize;
|
||||
public:
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
UInt64 Offset;
|
||||
|
||||
virtual ~CTailOutStream() {}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_virtSize = 0;
|
||||
}
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// LockedStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
// LockedStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// LockedStream.h
|
||||
|
||||
#ifndef __LOCKED_STREAM_H
|
||||
#define __LOCKED_STREAM_H
|
||||
|
||||
#endif
|
||||
// LockedStream.h
|
||||
|
||||
#ifndef __LOCKED_STREAM_H
|
||||
#define __LOCKED_STREAM_H
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,183 +1,183 @@
|
||||
// MemBlocks.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "MemBlocks.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
bool CMemBlockManager::AllocateSpace(size_t numBlocks)
|
||||
{
|
||||
FreeSpace();
|
||||
if (_blockSize < sizeof(void *) || numBlocks < 1)
|
||||
return false;
|
||||
size_t totalSize = numBlocks * _blockSize;
|
||||
if (totalSize / _blockSize != numBlocks)
|
||||
return false;
|
||||
_data = ::MidAlloc(totalSize);
|
||||
if (_data == 0)
|
||||
return false;
|
||||
Byte *p = (Byte *)_data;
|
||||
for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
|
||||
*(Byte **)p = (p + _blockSize);
|
||||
*(Byte **)p = 0;
|
||||
_headFree = _data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeSpace()
|
||||
{
|
||||
::MidFree(_data);
|
||||
_data = 0;
|
||||
_headFree= 0;
|
||||
}
|
||||
|
||||
void *CMemBlockManager::AllocateBlock()
|
||||
{
|
||||
if (_headFree == 0)
|
||||
return 0;
|
||||
void *p = _headFree;
|
||||
_headFree = *(void **)_headFree;
|
||||
return p;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeBlock(void *p)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
*(void **)p = _headFree;
|
||||
_headFree = p;
|
||||
}
|
||||
|
||||
|
||||
HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > numBlocks)
|
||||
return E_INVALIDARG;
|
||||
if (!CMemBlockManager::AllocateSpace(numBlocks))
|
||||
return E_OUTOFMEMORY;
|
||||
size_t numLockBlocks = numBlocks - numNoLockBlocks;
|
||||
Semaphore.Close();
|
||||
return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);
|
||||
}
|
||||
|
||||
HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > desiredNumberOfBlocks)
|
||||
return E_INVALIDARG;
|
||||
for (;;)
|
||||
{
|
||||
if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0)
|
||||
return 0;
|
||||
if (desiredNumberOfBlocks == numNoLockBlocks)
|
||||
return E_OUTOFMEMORY;
|
||||
desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeSpace()
|
||||
{
|
||||
Semaphore.Close();
|
||||
CMemBlockManager::FreeSpace();
|
||||
}
|
||||
|
||||
void *CMemBlockManagerMt::AllocateBlock()
|
||||
{
|
||||
// Semaphore.Lock();
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
return CMemBlockManager::AllocateBlock();
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
CMemBlockManager::FreeBlock(p);
|
||||
}
|
||||
if (lockMode)
|
||||
Semaphore.Release();
|
||||
}
|
||||
|
||||
void CMemBlocks::Free(CMemBlockManagerMt *manager)
|
||||
{
|
||||
while (Blocks.Size() > 0)
|
||||
{
|
||||
manager->FreeBlock(Blocks.Back());
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
|
||||
{
|
||||
Free(manager);
|
||||
Blocks.ClearAndFree();
|
||||
}
|
||||
|
||||
HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
|
||||
{
|
||||
UInt64 totalSize = TotalSize;
|
||||
for (unsigned blockIndex = 0; totalSize > 0; blockIndex++)
|
||||
{
|
||||
UInt32 curSize = (UInt32)blockSize;
|
||||
if (totalSize < curSize)
|
||||
curSize = (UInt32)totalSize;
|
||||
if (blockIndex >= Blocks.Size())
|
||||
return E_FAIL;
|
||||
RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));
|
||||
totalSize -= curSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
memManager->FreeBlock(Blocks[index], LockMode);
|
||||
Blocks[index] = 0;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
while (Blocks.Size() > 0)
|
||||
{
|
||||
FreeBlock(Blocks.Size() - 1, memManager);
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
if (LockMode)
|
||||
{
|
||||
if (Blocks.Size() > 0)
|
||||
{
|
||||
RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));
|
||||
}
|
||||
LockMode = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
blocks.Free(memManager);
|
||||
blocks.LockMode = LockMode;
|
||||
UInt64 totalSize = 0;
|
||||
size_t blockSize = memManager->GetBlockSize();
|
||||
FOR_VECTOR (i, Blocks)
|
||||
{
|
||||
if (totalSize < TotalSize)
|
||||
blocks.Blocks.Add(Blocks[i]);
|
||||
else
|
||||
FreeBlock(i, memManager);
|
||||
Blocks[i] = 0;
|
||||
totalSize += blockSize;
|
||||
}
|
||||
blocks.TotalSize = TotalSize;
|
||||
Free(memManager);
|
||||
}
|
||||
// MemBlocks.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "MemBlocks.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
bool CMemBlockManager::AllocateSpace(size_t numBlocks)
|
||||
{
|
||||
FreeSpace();
|
||||
if (_blockSize < sizeof(void *) || numBlocks < 1)
|
||||
return false;
|
||||
size_t totalSize = numBlocks * _blockSize;
|
||||
if (totalSize / _blockSize != numBlocks)
|
||||
return false;
|
||||
_data = ::MidAlloc(totalSize);
|
||||
if (_data == 0)
|
||||
return false;
|
||||
Byte *p = (Byte *)_data;
|
||||
for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
|
||||
*(Byte **)p = (p + _blockSize);
|
||||
*(Byte **)p = 0;
|
||||
_headFree = _data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeSpace()
|
||||
{
|
||||
::MidFree(_data);
|
||||
_data = 0;
|
||||
_headFree= 0;
|
||||
}
|
||||
|
||||
void *CMemBlockManager::AllocateBlock()
|
||||
{
|
||||
if (_headFree == 0)
|
||||
return 0;
|
||||
void *p = _headFree;
|
||||
_headFree = *(void **)_headFree;
|
||||
return p;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeBlock(void *p)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
*(void **)p = _headFree;
|
||||
_headFree = p;
|
||||
}
|
||||
|
||||
|
||||
HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > numBlocks)
|
||||
return E_INVALIDARG;
|
||||
if (!CMemBlockManager::AllocateSpace(numBlocks))
|
||||
return E_OUTOFMEMORY;
|
||||
size_t numLockBlocks = numBlocks - numNoLockBlocks;
|
||||
Semaphore.Close();
|
||||
return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);
|
||||
}
|
||||
|
||||
HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > desiredNumberOfBlocks)
|
||||
return E_INVALIDARG;
|
||||
for (;;)
|
||||
{
|
||||
if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0)
|
||||
return 0;
|
||||
if (desiredNumberOfBlocks == numNoLockBlocks)
|
||||
return E_OUTOFMEMORY;
|
||||
desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeSpace()
|
||||
{
|
||||
Semaphore.Close();
|
||||
CMemBlockManager::FreeSpace();
|
||||
}
|
||||
|
||||
void *CMemBlockManagerMt::AllocateBlock()
|
||||
{
|
||||
// Semaphore.Lock();
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
return CMemBlockManager::AllocateBlock();
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
CMemBlockManager::FreeBlock(p);
|
||||
}
|
||||
if (lockMode)
|
||||
Semaphore.Release();
|
||||
}
|
||||
|
||||
void CMemBlocks::Free(CMemBlockManagerMt *manager)
|
||||
{
|
||||
while (Blocks.Size() > 0)
|
||||
{
|
||||
manager->FreeBlock(Blocks.Back());
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
|
||||
{
|
||||
Free(manager);
|
||||
Blocks.ClearAndFree();
|
||||
}
|
||||
|
||||
HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
|
||||
{
|
||||
UInt64 totalSize = TotalSize;
|
||||
for (unsigned blockIndex = 0; totalSize > 0; blockIndex++)
|
||||
{
|
||||
UInt32 curSize = (UInt32)blockSize;
|
||||
if (totalSize < curSize)
|
||||
curSize = (UInt32)totalSize;
|
||||
if (blockIndex >= Blocks.Size())
|
||||
return E_FAIL;
|
||||
RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));
|
||||
totalSize -= curSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
memManager->FreeBlock(Blocks[index], LockMode);
|
||||
Blocks[index] = 0;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
while (Blocks.Size() > 0)
|
||||
{
|
||||
FreeBlock(Blocks.Size() - 1, memManager);
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
if (LockMode)
|
||||
{
|
||||
if (Blocks.Size() > 0)
|
||||
{
|
||||
RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));
|
||||
}
|
||||
LockMode = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
blocks.Free(memManager);
|
||||
blocks.LockMode = LockMode;
|
||||
UInt64 totalSize = 0;
|
||||
size_t blockSize = memManager->GetBlockSize();
|
||||
FOR_VECTOR (i, Blocks)
|
||||
{
|
||||
if (totalSize < TotalSize)
|
||||
blocks.Blocks.Add(Blocks[i]);
|
||||
else
|
||||
FreeBlock(i, memManager);
|
||||
Blocks[i] = 0;
|
||||
totalSize += blockSize;
|
||||
}
|
||||
blocks.TotalSize = TotalSize;
|
||||
Free(memManager);
|
||||
}
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
// MemBlocks.h
|
||||
|
||||
#ifndef __MEM_BLOCKS_H
|
||||
#define __MEM_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CMemBlockManager
|
||||
{
|
||||
void *_data;
|
||||
size_t _blockSize;
|
||||
void *_headFree;
|
||||
public:
|
||||
CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {}
|
||||
~CMemBlockManager() { FreeSpace(); }
|
||||
|
||||
bool AllocateSpace(size_t numBlocks);
|
||||
void FreeSpace();
|
||||
size_t GetBlockSize() const { return _blockSize; }
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p);
|
||||
};
|
||||
|
||||
|
||||
class CMemBlockManagerMt: public CMemBlockManager
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSection _criticalSection;
|
||||
public:
|
||||
NWindows::NSynchronization::CSemaphore Semaphore;
|
||||
|
||||
CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}
|
||||
~CMemBlockManagerMt() { FreeSpace(); }
|
||||
|
||||
HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0);
|
||||
HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);
|
||||
void FreeSpace();
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p, bool lockMode = true);
|
||||
HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); }
|
||||
};
|
||||
|
||||
|
||||
class CMemBlocks
|
||||
{
|
||||
void Free(CMemBlockManagerMt *manager);
|
||||
public:
|
||||
CRecordVector<void *> Blocks;
|
||||
UInt64 TotalSize;
|
||||
|
||||
CMemBlocks(): TotalSize(0) {}
|
||||
|
||||
void FreeOpt(CMemBlockManagerMt *manager);
|
||||
HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const;
|
||||
};
|
||||
|
||||
struct CMemLockBlocks: public CMemBlocks
|
||||
{
|
||||
bool LockMode;
|
||||
|
||||
CMemLockBlocks(): LockMode(true) {};
|
||||
void Free(CMemBlockManagerMt *memManager);
|
||||
void FreeBlock(int index, CMemBlockManagerMt *memManager);
|
||||
HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager);
|
||||
void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);
|
||||
};
|
||||
|
||||
#endif
|
||||
// MemBlocks.h
|
||||
|
||||
#ifndef __MEM_BLOCKS_H
|
||||
#define __MEM_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CMemBlockManager
|
||||
{
|
||||
void *_data;
|
||||
size_t _blockSize;
|
||||
void *_headFree;
|
||||
public:
|
||||
CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {}
|
||||
~CMemBlockManager() { FreeSpace(); }
|
||||
|
||||
bool AllocateSpace(size_t numBlocks);
|
||||
void FreeSpace();
|
||||
size_t GetBlockSize() const { return _blockSize; }
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p);
|
||||
};
|
||||
|
||||
|
||||
class CMemBlockManagerMt: public CMemBlockManager
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSection _criticalSection;
|
||||
public:
|
||||
NWindows::NSynchronization::CSemaphore Semaphore;
|
||||
|
||||
CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}
|
||||
~CMemBlockManagerMt() { FreeSpace(); }
|
||||
|
||||
HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0);
|
||||
HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);
|
||||
void FreeSpace();
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p, bool lockMode = true);
|
||||
HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); }
|
||||
};
|
||||
|
||||
|
||||
class CMemBlocks
|
||||
{
|
||||
void Free(CMemBlockManagerMt *manager);
|
||||
public:
|
||||
CRecordVector<void *> Blocks;
|
||||
UInt64 TotalSize;
|
||||
|
||||
CMemBlocks(): TotalSize(0) {}
|
||||
|
||||
void FreeOpt(CMemBlockManagerMt *manager);
|
||||
HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const;
|
||||
};
|
||||
|
||||
struct CMemLockBlocks: public CMemBlocks
|
||||
{
|
||||
bool LockMode;
|
||||
|
||||
CMemLockBlocks(): LockMode(true) {};
|
||||
void Free(CMemBlockManagerMt *memManager);
|
||||
void FreeBlock(int index, CMemBlockManagerMt *memManager);
|
||||
HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager);
|
||||
void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// MethodId.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
// MethodId.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// MethodId.h
|
||||
|
||||
#ifndef __7Z_METHOD_ID_H
|
||||
#define __7Z_METHOD_ID_H
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
|
||||
typedef UInt64 CMethodId;
|
||||
|
||||
#endif
|
||||
// MethodId.h
|
||||
|
||||
#ifndef __7Z_METHOD_ID_H
|
||||
#define __7Z_METHOD_ID_H
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
|
||||
typedef UInt64 CMethodId;
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,264 +1,264 @@
|
||||
// MethodProps.h
|
||||
|
||||
#ifndef __7Z_METHOD_PROPS_H
|
||||
#define __7Z_METHOD_PROPS_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "../../Windows/Defs.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
bool StringToBool(const wchar_t *s, bool &res);
|
||||
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
|
||||
unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
|
||||
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
|
||||
|
||||
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
|
||||
|
||||
struct CProp
|
||||
{
|
||||
PROPID Id;
|
||||
bool IsOptional;
|
||||
NWindows::NCOM::CPropVariant Value;
|
||||
CProp(): IsOptional(false) {}
|
||||
};
|
||||
|
||||
struct CProps
|
||||
{
|
||||
CObjectVector<CProp> Props;
|
||||
|
||||
void Clear() { Props.Clear(); }
|
||||
|
||||
bool AreThereNonOptionalProps() const
|
||||
{
|
||||
FOR_VECTOR (i, Props)
|
||||
if (!Props[i].IsOptional)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddProp32(PROPID propid, UInt32 val);
|
||||
|
||||
void AddPropBool(PROPID propid, bool val);
|
||||
|
||||
void AddProp_Ascii(PROPID propid, const char *s)
|
||||
{
|
||||
CProp &prop = Props.AddNew();
|
||||
prop.IsOptional = true;
|
||||
prop.Id = propid;
|
||||
prop.Value = s;
|
||||
}
|
||||
|
||||
HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;
|
||||
};
|
||||
|
||||
class CMethodProps: public CProps
|
||||
{
|
||||
HRESULT SetParam(const UString &name, const UString &value);
|
||||
public:
|
||||
int GetLevel() const;
|
||||
int Get_NumThreads() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kNumThreads);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return (int)Props[i].Value.ulVal;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Get_DicSize(UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
{
|
||||
res = Props[i].Value.ulVal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int FindProp(PROPID id) const;
|
||||
|
||||
UInt32 Get_Lzma_Algo() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kAlgorithm);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
return GetLevel() >= 5 ? 1 : 0;
|
||||
}
|
||||
|
||||
UInt32 Get_Lzma_DicSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
int level = GetLevel();
|
||||
return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
|
||||
}
|
||||
|
||||
bool Get_Lzma_Eos() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kEndMarker);
|
||||
if (i >= 0)
|
||||
{
|
||||
const NWindows::NCOM::CPropVariant &val = Props[i].Value;
|
||||
if (val.vt == VT_BOOL)
|
||||
return VARIANT_BOOLToBool(val.boolVal);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Are_Lzma_Model_Props_Defined() const
|
||||
{
|
||||
if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;
|
||||
if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;
|
||||
if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 Get_Lzma_NumThreads() const
|
||||
{
|
||||
if (Get_Lzma_Algo() == 0)
|
||||
return 1;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0)
|
||||
return numThreads < 2 ? 1 : 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
|
||||
{
|
||||
lzmaThreads = 1;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0 && numThreads <= 1)
|
||||
return 1;
|
||||
if (Get_Lzma_Algo() != 0)
|
||||
lzmaThreads = 2;
|
||||
return numThreads;
|
||||
}
|
||||
|
||||
UInt64 GetProp_BlockSize(PROPID id) const
|
||||
{
|
||||
int i = FindProp(id);
|
||||
if (i >= 0)
|
||||
{
|
||||
const NWindows::NCOM::CPropVariant &val = Props[i].Value;
|
||||
if (val.vt == VT_UI4) { return val.ulVal; }
|
||||
if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 Get_Xz_BlockSize() const
|
||||
{
|
||||
{
|
||||
UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
|
||||
UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
|
||||
UInt64 minSize = MyMin(blockSize1, blockSize2);
|
||||
if (minSize != 0)
|
||||
return minSize;
|
||||
UInt64 maxSize = MyMax(blockSize1, blockSize2);
|
||||
if (maxSize != 0)
|
||||
return maxSize;
|
||||
}
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
UInt32 dictSize = Get_Lzma_DicSize();
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
blockSize += (kMinSize - 1);
|
||||
blockSize &= ~(UInt64)(kMinSize - 1);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
|
||||
UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
|
||||
{
|
||||
fixedNumber = false;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0)
|
||||
{
|
||||
fixedNumber = true;
|
||||
if (numThreads < 1) return 1;
|
||||
const unsigned kNumBZip2ThreadsMax = 64;
|
||||
if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;
|
||||
return numThreads;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
UInt32 Get_BZip2_BlockSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 blockSize = Props[i].Value.ulVal;
|
||||
const UInt32 kDicSizeMin = 100000;
|
||||
const UInt32 kDicSizeMax = 900000;
|
||||
if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;
|
||||
if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;
|
||||
return blockSize;
|
||||
}
|
||||
int level = GetLevel();
|
||||
return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
|
||||
}
|
||||
|
||||
UInt32 Get_Ppmd_MemSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kUsedMemorySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
int level = GetLevel();
|
||||
return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));
|
||||
}
|
||||
|
||||
void AddProp_Level(UInt32 level)
|
||||
{
|
||||
AddProp32(NCoderPropID::kLevel, level);
|
||||
}
|
||||
|
||||
void AddProp_NumThreads(UInt32 numThreads)
|
||||
{
|
||||
AddProp32(NCoderPropID::kNumThreads, numThreads);
|
||||
}
|
||||
|
||||
void AddProp_EndMarker_if_NotFound(bool eos)
|
||||
{
|
||||
if (FindProp(NCoderPropID::kEndMarker) < 0)
|
||||
AddPropBool(NCoderPropID::kEndMarker, eos);
|
||||
}
|
||||
|
||||
HRESULT ParseParamsFromString(const UString &srcString);
|
||||
HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
class COneMethodInfo: public CMethodProps
|
||||
{
|
||||
public:
|
||||
AString MethodName;
|
||||
UString PropsString;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CMethodProps::Clear();
|
||||
MethodName.Empty();
|
||||
PropsString.Empty();
|
||||
}
|
||||
bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }
|
||||
HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
|
||||
HRESULT ParseMethodFromString(const UString &s);
|
||||
};
|
||||
|
||||
#endif
|
||||
// MethodProps.h
|
||||
|
||||
#ifndef __7Z_METHOD_PROPS_H
|
||||
#define __7Z_METHOD_PROPS_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "../../Windows/Defs.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
bool StringToBool(const wchar_t *s, bool &res);
|
||||
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
|
||||
unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
|
||||
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
|
||||
|
||||
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
|
||||
|
||||
struct CProp
|
||||
{
|
||||
PROPID Id;
|
||||
bool IsOptional;
|
||||
NWindows::NCOM::CPropVariant Value;
|
||||
CProp(): IsOptional(false) {}
|
||||
};
|
||||
|
||||
struct CProps
|
||||
{
|
||||
CObjectVector<CProp> Props;
|
||||
|
||||
void Clear() { Props.Clear(); }
|
||||
|
||||
bool AreThereNonOptionalProps() const
|
||||
{
|
||||
FOR_VECTOR (i, Props)
|
||||
if (!Props[i].IsOptional)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddProp32(PROPID propid, UInt32 val);
|
||||
|
||||
void AddPropBool(PROPID propid, bool val);
|
||||
|
||||
void AddProp_Ascii(PROPID propid, const char *s)
|
||||
{
|
||||
CProp &prop = Props.AddNew();
|
||||
prop.IsOptional = true;
|
||||
prop.Id = propid;
|
||||
prop.Value = s;
|
||||
}
|
||||
|
||||
HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;
|
||||
};
|
||||
|
||||
class CMethodProps: public CProps
|
||||
{
|
||||
HRESULT SetParam(const UString &name, const UString &value);
|
||||
public:
|
||||
int GetLevel() const;
|
||||
int Get_NumThreads() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kNumThreads);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return (int)Props[i].Value.ulVal;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Get_DicSize(UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
{
|
||||
res = Props[i].Value.ulVal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int FindProp(PROPID id) const;
|
||||
|
||||
UInt32 Get_Lzma_Algo() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kAlgorithm);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
return GetLevel() >= 5 ? 1 : 0;
|
||||
}
|
||||
|
||||
UInt32 Get_Lzma_DicSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
int level = GetLevel();
|
||||
return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
|
||||
}
|
||||
|
||||
bool Get_Lzma_Eos() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kEndMarker);
|
||||
if (i >= 0)
|
||||
{
|
||||
const NWindows::NCOM::CPropVariant &val = Props[i].Value;
|
||||
if (val.vt == VT_BOOL)
|
||||
return VARIANT_BOOLToBool(val.boolVal);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Are_Lzma_Model_Props_Defined() const
|
||||
{
|
||||
if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;
|
||||
if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;
|
||||
if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 Get_Lzma_NumThreads() const
|
||||
{
|
||||
if (Get_Lzma_Algo() == 0)
|
||||
return 1;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0)
|
||||
return numThreads < 2 ? 1 : 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
|
||||
{
|
||||
lzmaThreads = 1;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0 && numThreads <= 1)
|
||||
return 1;
|
||||
if (Get_Lzma_Algo() != 0)
|
||||
lzmaThreads = 2;
|
||||
return numThreads;
|
||||
}
|
||||
|
||||
UInt64 GetProp_BlockSize(PROPID id) const
|
||||
{
|
||||
int i = FindProp(id);
|
||||
if (i >= 0)
|
||||
{
|
||||
const NWindows::NCOM::CPropVariant &val = Props[i].Value;
|
||||
if (val.vt == VT_UI4) { return val.ulVal; }
|
||||
if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 Get_Xz_BlockSize() const
|
||||
{
|
||||
{
|
||||
UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
|
||||
UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
|
||||
UInt64 minSize = MyMin(blockSize1, blockSize2);
|
||||
if (minSize != 0)
|
||||
return minSize;
|
||||
UInt64 maxSize = MyMax(blockSize1, blockSize2);
|
||||
if (maxSize != 0)
|
||||
return maxSize;
|
||||
}
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
UInt32 dictSize = Get_Lzma_DicSize();
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
blockSize += (kMinSize - 1);
|
||||
blockSize &= ~(UInt64)(kMinSize - 1);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
|
||||
UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
|
||||
{
|
||||
fixedNumber = false;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0)
|
||||
{
|
||||
fixedNumber = true;
|
||||
if (numThreads < 1) return 1;
|
||||
const unsigned kNumBZip2ThreadsMax = 64;
|
||||
if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;
|
||||
return numThreads;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
UInt32 Get_BZip2_BlockSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kDictionarySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 blockSize = Props[i].Value.ulVal;
|
||||
const UInt32 kDicSizeMin = 100000;
|
||||
const UInt32 kDicSizeMax = 900000;
|
||||
if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;
|
||||
if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;
|
||||
return blockSize;
|
||||
}
|
||||
int level = GetLevel();
|
||||
return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
|
||||
}
|
||||
|
||||
UInt32 Get_Ppmd_MemSize() const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kUsedMemorySize);
|
||||
if (i >= 0)
|
||||
if (Props[i].Value.vt == VT_UI4)
|
||||
return Props[i].Value.ulVal;
|
||||
int level = GetLevel();
|
||||
return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));
|
||||
}
|
||||
|
||||
void AddProp_Level(UInt32 level)
|
||||
{
|
||||
AddProp32(NCoderPropID::kLevel, level);
|
||||
}
|
||||
|
||||
void AddProp_NumThreads(UInt32 numThreads)
|
||||
{
|
||||
AddProp32(NCoderPropID::kNumThreads, numThreads);
|
||||
}
|
||||
|
||||
void AddProp_EndMarker_if_NotFound(bool eos)
|
||||
{
|
||||
if (FindProp(NCoderPropID::kEndMarker) < 0)
|
||||
AddPropBool(NCoderPropID::kEndMarker, eos);
|
||||
}
|
||||
|
||||
HRESULT ParseParamsFromString(const UString &srcString);
|
||||
HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
class COneMethodInfo: public CMethodProps
|
||||
{
|
||||
public:
|
||||
AString MethodName;
|
||||
UString PropsString;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CMethodProps::Clear();
|
||||
MethodName.Empty();
|
||||
PropsString.Empty();
|
||||
}
|
||||
bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }
|
||||
HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
|
||||
HRESULT ParseMethodFromString(const UString &s);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
// OffsetStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "OffsetStream.h"
|
||||
|
||||
HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
|
||||
{
|
||||
_offset = offset;
|
||||
_stream = stream;
|
||||
return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return _stream->Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
UInt64 absoluteNewPosition;
|
||||
if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
offset += _offset;
|
||||
}
|
||||
HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
|
||||
if (newPosition)
|
||||
*newPosition = absoluteNewPosition - _offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
return _stream->SetSize(_offset + newSize);
|
||||
}
|
||||
// OffsetStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "OffsetStream.h"
|
||||
|
||||
HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
|
||||
{
|
||||
_offset = offset;
|
||||
_stream = stream;
|
||||
return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return _stream->Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
UInt64 absoluteNewPosition;
|
||||
if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
offset += _offset;
|
||||
}
|
||||
HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
|
||||
if (newPosition)
|
||||
*newPosition = absoluteNewPosition - _offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
return _stream->SetSize(_offset + newSize);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// OffsetStream.h
|
||||
|
||||
#ifndef __OFFSET_STREAM_H
|
||||
#define __OFFSET_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class COffsetOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _offset;
|
||||
CMyComPtr<IOutStream> _stream;
|
||||
public:
|
||||
HRESULT Init(IOutStream *stream, UInt64 offset);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// OffsetStream.h
|
||||
|
||||
#ifndef __OFFSET_STREAM_H
|
||||
#define __OFFSET_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class COffsetOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _offset;
|
||||
CMyComPtr<IOutStream> _stream;
|
||||
public:
|
||||
HRESULT Init(IOutStream *stream, UInt64 offset);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
// OutBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "OutBuffer.h"
|
||||
|
||||
bool COutBuffer::Create(UInt32 bufSize) throw()
|
||||
{
|
||||
const UInt32 kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_buf != 0 && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_buf = (Byte *)::MidAlloc(bufSize);
|
||||
return (_buf != 0);
|
||||
}
|
||||
|
||||
void COutBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_buf);
|
||||
_buf = 0;
|
||||
}
|
||||
|
||||
void COutBuffer::Init() throw()
|
||||
{
|
||||
_streamPos = 0;
|
||||
_limitPos = _bufSize;
|
||||
_pos = 0;
|
||||
_processedSize = 0;
|
||||
_overDict = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt64 COutBuffer::GetProcessedSize() const throw()
|
||||
{
|
||||
UInt64 res = _processedSize + _pos - _streamPos;
|
||||
if (_streamPos > _pos)
|
||||
res += _bufSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT COutBuffer::FlushPart() throw()
|
||||
{
|
||||
// _streamPos < _bufSize
|
||||
UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);
|
||||
HRESULT result = S_OK;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
result = ErrorCode;
|
||||
#endif
|
||||
if (_buf2 != 0)
|
||||
{
|
||||
memcpy(_buf2, _buf + _streamPos, size);
|
||||
_buf2 += size;
|
||||
}
|
||||
|
||||
if (_stream != 0
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
&& (ErrorCode == S_OK)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
UInt32 processedSize = 0;
|
||||
result = _stream->Write(_buf + _streamPos, size, &processedSize);
|
||||
size = processedSize;
|
||||
}
|
||||
_streamPos += size;
|
||||
if (_streamPos == _bufSize)
|
||||
_streamPos = 0;
|
||||
if (_pos == _bufSize)
|
||||
{
|
||||
_overDict = true;
|
||||
_pos = 0;
|
||||
}
|
||||
_limitPos = (_streamPos > _pos) ? _streamPos : _bufSize;
|
||||
_processedSize += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT COutBuffer::Flush() throw()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return ErrorCode;
|
||||
#endif
|
||||
|
||||
while (_streamPos != _pos)
|
||||
{
|
||||
HRESULT result = FlushPart();
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutBuffer::FlushWithCheck()
|
||||
{
|
||||
HRESULT result = Flush();
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
throw COutBufferException(result);
|
||||
#endif
|
||||
}
|
||||
// OutBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "OutBuffer.h"
|
||||
|
||||
bool COutBuffer::Create(UInt32 bufSize) throw()
|
||||
{
|
||||
const UInt32 kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_buf != 0 && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_buf = (Byte *)::MidAlloc(bufSize);
|
||||
return (_buf != 0);
|
||||
}
|
||||
|
||||
void COutBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_buf);
|
||||
_buf = 0;
|
||||
}
|
||||
|
||||
void COutBuffer::Init() throw()
|
||||
{
|
||||
_streamPos = 0;
|
||||
_limitPos = _bufSize;
|
||||
_pos = 0;
|
||||
_processedSize = 0;
|
||||
_overDict = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt64 COutBuffer::GetProcessedSize() const throw()
|
||||
{
|
||||
UInt64 res = _processedSize + _pos - _streamPos;
|
||||
if (_streamPos > _pos)
|
||||
res += _bufSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT COutBuffer::FlushPart() throw()
|
||||
{
|
||||
// _streamPos < _bufSize
|
||||
UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);
|
||||
HRESULT result = S_OK;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
result = ErrorCode;
|
||||
#endif
|
||||
if (_buf2 != 0)
|
||||
{
|
||||
memcpy(_buf2, _buf + _streamPos, size);
|
||||
_buf2 += size;
|
||||
}
|
||||
|
||||
if (_stream != 0
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
&& (ErrorCode == S_OK)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
UInt32 processedSize = 0;
|
||||
result = _stream->Write(_buf + _streamPos, size, &processedSize);
|
||||
size = processedSize;
|
||||
}
|
||||
_streamPos += size;
|
||||
if (_streamPos == _bufSize)
|
||||
_streamPos = 0;
|
||||
if (_pos == _bufSize)
|
||||
{
|
||||
_overDict = true;
|
||||
_pos = 0;
|
||||
}
|
||||
_limitPos = (_streamPos > _pos) ? _streamPos : _bufSize;
|
||||
_processedSize += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT COutBuffer::Flush() throw()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return ErrorCode;
|
||||
#endif
|
||||
|
||||
while (_streamPos != _pos)
|
||||
{
|
||||
HRESULT result = FlushPart();
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutBuffer::FlushWithCheck()
|
||||
{
|
||||
HRESULT result = Flush();
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
throw COutBufferException(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
// OutBuffer.h
|
||||
|
||||
#ifndef __OUT_BUFFER_H
|
||||
#define __OUT_BUFFER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyException.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
struct COutBufferException: public CSystemException
|
||||
{
|
||||
COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class COutBuffer
|
||||
{
|
||||
protected:
|
||||
Byte *_buf;
|
||||
UInt32 _pos;
|
||||
UInt32 _limitPos;
|
||||
UInt32 _streamPos;
|
||||
UInt32 _bufSize;
|
||||
ISequentialOutStream *_stream;
|
||||
UInt64 _processedSize;
|
||||
Byte *_buf2;
|
||||
bool _overDict;
|
||||
|
||||
HRESULT FlushPart() throw();
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
|
||||
COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {}
|
||||
~COutBuffer() { Free(); }
|
||||
|
||||
bool Create(UInt32 bufSize) throw();
|
||||
void Free() throw();
|
||||
|
||||
void SetMemStream(Byte *buf) { _buf2 = buf; }
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init() throw();
|
||||
HRESULT Flush() throw();
|
||||
void FlushWithCheck();
|
||||
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
UInt32 pos = _pos;
|
||||
_buf[pos] = b;
|
||||
pos++;
|
||||
_pos = pos;
|
||||
if (pos == _limitPos)
|
||||
FlushWithCheck();
|
||||
}
|
||||
void WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
WriteByte(((const Byte *)data)[i]);
|
||||
}
|
||||
|
||||
UInt64 GetProcessedSize() const throw();
|
||||
};
|
||||
|
||||
#endif
|
||||
// OutBuffer.h
|
||||
|
||||
#ifndef __OUT_BUFFER_H
|
||||
#define __OUT_BUFFER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyException.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
struct COutBufferException: public CSystemException
|
||||
{
|
||||
COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class COutBuffer
|
||||
{
|
||||
protected:
|
||||
Byte *_buf;
|
||||
UInt32 _pos;
|
||||
UInt32 _limitPos;
|
||||
UInt32 _streamPos;
|
||||
UInt32 _bufSize;
|
||||
ISequentialOutStream *_stream;
|
||||
UInt64 _processedSize;
|
||||
Byte *_buf2;
|
||||
bool _overDict;
|
||||
|
||||
HRESULT FlushPart() throw();
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
|
||||
COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {}
|
||||
~COutBuffer() { Free(); }
|
||||
|
||||
bool Create(UInt32 bufSize) throw();
|
||||
void Free() throw();
|
||||
|
||||
void SetMemStream(Byte *buf) { _buf2 = buf; }
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init() throw();
|
||||
HRESULT Flush() throw();
|
||||
void FlushWithCheck();
|
||||
|
||||
void WriteByte(Byte b)
|
||||
{
|
||||
UInt32 pos = _pos;
|
||||
_buf[pos] = b;
|
||||
pos++;
|
||||
_pos = pos;
|
||||
if (pos == _limitPos)
|
||||
FlushWithCheck();
|
||||
}
|
||||
void WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
WriteByte(((const Byte *)data)[i]);
|
||||
}
|
||||
|
||||
UInt64 GetProcessedSize() const throw();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,142 +1,142 @@
|
||||
// OutMemStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutMemStream.h"
|
||||
|
||||
void COutMemStream::Free()
|
||||
{
|
||||
Blocks.Free(_memManager);
|
||||
Blocks.LockMode = true;
|
||||
}
|
||||
|
||||
void COutMemStream::Init()
|
||||
{
|
||||
WriteToRealStreamEvent.Reset();
|
||||
_unlockEventWasSent = false;
|
||||
_realStreamMode = false;
|
||||
Free();
|
||||
_curBlockPos = 0;
|
||||
_curBlockIndex = 0;
|
||||
}
|
||||
|
||||
void COutMemStream::DetachData(CMemLockBlocks &blocks)
|
||||
{
|
||||
Blocks.Detach(blocks, _memManager);
|
||||
Free();
|
||||
}
|
||||
|
||||
|
||||
HRESULT COutMemStream::WriteToRealStream()
|
||||
{
|
||||
RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));
|
||||
Blocks.Free(_memManager);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
return OutSeqStream->Write(data, size, processedSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
if (_curBlockIndex < Blocks.Blocks.Size())
|
||||
{
|
||||
Byte *p = (Byte *)Blocks.Blocks[_curBlockIndex] + _curBlockPos;
|
||||
size_t curSize = _memManager->GetBlockSize() - _curBlockPos;
|
||||
if (size < curSize)
|
||||
curSize = size;
|
||||
memcpy(p, data, curSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize += (UInt32)curSize;
|
||||
data = (const void *)((const Byte *)data + curSize);
|
||||
size -= (UInt32)curSize;
|
||||
_curBlockPos += curSize;
|
||||
|
||||
UInt64 pos64 = GetPos();
|
||||
if (pos64 > Blocks.TotalSize)
|
||||
Blocks.TotalSize = pos64;
|
||||
if (_curBlockPos == _memManager->GetBlockSize())
|
||||
{
|
||||
_curBlockIndex++;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore };
|
||||
DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE);
|
||||
switch (waitResult)
|
||||
{
|
||||
case (WAIT_OBJECT_0 + 0):
|
||||
return StopWriteResult;
|
||||
case (WAIT_OBJECT_0 + 1):
|
||||
{
|
||||
_realStreamMode = true;
|
||||
RINOK(WriteToRealStream());
|
||||
UInt32 processedSize2;
|
||||
HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
|
||||
if (processedSize != 0)
|
||||
*processedSize += processedSize2;
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
case (WAIT_OBJECT_0 + 2):
|
||||
{
|
||||
// it has bug: no write.
|
||||
if (!Blocks.SwitchToNoLockMode(_memManager))
|
||||
return E_FAIL;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case (WAIT_OBJECT_0 + 2):
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
Blocks.Blocks.Add(_memManager->AllocateBlock());
|
||||
if (Blocks.Blocks.Back() == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
if (seekOrigin == STREAM_SEEK_CUR)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
else if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
_curBlockIndex = 0;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
else
|
||||
return E_NOTIMPL;
|
||||
if (newPosition)
|
||||
*newPosition = GetPos();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->SetSize(newSize);
|
||||
}
|
||||
Blocks.TotalSize = newSize;
|
||||
return S_OK;
|
||||
}
|
||||
// OutMemStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutMemStream.h"
|
||||
|
||||
void COutMemStream::Free()
|
||||
{
|
||||
Blocks.Free(_memManager);
|
||||
Blocks.LockMode = true;
|
||||
}
|
||||
|
||||
void COutMemStream::Init()
|
||||
{
|
||||
WriteToRealStreamEvent.Reset();
|
||||
_unlockEventWasSent = false;
|
||||
_realStreamMode = false;
|
||||
Free();
|
||||
_curBlockPos = 0;
|
||||
_curBlockIndex = 0;
|
||||
}
|
||||
|
||||
void COutMemStream::DetachData(CMemLockBlocks &blocks)
|
||||
{
|
||||
Blocks.Detach(blocks, _memManager);
|
||||
Free();
|
||||
}
|
||||
|
||||
|
||||
HRESULT COutMemStream::WriteToRealStream()
|
||||
{
|
||||
RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));
|
||||
Blocks.Free(_memManager);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
return OutSeqStream->Write(data, size, processedSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
if (_curBlockIndex < Blocks.Blocks.Size())
|
||||
{
|
||||
Byte *p = (Byte *)Blocks.Blocks[_curBlockIndex] + _curBlockPos;
|
||||
size_t curSize = _memManager->GetBlockSize() - _curBlockPos;
|
||||
if (size < curSize)
|
||||
curSize = size;
|
||||
memcpy(p, data, curSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize += (UInt32)curSize;
|
||||
data = (const void *)((const Byte *)data + curSize);
|
||||
size -= (UInt32)curSize;
|
||||
_curBlockPos += curSize;
|
||||
|
||||
UInt64 pos64 = GetPos();
|
||||
if (pos64 > Blocks.TotalSize)
|
||||
Blocks.TotalSize = pos64;
|
||||
if (_curBlockPos == _memManager->GetBlockSize())
|
||||
{
|
||||
_curBlockIndex++;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore };
|
||||
DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE);
|
||||
switch (waitResult)
|
||||
{
|
||||
case (WAIT_OBJECT_0 + 0):
|
||||
return StopWriteResult;
|
||||
case (WAIT_OBJECT_0 + 1):
|
||||
{
|
||||
_realStreamMode = true;
|
||||
RINOK(WriteToRealStream());
|
||||
UInt32 processedSize2;
|
||||
HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
|
||||
if (processedSize != 0)
|
||||
*processedSize += processedSize2;
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
case (WAIT_OBJECT_0 + 2):
|
||||
{
|
||||
// it has bug: no write.
|
||||
if (!Blocks.SwitchToNoLockMode(_memManager))
|
||||
return E_FAIL;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case (WAIT_OBJECT_0 + 2):
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
Blocks.Blocks.Add(_memManager->AllocateBlock());
|
||||
if (Blocks.Blocks.Back() == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
if (seekOrigin == STREAM_SEEK_CUR)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
else if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
_curBlockIndex = 0;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
else
|
||||
return E_NOTIMPL;
|
||||
if (newPosition)
|
||||
*newPosition = GetPos();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->SetSize(newSize);
|
||||
}
|
||||
Blocks.TotalSize = newSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
// OutMemStream.h
|
||||
|
||||
#ifndef __OUT_MEM_STREAM_H
|
||||
#define __OUT_MEM_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "MemBlocks.h"
|
||||
|
||||
class COutMemStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMemBlockManagerMt *_memManager;
|
||||
unsigned _curBlockIndex;
|
||||
size_t _curBlockPos;
|
||||
bool _realStreamMode;
|
||||
|
||||
bool _unlockEventWasSent;
|
||||
NWindows::NSynchronization::CAutoResetEvent StopWritingEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent;
|
||||
// NWindows::NSynchronization::CAutoResetEvent NoLockEvent;
|
||||
|
||||
HRESULT StopWriteResult;
|
||||
CMemLockBlocks Blocks;
|
||||
|
||||
UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }
|
||||
|
||||
CMyComPtr<ISequentialOutStream> OutSeqStream;
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
public:
|
||||
|
||||
HRes CreateEvents()
|
||||
{
|
||||
RINOK(StopWritingEvent.CreateIfNotCreated());
|
||||
return WriteToRealStreamEvent.CreateIfNotCreated();
|
||||
}
|
||||
|
||||
void SetOutStream(IOutStream *outStream)
|
||||
{
|
||||
OutStream = outStream;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void SetSeqOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
OutStream = NULL;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void ReleaseOutStream()
|
||||
{
|
||||
OutStream.Release();
|
||||
OutSeqStream.Release();
|
||||
}
|
||||
|
||||
COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { }
|
||||
|
||||
~COutMemStream() { Free(); }
|
||||
void Free();
|
||||
|
||||
void Init();
|
||||
HRESULT WriteToRealStream();
|
||||
|
||||
void DetachData(CMemLockBlocks &blocks);
|
||||
|
||||
bool WasUnlockEventSent() const { return _unlockEventWasSent; }
|
||||
|
||||
void SetRealStreamMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
WriteToRealStreamEvent.Set();
|
||||
}
|
||||
|
||||
/*
|
||||
void SetNoLockMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
NoLockEvent.Set();
|
||||
}
|
||||
*/
|
||||
|
||||
void StopWriting(HRESULT res)
|
||||
{
|
||||
StopWriteResult = res;
|
||||
StopWritingEvent.Set();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// OutMemStream.h
|
||||
|
||||
#ifndef __OUT_MEM_STREAM_H
|
||||
#define __OUT_MEM_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "MemBlocks.h"
|
||||
|
||||
class COutMemStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMemBlockManagerMt *_memManager;
|
||||
unsigned _curBlockIndex;
|
||||
size_t _curBlockPos;
|
||||
bool _realStreamMode;
|
||||
|
||||
bool _unlockEventWasSent;
|
||||
NWindows::NSynchronization::CAutoResetEvent StopWritingEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent;
|
||||
// NWindows::NSynchronization::CAutoResetEvent NoLockEvent;
|
||||
|
||||
HRESULT StopWriteResult;
|
||||
CMemLockBlocks Blocks;
|
||||
|
||||
UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }
|
||||
|
||||
CMyComPtr<ISequentialOutStream> OutSeqStream;
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
public:
|
||||
|
||||
HRes CreateEvents()
|
||||
{
|
||||
RINOK(StopWritingEvent.CreateIfNotCreated());
|
||||
return WriteToRealStreamEvent.CreateIfNotCreated();
|
||||
}
|
||||
|
||||
void SetOutStream(IOutStream *outStream)
|
||||
{
|
||||
OutStream = outStream;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void SetSeqOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
OutStream = NULL;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void ReleaseOutStream()
|
||||
{
|
||||
OutStream.Release();
|
||||
OutSeqStream.Release();
|
||||
}
|
||||
|
||||
COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { }
|
||||
|
||||
~COutMemStream() { Free(); }
|
||||
void Free();
|
||||
|
||||
void Init();
|
||||
HRESULT WriteToRealStream();
|
||||
|
||||
void DetachData(CMemLockBlocks &blocks);
|
||||
|
||||
bool WasUnlockEventSent() const { return _unlockEventWasSent; }
|
||||
|
||||
void SetRealStreamMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
WriteToRealStreamEvent.Set();
|
||||
}
|
||||
|
||||
/*
|
||||
void SetNoLockMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
NoLockEvent.Set();
|
||||
}
|
||||
*/
|
||||
|
||||
void StopWriting(HRESULT res)
|
||||
{
|
||||
StopWriteResult = res;
|
||||
StopWritingEvent.Set();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
// ProgressMt.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressMt.h"
|
||||
|
||||
void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes.Clear();
|
||||
OutSizes.Clear();
|
||||
for (int i = 0; i < numItems; i++)
|
||||
{
|
||||
InSizes.Add(0);
|
||||
OutSizes.Add(0);
|
||||
}
|
||||
TotalInSize = 0;
|
||||
TotalOutSize = 0;
|
||||
_progress = progress;
|
||||
}
|
||||
|
||||
void CMtCompressProgressMixer::Reinit(int index)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes[index] = 0;
|
||||
OutSizes[index] = 0;
|
||||
}
|
||||
|
||||
HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
if (inSize != 0)
|
||||
{
|
||||
UInt64 diff = *inSize - InSizes[index];
|
||||
InSizes[index] = *inSize;
|
||||
TotalInSize += diff;
|
||||
}
|
||||
if (outSize != 0)
|
||||
{
|
||||
UInt64 diff = *outSize - OutSizes[index];
|
||||
OutSizes[index] = *outSize;
|
||||
TotalOutSize += diff;
|
||||
}
|
||||
if (_progress)
|
||||
return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetRatioInfo(_index, inSize, outSize);
|
||||
}
|
||||
// ProgressMt.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressMt.h"
|
||||
|
||||
void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes.Clear();
|
||||
OutSizes.Clear();
|
||||
for (int i = 0; i < numItems; i++)
|
||||
{
|
||||
InSizes.Add(0);
|
||||
OutSizes.Add(0);
|
||||
}
|
||||
TotalInSize = 0;
|
||||
TotalOutSize = 0;
|
||||
_progress = progress;
|
||||
}
|
||||
|
||||
void CMtCompressProgressMixer::Reinit(int index)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes[index] = 0;
|
||||
OutSizes[index] = 0;
|
||||
}
|
||||
|
||||
HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
if (inSize != 0)
|
||||
{
|
||||
UInt64 diff = *inSize - InSizes[index];
|
||||
InSizes[index] = *inSize;
|
||||
TotalInSize += diff;
|
||||
}
|
||||
if (outSize != 0)
|
||||
{
|
||||
UInt64 diff = *outSize - OutSizes[index];
|
||||
OutSizes[index] = *outSize;
|
||||
TotalOutSize += diff;
|
||||
}
|
||||
if (_progress)
|
||||
return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetRatioInfo(_index, inSize, outSize);
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
// ProgressMt.h
|
||||
|
||||
#ifndef __PROGRESSMT_H
|
||||
#define __PROGRESSMT_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CMtCompressProgressMixer
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
UInt64 TotalInSize;
|
||||
UInt64 TotalOutSize;
|
||||
public:
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
void Init(int numItems, ICompressProgressInfo *progress);
|
||||
void Reinit(int index);
|
||||
HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CMtCompressProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMtCompressProgressMixer *_progress;
|
||||
int _index;
|
||||
public:
|
||||
void Init(CMtCompressProgressMixer *progress, int index)
|
||||
{
|
||||
_progress = progress;
|
||||
_index = index;
|
||||
}
|
||||
void Reinit() { _progress->Reinit(_index); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// ProgressMt.h
|
||||
|
||||
#ifndef __PROGRESSMT_H
|
||||
#define __PROGRESSMT_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CMtCompressProgressMixer
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
UInt64 TotalInSize;
|
||||
UInt64 TotalOutSize;
|
||||
public:
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
void Init(int numItems, ICompressProgressInfo *progress);
|
||||
void Reinit(int index);
|
||||
HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CMtCompressProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMtCompressProgressMixer *_progress;
|
||||
int _index;
|
||||
public:
|
||||
void Init(CMtCompressProgressMixer *progress, int index)
|
||||
{
|
||||
_progress = progress;
|
||||
_index = index;
|
||||
}
|
||||
void Reinit() { _progress->Reinit(_index); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
// ProgressUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressUtils.h"
|
||||
|
||||
CLocalProgress::CLocalProgress():
|
||||
ProgressOffset(0),
|
||||
InSize(0),
|
||||
OutSize(0),
|
||||
SendRatio(true),
|
||||
SendProgress(true)
|
||||
{}
|
||||
|
||||
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
|
||||
{
|
||||
_ratioProgress.Release();
|
||||
_progress = progress;
|
||||
_progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);
|
||||
_inSizeIsMain = inSizeIsMain;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
UInt64 inSize2 = InSize;
|
||||
UInt64 outSize2 = OutSize;
|
||||
|
||||
if (inSize)
|
||||
inSize2 += (*inSize);
|
||||
if (outSize)
|
||||
outSize2 += (*outSize);
|
||||
|
||||
if (SendRatio && _ratioProgress)
|
||||
{
|
||||
RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));
|
||||
}
|
||||
|
||||
if (SendProgress)
|
||||
{
|
||||
inSize2 += ProgressOffset;
|
||||
outSize2 += ProgressOffset;
|
||||
return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CLocalProgress::SetCur()
|
||||
{
|
||||
return SetRatioInfo(NULL, NULL);
|
||||
}
|
||||
// ProgressUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressUtils.h"
|
||||
|
||||
CLocalProgress::CLocalProgress():
|
||||
ProgressOffset(0),
|
||||
InSize(0),
|
||||
OutSize(0),
|
||||
SendRatio(true),
|
||||
SendProgress(true)
|
||||
{}
|
||||
|
||||
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
|
||||
{
|
||||
_ratioProgress.Release();
|
||||
_progress = progress;
|
||||
_progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);
|
||||
_inSizeIsMain = inSizeIsMain;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
UInt64 inSize2 = InSize;
|
||||
UInt64 outSize2 = OutSize;
|
||||
|
||||
if (inSize)
|
||||
inSize2 += (*inSize);
|
||||
if (outSize)
|
||||
outSize2 += (*outSize);
|
||||
|
||||
if (SendRatio && _ratioProgress)
|
||||
{
|
||||
RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));
|
||||
}
|
||||
|
||||
if (SendProgress)
|
||||
{
|
||||
inSize2 += ProgressOffset;
|
||||
outSize2 += ProgressOffset;
|
||||
return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CLocalProgress::SetCur()
|
||||
{
|
||||
return SetRatioInfo(NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
// ProgressUtils.h
|
||||
|
||||
#ifndef __PROGRESS_UTILS_H
|
||||
#define __PROGRESS_UTILS_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CLocalProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IProgress> _progress;
|
||||
CMyComPtr<ICompressProgressInfo> _ratioProgress;
|
||||
bool _inSizeIsMain;
|
||||
public:
|
||||
UInt64 ProgressOffset;
|
||||
UInt64 InSize;
|
||||
UInt64 OutSize;
|
||||
bool SendRatio;
|
||||
bool SendProgress;
|
||||
|
||||
CLocalProgress();
|
||||
|
||||
void Init(IProgress *progress, bool inSizeIsMain);
|
||||
HRESULT SetCur();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
// ProgressUtils.h
|
||||
|
||||
#ifndef __PROGRESS_UTILS_H
|
||||
#define __PROGRESS_UTILS_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CLocalProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IProgress> _progress;
|
||||
CMyComPtr<ICompressProgressInfo> _ratioProgress;
|
||||
bool _inSizeIsMain;
|
||||
public:
|
||||
UInt64 ProgressOffset;
|
||||
UInt64 InSize;
|
||||
UInt64 OutSize;
|
||||
bool SendRatio;
|
||||
bool SendProgress;
|
||||
|
||||
CLocalProgress();
|
||||
|
||||
void Init(IProgress *progress, bool inSizeIsMain);
|
||||
HRESULT SetCur();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
// PropId.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include "../PropID.h"
|
||||
|
||||
// VARTYPE
|
||||
const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
|
||||
{
|
||||
VT_EMPTY,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_FILETIME,
|
||||
VT_FILETIME,
|
||||
VT_FILETIME,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR, // or VT_UI8 kpidUnpackVer
|
||||
VT_UI4, // or VT_UI8 kpidVolume
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4, // kpidChecksum
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR, // or VT_UI8 kpidId
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR, // kpidNtSecure
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BSTR, // SHA-1
|
||||
VT_BSTR, // SHA-256
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR, // kpidNtReparse
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_BSTR
|
||||
};
|
||||
// PropId.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include "../PropID.h"
|
||||
|
||||
// VARTYPE
|
||||
const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
|
||||
{
|
||||
VT_EMPTY,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_FILETIME,
|
||||
VT_FILETIME,
|
||||
VT_FILETIME,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR, // or VT_UI8 kpidUnpackVer
|
||||
VT_UI4, // or VT_UI8 kpidVolume
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4, // kpidChecksum
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_BSTR, // or VT_UI8 kpidId
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR, // kpidNtSecure
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BSTR, // SHA-1
|
||||
VT_BSTR, // SHA-256
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BSTR,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_BOOL,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BSTR, // kpidNtReparse
|
||||
VT_BSTR,
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BOOL,
|
||||
VT_BSTR,
|
||||
VT_BSTR
|
||||
};
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
// RegisterArc.h
|
||||
|
||||
#ifndef __REGISTER_ARC_H
|
||||
#define __REGISTER_ARC_H
|
||||
|
||||
#include "../Archive/IArchive.h"
|
||||
|
||||
struct CArcInfo
|
||||
{
|
||||
UInt16 Flags;
|
||||
Byte Id;
|
||||
Byte SignatureSize;
|
||||
UInt16 SignatureOffset;
|
||||
|
||||
const Byte *Signature;
|
||||
const char *Name;
|
||||
const char *Ext;
|
||||
const char *AddExt;
|
||||
|
||||
Func_CreateInArchive CreateInArchive;
|
||||
Func_CreateOutArchive CreateOutArchive;
|
||||
Func_IsArc IsArc;
|
||||
|
||||
bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }
|
||||
};
|
||||
|
||||
void RegisterArc(const CArcInfo *arcInfo) throw();
|
||||
|
||||
|
||||
#define IMP_CreateArcIn_2(c) \
|
||||
static IInArchive *CreateArc() { return new c; }
|
||||
|
||||
#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define IMP_CreateArcOut
|
||||
#define CreateArcOut NULL
|
||||
#else
|
||||
#define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); }
|
||||
#endif
|
||||
|
||||
#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \
|
||||
|
||||
#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \
|
||||
static CRegisterArc g_RegisterArc;
|
||||
|
||||
|
||||
#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc)
|
||||
|
||||
#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc)
|
||||
|
||||
#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc)
|
||||
|
||||
#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \
|
||||
REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc)
|
||||
|
||||
|
||||
#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc)
|
||||
|
||||
#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \
|
||||
struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \
|
||||
static CRegisterArcDecSig g_RegisterArc;
|
||||
|
||||
#endif
|
||||
// RegisterArc.h
|
||||
|
||||
#ifndef __REGISTER_ARC_H
|
||||
#define __REGISTER_ARC_H
|
||||
|
||||
#include "../Archive/IArchive.h"
|
||||
|
||||
struct CArcInfo
|
||||
{
|
||||
UInt16 Flags;
|
||||
Byte Id;
|
||||
Byte SignatureSize;
|
||||
UInt16 SignatureOffset;
|
||||
|
||||
const Byte *Signature;
|
||||
const char *Name;
|
||||
const char *Ext;
|
||||
const char *AddExt;
|
||||
|
||||
Func_CreateInArchive CreateInArchive;
|
||||
Func_CreateOutArchive CreateOutArchive;
|
||||
Func_IsArc IsArc;
|
||||
|
||||
bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }
|
||||
};
|
||||
|
||||
void RegisterArc(const CArcInfo *arcInfo) throw();
|
||||
|
||||
|
||||
#define IMP_CreateArcIn_2(c) \
|
||||
static IInArchive *CreateArc() { return new c; }
|
||||
|
||||
#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define IMP_CreateArcOut
|
||||
#define CreateArcOut NULL
|
||||
#else
|
||||
#define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); }
|
||||
#endif
|
||||
|
||||
#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \
|
||||
|
||||
#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
|
||||
struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \
|
||||
static CRegisterArc g_RegisterArc;
|
||||
|
||||
|
||||
#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc)
|
||||
|
||||
#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc)
|
||||
|
||||
#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc)
|
||||
|
||||
#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \
|
||||
REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc)
|
||||
|
||||
|
||||
#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc)
|
||||
|
||||
#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \
|
||||
struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \
|
||||
static CRegisterArcDecSig g_RegisterArc;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
// RegisterCodec.h
|
||||
|
||||
#ifndef __REGISTER_CODEC_H
|
||||
#define __REGISTER_CODEC_H
|
||||
|
||||
#include "../Common/MethodId.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
typedef void * (*CreateCodecP)();
|
||||
|
||||
struct CCodecInfo
|
||||
{
|
||||
CreateCodecP CreateDecoder;
|
||||
CreateCodecP CreateEncoder;
|
||||
CMethodId Id;
|
||||
const char *Name;
|
||||
UInt32 NumStreams;
|
||||
bool IsFilter;
|
||||
};
|
||||
|
||||
void RegisterCodec(const CCodecInfo *codecInfo) throw();
|
||||
|
||||
|
||||
#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); }
|
||||
#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder)
|
||||
|
||||
#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
|
||||
#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo =
|
||||
|
||||
#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
|
||||
REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
|
||||
static REGISTER_CODEC_NAME(x) g_RegisterCodec;
|
||||
|
||||
|
||||
#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
|
||||
#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =
|
||||
|
||||
#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
|
||||
REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
|
||||
RegisterCodec(&g_CodecsInfo[i]); }}; \
|
||||
static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
|
||||
|
||||
|
||||
#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \
|
||||
REGISTER_CODEC_VAR \
|
||||
{ crDec, crEnc, id, name, 1, false }; \
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_CODEC_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_CODEC_2(x, CreateDec, NULL, id, name)
|
||||
#else
|
||||
#define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_CODEC_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \
|
||||
REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter)
|
||||
|
||||
#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \
|
||||
{ crDec, crEnc, id, name, 1, true }
|
||||
|
||||
#define REGISTER_FILTER(x, crDec, crEnc, id, name) \
|
||||
REGISTER_CODEC_VAR \
|
||||
REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_FILTER_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_FILTER(x, CreateDec, NULL, id, name)
|
||||
#else
|
||||
#define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_FILTER_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \
|
||||
REGISTER_FILTER(x, CreateDec, CreateEnc, id, name)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct CHasherInfo
|
||||
{
|
||||
IHasher * (*CreateHasher)();
|
||||
CMethodId Id;
|
||||
const char *Name;
|
||||
UInt32 DigestSize;
|
||||
};
|
||||
|
||||
void RegisterHasher(const CHasherInfo *hasher) throw();
|
||||
|
||||
#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x
|
||||
|
||||
#define REGISTER_HASHER(cls, id, name, size) \
|
||||
STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \
|
||||
static IHasher *CreateHasherSpec() { return new cls(); } \
|
||||
static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \
|
||||
struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
|
||||
static REGISTER_HASHER_NAME(cls) g_RegisterHasher;
|
||||
// RegisterCodec.h
|
||||
|
||||
#endif
|
||||
#ifndef __REGISTER_CODEC_H
|
||||
#define __REGISTER_CODEC_H
|
||||
|
||||
#include "../Common/MethodId.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
typedef void * (*CreateCodecP)();
|
||||
|
||||
struct CCodecInfo
|
||||
{
|
||||
CreateCodecP CreateDecoder;
|
||||
CreateCodecP CreateEncoder;
|
||||
CMethodId Id;
|
||||
const char *Name;
|
||||
UInt32 NumStreams;
|
||||
bool IsFilter;
|
||||
};
|
||||
|
||||
void RegisterCodec(const CCodecInfo *codecInfo) throw();
|
||||
|
||||
|
||||
#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); }
|
||||
#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder)
|
||||
|
||||
#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
|
||||
#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo =
|
||||
|
||||
#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
|
||||
REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
|
||||
static REGISTER_CODEC_NAME(x) g_RegisterCodec;
|
||||
|
||||
|
||||
#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
|
||||
#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =
|
||||
|
||||
#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
|
||||
REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
|
||||
RegisterCodec(&g_CodecsInfo[i]); }}; \
|
||||
static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
|
||||
|
||||
|
||||
#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \
|
||||
REGISTER_CODEC_VAR \
|
||||
{ crDec, crEnc, id, name, 1, false }; \
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_CODEC_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_CODEC_2(x, CreateDec, NULL, id, name)
|
||||
#else
|
||||
#define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_CODEC_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \
|
||||
REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter)
|
||||
|
||||
#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \
|
||||
{ crDec, crEnc, id, name, 1, true }
|
||||
|
||||
#define REGISTER_FILTER(x, crDec, crEnc, id, name) \
|
||||
REGISTER_CODEC_VAR \
|
||||
REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_FILTER_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_FILTER(x, CreateDec, NULL, id, name)
|
||||
#else
|
||||
#define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_FILTER_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \
|
||||
REGISTER_FILTER(x, CreateDec, CreateEnc, id, name)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct CHasherInfo
|
||||
{
|
||||
IHasher * (*CreateHasher)();
|
||||
CMethodId Id;
|
||||
const char *Name;
|
||||
UInt32 DigestSize;
|
||||
};
|
||||
|
||||
void RegisterHasher(const CHasherInfo *hasher) throw();
|
||||
|
||||
#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x
|
||||
|
||||
#define REGISTER_HASHER(cls, id, name, size) \
|
||||
STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \
|
||||
static IHasher *CreateHasherSpec() { return new cls(); } \
|
||||
static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \
|
||||
struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
|
||||
static REGISTER_HASHER_NAME(cls) g_RegisterHasher;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
// StreamBinder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "StreamBinder.h"
|
||||
|
||||
class CBinderInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderInStream() { _binder->CloseRead(); }
|
||||
CBinderInStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{ return _binder->Read(data, size, processedSize); }
|
||||
|
||||
class CBinderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderOutStream() { _binder->CloseWrite(); }
|
||||
CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{ return _binder->Write(data, size, processedSize); }
|
||||
|
||||
|
||||
|
||||
WRes CStreamBinder::CreateEvents()
|
||||
{
|
||||
RINOK(_canWrite_Event.Create());
|
||||
RINOK(_canRead_Event.Create());
|
||||
return _readingWasClosed_Event.Create();
|
||||
}
|
||||
|
||||
void CStreamBinder::ReInit()
|
||||
{
|
||||
_canWrite_Event.Reset();
|
||||
_canRead_Event.Reset();
|
||||
_readingWasClosed_Event.Reset();
|
||||
|
||||
// _readingWasClosed = false;
|
||||
_readingWasClosed2 = false;
|
||||
|
||||
_waitWrite = true;
|
||||
_bufSize = 0;
|
||||
_buf = NULL;
|
||||
ProcessedSize = 0;
|
||||
// WritingWasCut = false;
|
||||
}
|
||||
|
||||
|
||||
void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
|
||||
{
|
||||
// _readingWasClosed = false;
|
||||
_readingWasClosed2 = false;
|
||||
|
||||
_waitWrite = true;
|
||||
_bufSize = 0;
|
||||
_buf = NULL;
|
||||
ProcessedSize = 0;
|
||||
// WritingWasCut = false;
|
||||
|
||||
CBinderInStream *inStreamSpec = new CBinderInStream(this);
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
*inStream = inStreamLoc.Detach();
|
||||
|
||||
CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
|
||||
CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
|
||||
*outStream = outStreamLoc.Detach();
|
||||
}
|
||||
|
||||
// (_canRead_Event && _bufSize == 0) means that stream is finished.
|
||||
|
||||
HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size != 0)
|
||||
{
|
||||
if (_waitWrite)
|
||||
{
|
||||
RINOK(_canRead_Event.Lock());
|
||||
_waitWrite = false;
|
||||
}
|
||||
if (size > _bufSize)
|
||||
size = _bufSize;
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(data, _buf, size);
|
||||
_buf = ((const Byte *)_buf) + size;
|
||||
ProcessedSize += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_bufSize -= size;
|
||||
if (_bufSize == 0)
|
||||
{
|
||||
_waitWrite = true;
|
||||
_canRead_Event.Reset();
|
||||
_canWrite_Event.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (!_readingWasClosed2)
|
||||
{
|
||||
_buf = data;
|
||||
_bufSize = size;
|
||||
_canRead_Event.Set();
|
||||
|
||||
/*
|
||||
_canWrite_Event.Lock();
|
||||
if (_readingWasClosed)
|
||||
_readingWasClosed2 = true;
|
||||
*/
|
||||
|
||||
HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult >= WAIT_OBJECT_0 + 2)
|
||||
return E_FAIL;
|
||||
|
||||
size -= _bufSize;
|
||||
if (size != 0)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
// if (waitResult == WAIT_OBJECT_0 + 1)
|
||||
_readingWasClosed2 = true;
|
||||
}
|
||||
|
||||
// WritingWasCut = true;
|
||||
return k_My_HRESULT_WritingWasCut;
|
||||
}
|
||||
// StreamBinder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "StreamBinder.h"
|
||||
|
||||
class CBinderInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderInStream() { _binder->CloseRead(); }
|
||||
CBinderInStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{ return _binder->Read(data, size, processedSize); }
|
||||
|
||||
class CBinderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderOutStream() { _binder->CloseWrite(); }
|
||||
CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{ return _binder->Write(data, size, processedSize); }
|
||||
|
||||
|
||||
|
||||
WRes CStreamBinder::CreateEvents()
|
||||
{
|
||||
RINOK(_canWrite_Event.Create());
|
||||
RINOK(_canRead_Event.Create());
|
||||
return _readingWasClosed_Event.Create();
|
||||
}
|
||||
|
||||
void CStreamBinder::ReInit()
|
||||
{
|
||||
_canWrite_Event.Reset();
|
||||
_canRead_Event.Reset();
|
||||
_readingWasClosed_Event.Reset();
|
||||
|
||||
// _readingWasClosed = false;
|
||||
_readingWasClosed2 = false;
|
||||
|
||||
_waitWrite = true;
|
||||
_bufSize = 0;
|
||||
_buf = NULL;
|
||||
ProcessedSize = 0;
|
||||
// WritingWasCut = false;
|
||||
}
|
||||
|
||||
|
||||
void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
|
||||
{
|
||||
// _readingWasClosed = false;
|
||||
_readingWasClosed2 = false;
|
||||
|
||||
_waitWrite = true;
|
||||
_bufSize = 0;
|
||||
_buf = NULL;
|
||||
ProcessedSize = 0;
|
||||
// WritingWasCut = false;
|
||||
|
||||
CBinderInStream *inStreamSpec = new CBinderInStream(this);
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
*inStream = inStreamLoc.Detach();
|
||||
|
||||
CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
|
||||
CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
|
||||
*outStream = outStreamLoc.Detach();
|
||||
}
|
||||
|
||||
// (_canRead_Event && _bufSize == 0) means that stream is finished.
|
||||
|
||||
HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size != 0)
|
||||
{
|
||||
if (_waitWrite)
|
||||
{
|
||||
RINOK(_canRead_Event.Lock());
|
||||
_waitWrite = false;
|
||||
}
|
||||
if (size > _bufSize)
|
||||
size = _bufSize;
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(data, _buf, size);
|
||||
_buf = ((const Byte *)_buf) + size;
|
||||
ProcessedSize += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_bufSize -= size;
|
||||
if (_bufSize == 0)
|
||||
{
|
||||
_waitWrite = true;
|
||||
_canRead_Event.Reset();
|
||||
_canWrite_Event.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (!_readingWasClosed2)
|
||||
{
|
||||
_buf = data;
|
||||
_bufSize = size;
|
||||
_canRead_Event.Set();
|
||||
|
||||
/*
|
||||
_canWrite_Event.Lock();
|
||||
if (_readingWasClosed)
|
||||
_readingWasClosed2 = true;
|
||||
*/
|
||||
|
||||
HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult >= WAIT_OBJECT_0 + 2)
|
||||
return E_FAIL;
|
||||
|
||||
size -= _bufSize;
|
||||
if (size != 0)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
// if (waitResult == WAIT_OBJECT_0 + 1)
|
||||
_readingWasClosed2 = true;
|
||||
}
|
||||
|
||||
// WritingWasCut = true;
|
||||
return k_My_HRESULT_WritingWasCut;
|
||||
}
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
// StreamBinder.h
|
||||
|
||||
#ifndef __STREAM_BINDER_H
|
||||
#define __STREAM_BINDER_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
/*
|
||||
We don't use probably UNSAFE version:
|
||||
reader thread:
|
||||
_canWrite_Event.Set();
|
||||
_readingWasClosed = true
|
||||
_canWrite_Event.Set();
|
||||
writer thread:
|
||||
_canWrite_Event.Wait()
|
||||
if (_readingWasClosed)
|
||||
Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set?
|
||||
*/
|
||||
|
||||
class CStreamBinder
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent _canWrite_Event;
|
||||
NWindows::NSynchronization::CManualResetEvent _canRead_Event;
|
||||
NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;
|
||||
|
||||
// bool _readingWasClosed;
|
||||
bool _readingWasClosed2;
|
||||
// bool WritingWasCut;
|
||||
bool _waitWrite;
|
||||
UInt32 _bufSize;
|
||||
const void *_buf;
|
||||
public:
|
||||
UInt64 ProcessedSize;
|
||||
|
||||
WRes CreateEvents();
|
||||
void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream);
|
||||
|
||||
void ReInit();
|
||||
|
||||
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
|
||||
HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
void CloseRead()
|
||||
{
|
||||
_readingWasClosed_Event.Set();
|
||||
// _readingWasClosed = true;
|
||||
// _canWrite_Event.Set();
|
||||
}
|
||||
|
||||
void CloseWrite()
|
||||
{
|
||||
_buf = NULL;
|
||||
_bufSize = 0;
|
||||
_canRead_Event.Set();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
// StreamBinder.h
|
||||
|
||||
#ifndef __STREAM_BINDER_H
|
||||
#define __STREAM_BINDER_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
/*
|
||||
We don't use probably UNSAFE version:
|
||||
reader thread:
|
||||
_canWrite_Event.Set();
|
||||
_readingWasClosed = true
|
||||
_canWrite_Event.Set();
|
||||
writer thread:
|
||||
_canWrite_Event.Wait()
|
||||
if (_readingWasClosed)
|
||||
Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set?
|
||||
*/
|
||||
|
||||
class CStreamBinder
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent _canWrite_Event;
|
||||
NWindows::NSynchronization::CManualResetEvent _canRead_Event;
|
||||
NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;
|
||||
|
||||
// bool _readingWasClosed;
|
||||
bool _readingWasClosed2;
|
||||
// bool WritingWasCut;
|
||||
bool _waitWrite;
|
||||
UInt32 _bufSize;
|
||||
const void *_buf;
|
||||
public:
|
||||
UInt64 ProcessedSize;
|
||||
|
||||
WRes CreateEvents();
|
||||
void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream);
|
||||
|
||||
void ReInit();
|
||||
|
||||
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
|
||||
HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
void CloseRead()
|
||||
{
|
||||
_readingWasClosed_Event.Set();
|
||||
// _readingWasClosed = true;
|
||||
// _canWrite_Event.Set();
|
||||
}
|
||||
|
||||
void CloseWrite()
|
||||
{
|
||||
_buf = NULL;
|
||||
_bufSize = 0;
|
||||
_canRead_Event.Set();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,285 +1,285 @@
|
||||
// StreamObjects.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "StreamObjects.h"
|
||||
|
||||
STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= Buf.Size())
|
||||
return S_OK;
|
||||
size_t rem = Buf.Size() - (size_t)_pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);
|
||||
_pos += rem;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += Buf.Size(); break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _size)
|
||||
return S_OK;
|
||||
size_t rem = _size - (size_t)_pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
memcpy(data, _data + (size_t)_pos, rem);
|
||||
_pos += rem;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)
|
||||
{
|
||||
*stream = NULL;
|
||||
CBufInStream *inStreamSpec = new CBufInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
||||
inStreamSpec->Init((const Byte *)data, size, ref);
|
||||
*stream = streamTemp.Detach();
|
||||
}
|
||||
|
||||
void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
|
||||
{
|
||||
*stream = NULL;
|
||||
CBufferInStream *inStreamSpec = new CBufferInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
||||
inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
|
||||
inStreamSpec->Init();
|
||||
*stream = streamTemp.Detach();
|
||||
}
|
||||
|
||||
void CByteDynBuffer::Free() throw()
|
||||
{
|
||||
free(_buf);
|
||||
_buf = 0;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
|
||||
{
|
||||
if (cap <= _capacity)
|
||||
return true;
|
||||
size_t delta;
|
||||
if (_capacity > 64)
|
||||
delta = _capacity / 4;
|
||||
else if (_capacity > 8)
|
||||
delta = 16;
|
||||
else
|
||||
delta = 4;
|
||||
cap = MyMax(_capacity + delta, cap);
|
||||
Byte *buf = (Byte *)realloc(_buf, cap);
|
||||
if (!buf)
|
||||
return false;
|
||||
_buf = buf;
|
||||
_capacity = cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
|
||||
{
|
||||
addSize += _size;
|
||||
if (addSize < _size)
|
||||
return NULL;
|
||||
if (!_buffer.EnsureCapacity(addSize))
|
||||
return NULL;
|
||||
return (Byte *)_buffer + _size;
|
||||
}
|
||||
|
||||
void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
|
||||
{
|
||||
dest.CopyFrom((const Byte *)_buffer, _size);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
Byte *buf = GetBufPtrForWriting(size);
|
||||
if (!buf)
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(buf, data, size);
|
||||
UpdateSize(size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t rem = _size - _pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
if (rem != 0)
|
||||
{
|
||||
memcpy(_buffer + _pos, data, rem);
|
||||
_pos += rem;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return (rem != 0 || size == 0) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Write(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
|
||||
|
||||
void CCachedInStream::Free() throw()
|
||||
{
|
||||
MyFree(_tags);
|
||||
_tags = 0;
|
||||
MidFree(_data);
|
||||
_data = 0;
|
||||
}
|
||||
|
||||
bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()
|
||||
{
|
||||
unsigned sizeLog = blockSizeLog + numBlocksLog;
|
||||
if (sizeLog >= sizeof(size_t) * 8)
|
||||
return false;
|
||||
size_t dataSize = (size_t)1 << sizeLog;
|
||||
if (_data == 0 || dataSize != _dataSize)
|
||||
{
|
||||
MidFree(_data);
|
||||
_data = (Byte *)MidAlloc(dataSize);
|
||||
if (_data == 0)
|
||||
return false;
|
||||
_dataSize = dataSize;
|
||||
}
|
||||
if (_tags == 0 || numBlocksLog != _numBlocksLog)
|
||||
{
|
||||
MyFree(_tags);
|
||||
_tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
|
||||
if (_tags == 0)
|
||||
return false;
|
||||
_numBlocksLog = numBlocksLog;
|
||||
}
|
||||
_blockSizeLog = blockSizeLog;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCachedInStream::Init(UInt64 size) throw()
|
||||
{
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
size_t numBlocks = (size_t)1 << _numBlocksLog;
|
||||
for (size_t i = 0; i < numBlocks; i++)
|
||||
_tags[i] = kEmptyTag;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _size)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
UInt64 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
UInt64 cacheTag = _pos >> _blockSizeLog;
|
||||
size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
|
||||
Byte *p = _data + (cacheIndex << _blockSizeLog);
|
||||
if (_tags[cacheIndex] != cacheTag)
|
||||
{
|
||||
UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
|
||||
size_t blockSize = (size_t)1 << _blockSizeLog;
|
||||
if (blockSize > remInBlock)
|
||||
blockSize = (size_t)remInBlock;
|
||||
RINOK(ReadBlock(cacheTag, p, blockSize));
|
||||
_tags[cacheIndex] = cacheTag;
|
||||
}
|
||||
size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);
|
||||
UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);
|
||||
memcpy(data, p + offset, cur);
|
||||
if (processedSize)
|
||||
*processedSize += cur;
|
||||
data = (void *)((const Byte *)data + cur);
|
||||
_pos += cur;
|
||||
size -= cur;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
// StreamObjects.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "StreamObjects.h"
|
||||
|
||||
STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= Buf.Size())
|
||||
return S_OK;
|
||||
size_t rem = Buf.Size() - (size_t)_pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);
|
||||
_pos += rem;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += Buf.Size(); break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _size)
|
||||
return S_OK;
|
||||
size_t rem = _size - (size_t)_pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
memcpy(data, _data + (size_t)_pos, rem);
|
||||
_pos += rem;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)
|
||||
{
|
||||
*stream = NULL;
|
||||
CBufInStream *inStreamSpec = new CBufInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
||||
inStreamSpec->Init((const Byte *)data, size, ref);
|
||||
*stream = streamTemp.Detach();
|
||||
}
|
||||
|
||||
void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
|
||||
{
|
||||
*stream = NULL;
|
||||
CBufferInStream *inStreamSpec = new CBufferInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
||||
inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
|
||||
inStreamSpec->Init();
|
||||
*stream = streamTemp.Detach();
|
||||
}
|
||||
|
||||
void CByteDynBuffer::Free() throw()
|
||||
{
|
||||
free(_buf);
|
||||
_buf = 0;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
|
||||
{
|
||||
if (cap <= _capacity)
|
||||
return true;
|
||||
size_t delta;
|
||||
if (_capacity > 64)
|
||||
delta = _capacity / 4;
|
||||
else if (_capacity > 8)
|
||||
delta = 16;
|
||||
else
|
||||
delta = 4;
|
||||
cap = MyMax(_capacity + delta, cap);
|
||||
Byte *buf = (Byte *)realloc(_buf, cap);
|
||||
if (!buf)
|
||||
return false;
|
||||
_buf = buf;
|
||||
_capacity = cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
|
||||
{
|
||||
addSize += _size;
|
||||
if (addSize < _size)
|
||||
return NULL;
|
||||
if (!_buffer.EnsureCapacity(addSize))
|
||||
return NULL;
|
||||
return (Byte *)_buffer + _size;
|
||||
}
|
||||
|
||||
void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
|
||||
{
|
||||
dest.CopyFrom((const Byte *)_buffer, _size);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
Byte *buf = GetBufPtrForWriting(size);
|
||||
if (!buf)
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(buf, data, size);
|
||||
UpdateSize(size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t rem = _size - _pos;
|
||||
if (rem > size)
|
||||
rem = (size_t)size;
|
||||
if (rem != 0)
|
||||
{
|
||||
memcpy(_buffer + _pos, data, rem);
|
||||
_pos += rem;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)rem;
|
||||
return (rem != 0 || size == 0) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Write(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
|
||||
|
||||
void CCachedInStream::Free() throw()
|
||||
{
|
||||
MyFree(_tags);
|
||||
_tags = 0;
|
||||
MidFree(_data);
|
||||
_data = 0;
|
||||
}
|
||||
|
||||
bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()
|
||||
{
|
||||
unsigned sizeLog = blockSizeLog + numBlocksLog;
|
||||
if (sizeLog >= sizeof(size_t) * 8)
|
||||
return false;
|
||||
size_t dataSize = (size_t)1 << sizeLog;
|
||||
if (_data == 0 || dataSize != _dataSize)
|
||||
{
|
||||
MidFree(_data);
|
||||
_data = (Byte *)MidAlloc(dataSize);
|
||||
if (_data == 0)
|
||||
return false;
|
||||
_dataSize = dataSize;
|
||||
}
|
||||
if (_tags == 0 || numBlocksLog != _numBlocksLog)
|
||||
{
|
||||
MyFree(_tags);
|
||||
_tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
|
||||
if (_tags == 0)
|
||||
return false;
|
||||
_numBlocksLog = numBlocksLog;
|
||||
}
|
||||
_blockSizeLog = blockSizeLog;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCachedInStream::Init(UInt64 size) throw()
|
||||
{
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
size_t numBlocks = (size_t)1 << _numBlocksLog;
|
||||
for (size_t i = 0; i < numBlocks; i++)
|
||||
_tags[i] = kEmptyTag;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _size)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
UInt64 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
UInt64 cacheTag = _pos >> _blockSizeLog;
|
||||
size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
|
||||
Byte *p = _data + (cacheIndex << _blockSizeLog);
|
||||
if (_tags[cacheIndex] != cacheTag)
|
||||
{
|
||||
UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
|
||||
size_t blockSize = (size_t)1 << _blockSizeLog;
|
||||
if (blockSize > remInBlock)
|
||||
blockSize = (size_t)remInBlock;
|
||||
RINOK(ReadBlock(cacheTag, p, blockSize));
|
||||
_tags[cacheIndex] = cacheTag;
|
||||
}
|
||||
size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);
|
||||
UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);
|
||||
memcpy(data, p + offset, cur);
|
||||
if (processedSize)
|
||||
*processedSize += cur;
|
||||
data = (void *)((const Byte *)data + cur);
|
||||
_pos += cur;
|
||||
size -= cur;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,157 +1,157 @@
|
||||
// StreamObjects.h
|
||||
|
||||
#ifndef __STREAM_OBJECTS_H
|
||||
#define __STREAM_OBJECTS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CBufferInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _pos;
|
||||
public:
|
||||
CByteBuffer Buf;
|
||||
void Init() { _pos = 0; }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
struct CReferenceBuf:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteBuffer Buf;
|
||||
MY_UNKNOWN_IMP
|
||||
};
|
||||
|
||||
class CBufInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
const Byte *_data;
|
||||
UInt64 _pos;
|
||||
size_t _size;
|
||||
CMyComPtr<IUnknown> _ref;
|
||||
public:
|
||||
void Init(const Byte *data, size_t size, IUnknown *ref = 0)
|
||||
{
|
||||
_data = data;
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
_ref = ref;
|
||||
}
|
||||
void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream);
|
||||
void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream);
|
||||
inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream)
|
||||
{ Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }
|
||||
|
||||
class CByteDynBuffer
|
||||
{
|
||||
size_t _capacity;
|
||||
Byte *_buf;
|
||||
public:
|
||||
CByteDynBuffer(): _capacity(0), _buf(0) {};
|
||||
// there is no copy constructor. So don't copy this object.
|
||||
~CByteDynBuffer() { Free(); }
|
||||
void Free() throw();
|
||||
size_t GetCapacity() const { return _capacity; }
|
||||
operator Byte*() const { return _buf; }
|
||||
operator const Byte*() const { return _buf; }
|
||||
bool EnsureCapacity(size_t capacity) throw();
|
||||
};
|
||||
|
||||
class CDynBufSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteDynBuffer _buffer;
|
||||
size_t _size;
|
||||
public:
|
||||
CDynBufSeqOutStream(): _size(0) {}
|
||||
void Init() { _size = 0; }
|
||||
size_t GetSize() const { return _size; }
|
||||
const Byte *GetBuffer() const { return _buffer; }
|
||||
void CopyToBuffer(CByteBuffer &dest) const;
|
||||
Byte *GetBufPtrForWriting(size_t addSize);
|
||||
void UpdateSize(size_t addSize) { _size += addSize; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CBufPtrSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Byte *_buffer;
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
public:
|
||||
void Init(Byte *buffer, size_t size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_pos = 0;
|
||||
_size = size;
|
||||
}
|
||||
size_t GetPos() const { return _pos; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CSequentialOutStreamSizeCount:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 *_tags;
|
||||
Byte *_data;
|
||||
size_t _dataSize;
|
||||
unsigned _blockSizeLog;
|
||||
unsigned _numBlocksLog;
|
||||
UInt64 _size;
|
||||
UInt64 _pos;
|
||||
protected:
|
||||
virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;
|
||||
public:
|
||||
CCachedInStream(): _tags(0), _data(0) {}
|
||||
virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!
|
||||
void Free() throw();
|
||||
bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();
|
||||
void Init(UInt64 size) throw();
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
#endif
|
||||
// StreamObjects.h
|
||||
|
||||
#ifndef __STREAM_OBJECTS_H
|
||||
#define __STREAM_OBJECTS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CBufferInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _pos;
|
||||
public:
|
||||
CByteBuffer Buf;
|
||||
void Init() { _pos = 0; }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
struct CReferenceBuf:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteBuffer Buf;
|
||||
MY_UNKNOWN_IMP
|
||||
};
|
||||
|
||||
class CBufInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
const Byte *_data;
|
||||
UInt64 _pos;
|
||||
size_t _size;
|
||||
CMyComPtr<IUnknown> _ref;
|
||||
public:
|
||||
void Init(const Byte *data, size_t size, IUnknown *ref = 0)
|
||||
{
|
||||
_data = data;
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
_ref = ref;
|
||||
}
|
||||
void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream);
|
||||
void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream);
|
||||
inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream)
|
||||
{ Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }
|
||||
|
||||
class CByteDynBuffer
|
||||
{
|
||||
size_t _capacity;
|
||||
Byte *_buf;
|
||||
public:
|
||||
CByteDynBuffer(): _capacity(0), _buf(0) {};
|
||||
// there is no copy constructor. So don't copy this object.
|
||||
~CByteDynBuffer() { Free(); }
|
||||
void Free() throw();
|
||||
size_t GetCapacity() const { return _capacity; }
|
||||
operator Byte*() const { return _buf; }
|
||||
operator const Byte*() const { return _buf; }
|
||||
bool EnsureCapacity(size_t capacity) throw();
|
||||
};
|
||||
|
||||
class CDynBufSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteDynBuffer _buffer;
|
||||
size_t _size;
|
||||
public:
|
||||
CDynBufSeqOutStream(): _size(0) {}
|
||||
void Init() { _size = 0; }
|
||||
size_t GetSize() const { return _size; }
|
||||
const Byte *GetBuffer() const { return _buffer; }
|
||||
void CopyToBuffer(CByteBuffer &dest) const;
|
||||
Byte *GetBufPtrForWriting(size_t addSize);
|
||||
void UpdateSize(size_t addSize) { _size += addSize; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CBufPtrSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Byte *_buffer;
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
public:
|
||||
void Init(Byte *buffer, size_t size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_pos = 0;
|
||||
_size = size;
|
||||
}
|
||||
size_t GetPos() const { return _pos; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CSequentialOutStreamSizeCount:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
class CCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 *_tags;
|
||||
Byte *_data;
|
||||
size_t _dataSize;
|
||||
unsigned _blockSizeLog;
|
||||
unsigned _numBlocksLog;
|
||||
UInt64 _size;
|
||||
UInt64 _pos;
|
||||
protected:
|
||||
virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;
|
||||
public:
|
||||
CCachedInStream(): _tags(0), _data(0) {}
|
||||
virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!
|
||||
void Free() throw();
|
||||
bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();
|
||||
void Init(UInt64 size) throw();
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
// StreamUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
static const UInt32 kBlockSize = ((UInt32)1 << 31);
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()
|
||||
{
|
||||
size_t size = *processedSize;
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
HRESULT res = stream->Read(data, curSize, &processedSizeLoc);
|
||||
*processedSize += processedSizeLoc;
|
||||
data = (void *)((Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
if (processedSizeLoc == 0)
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
return (size == processedSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
return (size == processedSize) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw()
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
HRESULT res = stream->Write(data, curSize, &processedSizeLoc);
|
||||
data = (const void *)((const Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
if (processedSizeLoc == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
// StreamUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
static const UInt32 kBlockSize = ((UInt32)1 << 31);
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()
|
||||
{
|
||||
size_t size = *processedSize;
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
HRESULT res = stream->Read(data, curSize, &processedSizeLoc);
|
||||
*processedSize += processedSizeLoc;
|
||||
data = (void *)((Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
if (processedSizeLoc == 0)
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
return (size == processedSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
return (size == processedSize) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw()
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
HRESULT res = stream->Write(data, curSize, &processedSizeLoc);
|
||||
data = (const void *)((const Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
if (processedSizeLoc == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// StreamUtils.h
|
||||
|
||||
#ifndef __STREAM_UTILS_H
|
||||
#define __STREAM_UTILS_H
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw();
|
||||
|
||||
#endif
|
||||
// StreamUtils.h
|
||||
|
||||
#ifndef __STREAM_UTILS_H
|
||||
#define __STREAM_UTILS_H
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
// UniqBlocks.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "UniqBlocks.h"
|
||||
|
||||
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
|
||||
{
|
||||
unsigned left = 0, right = Sorted.Size();
|
||||
while (left != right)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
unsigned index = Sorted[mid];
|
||||
const CByteBuffer &buf = Bufs[index];
|
||||
size_t sizeMid = buf.Size();
|
||||
if (size < sizeMid)
|
||||
right = mid;
|
||||
else if (size > sizeMid)
|
||||
left = mid + 1;
|
||||
else
|
||||
{
|
||||
if (size == 0)
|
||||
return index;
|
||||
int cmp = memcmp(data, buf, size);
|
||||
if (cmp == 0)
|
||||
return index;
|
||||
if (cmp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
unsigned index = Bufs.Size();
|
||||
Sorted.Insert(left, index);
|
||||
Bufs.AddNew().CopyFrom(data, size);
|
||||
return index;
|
||||
}
|
||||
|
||||
UInt64 CUniqBlocks::GetTotalSizeInBytes() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
FOR_VECTOR (i, Bufs)
|
||||
size += Bufs[i].Size();
|
||||
return size;
|
||||
}
|
||||
|
||||
void CUniqBlocks::GetReverseMap()
|
||||
{
|
||||
unsigned num = Sorted.Size();
|
||||
BufIndexToSortedIndex.ClearAndSetSize(num);
|
||||
unsigned *p = &BufIndexToSortedIndex[0];
|
||||
const unsigned *sorted = &Sorted[0];
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
p[sorted[i]] = i;
|
||||
}
|
||||
// UniqBlocks.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "UniqBlocks.h"
|
||||
|
||||
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
|
||||
{
|
||||
unsigned left = 0, right = Sorted.Size();
|
||||
while (left != right)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
unsigned index = Sorted[mid];
|
||||
const CByteBuffer &buf = Bufs[index];
|
||||
size_t sizeMid = buf.Size();
|
||||
if (size < sizeMid)
|
||||
right = mid;
|
||||
else if (size > sizeMid)
|
||||
left = mid + 1;
|
||||
else
|
||||
{
|
||||
if (size == 0)
|
||||
return index;
|
||||
int cmp = memcmp(data, buf, size);
|
||||
if (cmp == 0)
|
||||
return index;
|
||||
if (cmp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
unsigned index = Bufs.Size();
|
||||
Sorted.Insert(left, index);
|
||||
Bufs.AddNew().CopyFrom(data, size);
|
||||
return index;
|
||||
}
|
||||
|
||||
UInt64 CUniqBlocks::GetTotalSizeInBytes() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
FOR_VECTOR (i, Bufs)
|
||||
size += Bufs[i].Size();
|
||||
return size;
|
||||
}
|
||||
|
||||
void CUniqBlocks::GetReverseMap()
|
||||
{
|
||||
unsigned num = Sorted.Size();
|
||||
BufIndexToSortedIndex.ClearAndSetSize(num);
|
||||
unsigned *p = &BufIndexToSortedIndex[0];
|
||||
const unsigned *sorted = &Sorted[0];
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
p[sorted[i]] = i;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// UniqBlocks.h
|
||||
|
||||
#ifndef __UNIQ_BLOCKS_H
|
||||
#define __UNIQ_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
struct CUniqBlocks
|
||||
{
|
||||
CObjectVector<CByteBuffer> Bufs;
|
||||
CUIntVector Sorted;
|
||||
CUIntVector BufIndexToSortedIndex;
|
||||
|
||||
unsigned AddUniq(const Byte *data, size_t size);
|
||||
UInt64 GetTotalSizeInBytes() const;
|
||||
void GetReverseMap();
|
||||
|
||||
bool IsOnlyEmpty() const
|
||||
{
|
||||
return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
// UniqBlocks.h
|
||||
|
||||
#ifndef __UNIQ_BLOCKS_H
|
||||
#define __UNIQ_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
struct CUniqBlocks
|
||||
{
|
||||
CObjectVector<CByteBuffer> Bufs;
|
||||
CUIntVector Sorted;
|
||||
CUIntVector BufIndexToSortedIndex;
|
||||
|
||||
unsigned AddUniq(const Byte *data, size_t size);
|
||||
UInt64 GetTotalSizeInBytes() const;
|
||||
void GetReverseMap();
|
||||
|
||||
bool IsOnlyEmpty() const
|
||||
{
|
||||
return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
// VirtThread.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "VirtThread.h"
|
||||
|
||||
static THREAD_FUNC_DECL CoderThread(void *p)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
CVirtThread *t = (CVirtThread *)p;
|
||||
t->StartEvent.Lock();
|
||||
if (t->Exit)
|
||||
return 0;
|
||||
t->Execute();
|
||||
t->FinishedEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
WRes CVirtThread::Create()
|
||||
{
|
||||
RINOK(StartEvent.CreateIfNotCreated());
|
||||
RINOK(FinishedEvent.CreateIfNotCreated());
|
||||
StartEvent.Reset();
|
||||
FinishedEvent.Reset();
|
||||
Exit = false;
|
||||
if (Thread.IsCreated())
|
||||
return S_OK;
|
||||
return Thread.Create(CoderThread, this);
|
||||
}
|
||||
|
||||
void CVirtThread::Start()
|
||||
{
|
||||
Exit = false;
|
||||
StartEvent.Set();
|
||||
}
|
||||
|
||||
void CVirtThread::WaitThreadFinish()
|
||||
{
|
||||
Exit = true;
|
||||
if (StartEvent.IsCreated())
|
||||
StartEvent.Set();
|
||||
if (Thread.IsCreated())
|
||||
{
|
||||
Thread.Wait();
|
||||
Thread.Close();
|
||||
}
|
||||
}
|
||||
// VirtThread.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "VirtThread.h"
|
||||
|
||||
static THREAD_FUNC_DECL CoderThread(void *p)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
CVirtThread *t = (CVirtThread *)p;
|
||||
t->StartEvent.Lock();
|
||||
if (t->Exit)
|
||||
return 0;
|
||||
t->Execute();
|
||||
t->FinishedEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
WRes CVirtThread::Create()
|
||||
{
|
||||
RINOK(StartEvent.CreateIfNotCreated());
|
||||
RINOK(FinishedEvent.CreateIfNotCreated());
|
||||
StartEvent.Reset();
|
||||
FinishedEvent.Reset();
|
||||
Exit = false;
|
||||
if (Thread.IsCreated())
|
||||
return S_OK;
|
||||
return Thread.Create(CoderThread, this);
|
||||
}
|
||||
|
||||
void CVirtThread::Start()
|
||||
{
|
||||
Exit = false;
|
||||
StartEvent.Set();
|
||||
}
|
||||
|
||||
void CVirtThread::WaitThreadFinish()
|
||||
{
|
||||
Exit = true;
|
||||
if (StartEvent.IsCreated())
|
||||
StartEvent.Set();
|
||||
if (Thread.IsCreated())
|
||||
{
|
||||
Thread.Wait();
|
||||
Thread.Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
// VirtThread.h
|
||||
|
||||
#ifndef __VIRT_THREAD_H
|
||||
#define __VIRT_THREAD_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
#include "../../Windows/Thread.h"
|
||||
|
||||
struct CVirtThread
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent StartEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent FinishedEvent;
|
||||
NWindows::CThread Thread;
|
||||
bool Exit;
|
||||
|
||||
~CVirtThread() { WaitThreadFinish(); }
|
||||
void WaitThreadFinish(); // call it in destructor of child class !
|
||||
WRes Create();
|
||||
void Start();
|
||||
virtual void Execute() = 0;
|
||||
void WaitExecuteFinish() { FinishedEvent.Lock(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
// VirtThread.h
|
||||
|
||||
#ifndef __VIRT_THREAD_H
|
||||
#define __VIRT_THREAD_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
#include "../../Windows/Thread.h"
|
||||
|
||||
struct CVirtThread
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent StartEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent FinishedEvent;
|
||||
NWindows::CThread Thread;
|
||||
bool Exit;
|
||||
|
||||
~CVirtThread() { WaitThreadFinish(); }
|
||||
void WaitThreadFinish(); // call it in destructor of child class !
|
||||
WRes Create();
|
||||
void Start();
|
||||
virtual void Execute() = 0;
|
||||
void WaitExecuteFinish() { FinishedEvent.Lock(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user