Files
easy7zip/CPP/7zip/Compress/PpmdEncoder.cpp
Igor Pavlov 829409452d 9.04 beta
2016-05-28 00:15:59 +01:00

149 lines
3.7 KiB
C++
Executable File

// PpmdEncoder.cpp
// 2009-05-30 : Igor Pavlov : Public domain
#include "StdAfx.h"
// #include <fstream.h>
// #include <iomanip.h>
#include "../Common/StreamUtils.h"
#include "PpmdEncoder.h"
namespace NCompress {
namespace NPpmd {
const UInt32 kMinMemSize = (1 << 11);
const UInt32 kMinOrder = 2;
/*
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;
*/
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
switch(propIDs[i])
{
case NCoderPropID::kUsedMemorySize:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize)
return E_INVALIDARG;
_usedMemorySize = (UInt32)prop.ulVal;
break;
case NCoderPropID::kOrder:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress)
return E_INVALIDARG;
_order = (Byte)prop.ulVal;
break;
default:
return E_INVALIDARG;
}
}
return S_OK;
}
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
const UInt32 kPropSize = 5;
Byte props[kPropSize];
props[0] = _order;
for (int i = 0; i < 4; i++)
props[1 + i] = Byte(_usedMemorySize >> (8 * i));
return WriteStream(outStream, props, kPropSize);
}
const UInt32 kUsedMemorySizeDefault = (1 << 24);
const int kOrderDefault = 6;
CEncoder::CEncoder():
_usedMemorySize(kUsedMemorySizeDefault),
_order(kOrderDefault)
{
}
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
{
if (!_inStream.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_rangeEncoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY;
_inStream.SetStream(inStream);
_inStream.Init();
_rangeEncoder.SetStream(outStream);
_rangeEncoder.Init();
CEncoderFlusher flusher(this);
_info.MaxOrder = 0;
_info.StartModelRare(_order);
for (;;)
{
UInt32 size = (1 << 18);
do
{
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);
}
while (--size != 0);
if (progress != NULL)
{
UInt64 inSize = _inStream.GetProcessedSize();
UInt64 outSize = _rangeEncoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &outSize));
}
}
}
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; }
}
}}