Normalize all the line endings

This commit is contained in:
Tino Reichardt
2020-05-31 13:08:03 +02:00
parent d8345ee3b3
commit 9c3c277ad7
1156 changed files with 292304 additions and 292304 deletions

View File

@@ -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;
}

View File

@@ -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

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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); }

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}
*/

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -1,3 +1,3 @@
// LockedStream.cpp
#include "StdAfx.h"
// LockedStream.cpp
#include "StdAfx.h"

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -1,3 +1,3 @@
// MethodId.cpp
#include "StdAfx.h"
// MethodId.cpp
#include "StdAfx.h"

View File

@@ -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

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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