Files
easy7zip/7zip/Compress/PPMD/PPMDEncoder.cpp
Igor Pavlov 8c1b5c7b7e 3.13
2016-05-28 00:15:41 +01:00

183 lines
4.0 KiB
C++
Executable File

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