tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PpmdDecoder.cpp (3808B)


      1 // PpmdDecoder.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 "PpmdDecoder.h"
     12 
     13 namespace NCompress {
     14 namespace NPpmd {
     15 
     16 static const UInt32 kBufSize = (1 << 20);
     17 
     18 enum
     19 {
     20  kStatus_NeedInit,
     21  kStatus_Normal,
     22  kStatus_Finished,
     23  kStatus_Error
     24 };
     25 
     26 CDecoder::~CDecoder()
     27 {
     28  ::MidFree(_outBuf);
     29  Ppmd7_Free(&_ppmd, &g_BigAlloc);
     30 }
     31 
     32 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)
     33 {
     34  if (size < 5)
     35    return E_INVALIDARG;
     36  _order = props[0];
     37  UInt32 memSize = GetUi32(props + 1);
     38  if (_order < PPMD7_MIN_ORDER ||
     39      _order > PPMD7_MAX_ORDER ||
     40      memSize < PPMD7_MIN_MEM_SIZE ||
     41      memSize > PPMD7_MAX_MEM_SIZE)
     42    return E_NOTIMPL;
     43  if (!_inStream.Alloc(1 << 20))
     44    return E_OUTOFMEMORY;
     45  if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))
     46    return E_OUTOFMEMORY;
     47  return S_OK;
     48 }
     49 
     50 HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
     51 {
     52  switch (_status)
     53  {
     54    case kStatus_Finished: return S_OK;
     55    case kStatus_Error: return S_FALSE;
     56    case kStatus_NeedInit:
     57      _inStream.Init();
     58      if (!Ppmd7z_RangeDec_Init(&_rangeDec))
     59      {
     60        _status = kStatus_Error;
     61        return S_FALSE;
     62      }
     63      _status = kStatus_Normal;
     64      Ppmd7_Init(&_ppmd, _order);
     65      break;
     66  }
     67  if (_outSizeDefined)
     68  {
     69    const UInt64 rem = _outSize - _processedSize;
     70    if (size > rem)
     71      size = (UInt32)rem;
     72  }
     73 
     74  UInt32 i;
     75  int sym = 0;
     76  for (i = 0; i != size; i++)
     77  {
     78    sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt);
     79    if (_inStream.Extra || sym < 0)
     80      break;
     81    memStream[i] = (Byte)sym;
     82  }
     83 
     84  _processedSize += i;
     85  if (_inStream.Extra)
     86  {
     87    _status = kStatus_Error;
     88    return _inStream.Res;
     89  }
     90  if (sym < 0)
     91    _status = (sym < -1) ? kStatus_Error : kStatus_Finished;
     92  return S_OK;
     93 }
     94 
     95 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
     96    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
     97 {
     98  if (!_outBuf)
     99  {
    100    _outBuf = (Byte *)::MidAlloc(kBufSize);
    101    if (!_outBuf)
    102      return E_OUTOFMEMORY;
    103  }
    104  
    105  _inStream.Stream = inStream;
    106  SetOutStreamSize(outSize);
    107 
    108  do
    109  {
    110    const UInt64 startPos = _processedSize;
    111    HRESULT res = CodeSpec(_outBuf, kBufSize);
    112    size_t processed = (size_t)(_processedSize - startPos);
    113    RINOK(WriteStream(outStream, _outBuf, processed));
    114    RINOK(res);
    115    if (_status == kStatus_Finished)
    116      break;
    117    if (progress)
    118    {
    119      UInt64 inSize = _inStream.GetProcessed();
    120      RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
    121    }
    122  }
    123  while (!_outSizeDefined || _processedSize < _outSize);
    124  return S_OK;
    125 }
    126 
    127 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
    128 {
    129  _outSizeDefined = (outSize != NULL);
    130  if (_outSizeDefined)
    131    _outSize = *outSize;
    132  _processedSize = 0;
    133  _status = kStatus_NeedInit;
    134  return S_OK;
    135 }
    136 
    137 
    138 STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
    139 {
    140  *value = _inStream.GetProcessed();
    141  return S_OK;
    142 }
    143 
    144 #ifndef NO_READ_FROM_CODER
    145 
    146 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
    147 {
    148  InSeqStream = inStream;
    149  _inStream.Stream = inStream;
    150  return S_OK;
    151 }
    152 
    153 STDMETHODIMP CDecoder::ReleaseInStream()
    154 {
    155  InSeqStream.Release();
    156  return S_OK;
    157 }
    158 
    159 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
    160 {
    161  const UInt64 startPos = _processedSize;
    162  HRESULT res = CodeSpec((Byte *)data, size);
    163  if (processedSize)
    164    *processedSize = (UInt32)(_processedSize - startPos);
    165  return res;
    166 }
    167 
    168 #endif
    169 
    170 }}