summaryrefslogtreecommitdiffstats
path: root/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/Compress/PpmdEncoder.cpp
blob: ce1b7af022461545028ecbebad984a768f315208 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// 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 < static_cast< Int32 >( kMinOrder ) || prop.ulVal > static_cast< Int32 >( 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; }
}

}}