mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-15 02:11:43 -06:00
3.13
This commit is contained in:
182
7zip/Compress/PPMD/PPMDEncoder.cpp
Executable file
182
7zip/Compress/PPMD/PPMDEncoder.cpp
Executable file
@@ -0,0 +1,182 @@
|
||||
// Compress/Associative/Encoder.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
// #include <fstream.h>
|
||||
// #include <iomanip.h>
|
||||
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "PPMDEncoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NPPMD {
|
||||
|
||||
/*
|
||||
UINT32 g_NumInner = 0;
|
||||
UINT32 g_InnerCycles = 0;
|
||||
|
||||
UINT32 g_Encode2 = 0;
|
||||
UINT32 g_Encode2Cycles = 0;
|
||||
UINT32 g_Encode2Cycles2 = 0;
|
||||
|
||||
class CCounter
|
||||
{
|
||||
public:
|
||||
CCounter() {}
|
||||
~CCounter()
|
||||
{
|
||||
ofstream ofs("Res.dat");
|
||||
ofs << "innerEncode1 = " << setw(10) << g_NumInner << endl;
|
||||
ofs << "g_InnerCycles = " << setw(10) << g_InnerCycles << endl;
|
||||
ofs << "g_Encode2 = " << setw(10) << g_Encode2 << endl;
|
||||
ofs << "g_Encode2Cycles = " << setw(10) << g_Encode2Cycles << endl;
|
||||
ofs << "g_Encode2Cycles2= " << setw(10) << g_Encode2Cycles2 << endl;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
CCounter g_Counter;
|
||||
|
||||
|
||||
/*
|
||||
// ISetRangeEncoder
|
||||
STDMETHODIMP CEncoder::SetRangeEncoder(CRangeEncoder *aRangeEncoder)
|
||||
{
|
||||
_rangeEncoder = aRangeEncoder;
|
||||
RINOK(_rangeEncoder.QueryInterface(&m_InitOutCoder));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UINT32 numProperties)
|
||||
{
|
||||
for (UINT32 i = 0; i < numProperties; i++)
|
||||
{
|
||||
const PROPVARIANT &aProperty = properties[i];
|
||||
switch(propIDs[i])
|
||||
{
|
||||
case NCoderPropID::kUsedMemorySize:
|
||||
if (aProperty.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (aProperty.ulVal < kMinMemSize)
|
||||
return E_INVALIDARG;
|
||||
_usedMemorySize = aProperty.ulVal;
|
||||
break;
|
||||
case NCoderPropID::kOrder:
|
||||
if (aProperty.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (aProperty.ulVal < kMinOrder || aProperty.ulVal > kMaxOrderCompress)
|
||||
return E_INVALIDARG;
|
||||
_order = BYTE(aProperty.ulVal);
|
||||
break;
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
RINOK(outStream->Write(&_order, sizeof(_order), NULL));
|
||||
return outStream->Write(&_usedMemorySize, sizeof(_usedMemorySize), NULL);
|
||||
}
|
||||
|
||||
const UINT32 kUsedMemorySizeDefault = (1 << 24);
|
||||
const int kOrderDefault = 6;
|
||||
|
||||
CEncoder::CEncoder():
|
||||
_usedMemorySize(kUsedMemorySizeDefault),
|
||||
_order(kOrderDefault)
|
||||
{
|
||||
// SubAllocator.StartSubAllocator(kSubAllocator);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::Flush()
|
||||
{
|
||||
_rangeEncoder.FlushData();
|
||||
return _rangeEncoder.FlushStream();
|
||||
}
|
||||
|
||||
class CEncoderFlusher
|
||||
{
|
||||
CEncoder *_encoder;
|
||||
public:
|
||||
CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {}
|
||||
~CEncoderFlusher()
|
||||
{
|
||||
_encoder->Flush();
|
||||
// _encoder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
_inStream.Init(inStream);
|
||||
_rangeEncoder.Init(outStream);
|
||||
|
||||
CEncoderFlusher aFlusher(this);
|
||||
|
||||
UINT64 pos = 0;
|
||||
UINT64 prevProgressPos = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if ( !_info.SubAllocator.StartSubAllocator(_usedMemorySize) )
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
|
||||
_info.MaxOrder = 0;
|
||||
_info.StartModelRare(_order);
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
BYTE symbol;
|
||||
if (!_inStream.ReadByte(symbol))
|
||||
{
|
||||
// here we can write End Mark for stream version.
|
||||
// In current version this feature is not used.
|
||||
// _info.EncodeSymbol(-1, &_rangeEncoder);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
_info.EncodeSymbol(symbol, &_rangeEncoder);
|
||||
pos++;
|
||||
if (pos - prevProgressPos >= (1 << 18) && progress != NULL)
|
||||
{
|
||||
UINT64 outSize = _rangeEncoder.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&pos, &outSize));
|
||||
prevProgressPos = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
|
||||
catch(const COutBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(...) { return E_FAIL; }
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user