• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // PpmdEncoder.cpp
2 // 2009-03-11 : Igor Pavlov : Public domain
3 
4 #include "StdAfx.h"
5 
6 #include "../../../C/Alloc.h"
7 #include "../../../C/CpuArch.h"
8 
9 #include "../Common/StreamUtils.h"
10 
11 #include "PpmdEncoder.h"
12 
13 namespace NCompress {
14 namespace NPpmd {
15 
16 static const UInt32 kBufSize = (1 << 20);
17 
SzBigAlloc(void *,size_t size)18 static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
SzBigFree(void *,void * address)19 static void SzBigFree(void *, void *address) { BigFree(address); }
20 static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
21 
CEncoder()22 CEncoder::CEncoder():
23   _inBuf(NULL),
24   _usedMemSize(1 << 24),
25   _order(6)
26 {
27   _rangeEnc.Stream = &_outStream.p;
28   Ppmd7_Construct(&_ppmd);
29 }
30 
~CEncoder()31 CEncoder::~CEncoder()
32 {
33   ::MidFree(_inBuf);
34   Ppmd7_Free(&_ppmd, &g_BigAlloc);
35 }
36 
SetCoderProperties(const PROPID * propIDs,const PROPVARIANT * props,UInt32 numProps)37 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
38 {
39   for (UInt32 i = 0; i < numProps; i++)
40   {
41     const PROPVARIANT &prop = props[i];
42     if (prop.vt != VT_UI4)
43       return E_INVALIDARG;
44     UInt32 v = (UInt32)prop.ulVal;
45     switch(propIDs[i])
46     {
47       case NCoderPropID::kUsedMemorySize:
48         if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)
49           return E_INVALIDARG;
50         _usedMemSize = v;
51         break;
52       case NCoderPropID::kOrder:
53         if (v < 2 || v > 32)
54           return E_INVALIDARG;
55         _order = (Byte)v;
56         break;
57       default:
58         return E_INVALIDARG;
59     }
60   }
61   return S_OK;
62 }
63 
WriteCoderProperties(ISequentialOutStream * outStream)64 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
65 {
66   const UInt32 kPropSize = 5;
67   Byte props[kPropSize];
68   props[0] = _order;
69   SetUi32(props + 1, _usedMemSize);
70   return WriteStream(outStream, props, kPropSize);
71 }
72 
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 *,ICompressProgressInfo * progress)73 HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
74     const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
75 {
76   if (!_inBuf)
77   {
78     _inBuf = (Byte *)::MidAlloc(kBufSize);
79     if (!_inBuf)
80       return E_OUTOFMEMORY;
81   }
82   if (!_outStream.Alloc(1 << 20))
83     return E_OUTOFMEMORY;
84   if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))
85     return E_OUTOFMEMORY;
86 
87   _outStream.Stream = outStream;
88   _outStream.Init();
89 
90   Ppmd7z_RangeEnc_Init(&_rangeEnc);
91   Ppmd7_Init(&_ppmd, _order);
92 
93   UInt64 processed = 0;
94   for (;;)
95   {
96     UInt32 size;
97     RINOK(inStream->Read(_inBuf, kBufSize, &size));
98     if (size == 0)
99     {
100       // We don't write EndMark in PPMD-7z.
101       // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1);
102       Ppmd7z_RangeEnc_FlushData(&_rangeEnc);
103       return _outStream.Flush();
104     }
105     for (UInt32 i = 0; i < size; i++)
106     {
107       Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]);
108       RINOK(_outStream.Res);
109     }
110     processed += size;
111     if (progress)
112     {
113       UInt64 outSize = _outStream.GetProcessed();
114       RINOK(progress->SetRatioInfo(&processed, &outSize));
115     }
116   }
117 }
118 
119 }}
120