diff src/win32/7zip/7z/CPP/7zip/Compress/ShrinkDecoder.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/ShrinkDecoder.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,148 @@
     1.4 +// ShrinkDecoder.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +extern "C"
     1.9 +{
    1.10 +#include "../../../C/Alloc.h"
    1.11 +}
    1.12 +
    1.13 +#include "../Common/InBuffer.h"
    1.14 +#include "../Common/OutBuffer.h"
    1.15 +
    1.16 +#include "BitlDecoder.h"
    1.17 +#include "ShrinkDecoder.h"
    1.18 +
    1.19 +namespace NCompress {
    1.20 +namespace NShrink {
    1.21 +
    1.22 +static const UInt32 kBufferSize = (1 << 20);
    1.23 +static const int kNumMinBits = 9;
    1.24 +
    1.25 +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
    1.26 +    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
    1.27 +{
    1.28 +  NBitl::CBaseDecoder<CInBuffer> inBuffer;
    1.29 +  COutBuffer outBuffer;
    1.30 +
    1.31 +  if (!inBuffer.Create(kBufferSize))
    1.32 +    return E_OUTOFMEMORY;
    1.33 +  inBuffer.SetStream(inStream);
    1.34 +  inBuffer.Init();
    1.35 +
    1.36 +  if (!outBuffer.Create(kBufferSize))
    1.37 +    return E_OUTOFMEMORY;
    1.38 +  outBuffer.SetStream(outStream);
    1.39 +  outBuffer.Init();
    1.40 +
    1.41 +  UInt64 prevPos = 0;
    1.42 +  int numBits = kNumMinBits;
    1.43 +  UInt32 head = 257;
    1.44 +  bool needPrev = false;
    1.45 +  UInt32 lastSymbol = 0;
    1.46 +
    1.47 +  int i;
    1.48 +  for (i = 0; i < kNumItems; i++)
    1.49 +    _parents[i] = 0;
    1.50 +  for (i = 0; i < kNumItems; i++)
    1.51 +    _suffixes[i] = 0;
    1.52 +  for (i = 0; i < 257; i++)
    1.53 +    _isFree[i] = false;
    1.54 +  for (; i < kNumItems; i++)
    1.55 +    _isFree[i] = true;
    1.56 +
    1.57 +  for (;;)
    1.58 +  {
    1.59 +    UInt32 symbol = inBuffer.ReadBits(numBits);
    1.60 +    if (inBuffer.ExtraBitsWereRead())
    1.61 +      break;
    1.62 +    if (_isFree[symbol])
    1.63 +      return S_FALSE;
    1.64 +    if (symbol == 256)
    1.65 +    {
    1.66 +      UInt32 symbol = inBuffer.ReadBits(numBits);
    1.67 +      if (symbol == 1)
    1.68 +      {
    1.69 +        if (numBits < kNumMaxBits)
    1.70 +          numBits++;
    1.71 +      }
    1.72 +      else if (symbol == 2)
    1.73 +      {
    1.74 +        if (needPrev)
    1.75 +          _isFree[head - 1] = true;
    1.76 +        for (i = 257; i < kNumItems; i++)
    1.77 +          _isParent[i] = false;
    1.78 +        for (i = 257; i < kNumItems; i++)
    1.79 +          if (!_isFree[i])
    1.80 +            _isParent[_parents[i]] = true;
    1.81 +        for (i = 257; i < kNumItems; i++)
    1.82 +          if (!_isParent[i])
    1.83 +            _isFree[i] = true;
    1.84 +        head = 257;
    1.85 +        while (head < kNumItems && !_isFree[head])
    1.86 +          head++;
    1.87 +        if (head < kNumItems)
    1.88 +        {
    1.89 +          needPrev = true;
    1.90 +          _isFree[head] = false;
    1.91 +          _parents[head] = (UInt16)lastSymbol;
    1.92 +          head++;
    1.93 +        }
    1.94 +      }
    1.95 +      else
    1.96 +        return S_FALSE;
    1.97 +      continue;
    1.98 +    }
    1.99 +    UInt32 cur = symbol;
   1.100 +    i = 0;
   1.101 +    int corectionIndex = -1;
   1.102 +    while (cur >= 256)
   1.103 +    {
   1.104 +      if (cur == head - 1)
   1.105 +        corectionIndex = i;
   1.106 +      _stack[i++] = _suffixes[cur];
   1.107 +      cur = _parents[cur];
   1.108 +    }
   1.109 +    _stack[i++] = (Byte)cur;
   1.110 +    if (needPrev)
   1.111 +    {
   1.112 +      _suffixes[head - 1] = (Byte)cur;
   1.113 +      if (corectionIndex >= 0)
   1.114 +        _stack[corectionIndex] = (Byte)cur;
   1.115 +    }
   1.116 +    while (i > 0)
   1.117 +      outBuffer.WriteByte((_stack[--i]));
   1.118 +    while (head < kNumItems && !_isFree[head])
   1.119 +      head++;
   1.120 +    if (head < kNumItems)
   1.121 +    {
   1.122 +      needPrev = true;
   1.123 +      _isFree[head] = false;
   1.124 +      _parents[head] = (UInt16)symbol;
   1.125 +      head++;
   1.126 +    }
   1.127 +    else
   1.128 +      needPrev = false;
   1.129 +    lastSymbol = symbol;
   1.130 +
   1.131 +    UInt64 nowPos = outBuffer.GetProcessedSize();
   1.132 +    if (progress != NULL && nowPos - prevPos > (1 << 18))
   1.133 +    {
   1.134 +      prevPos = nowPos;
   1.135 +      UInt64 packSize = inBuffer.GetProcessedSize();
   1.136 +      RINOK(progress->SetRatioInfo(&packSize, &nowPos));
   1.137 +    }
   1.138 +  }
   1.139 +  return outBuffer.Flush();
   1.140 +}
   1.141 +
   1.142 +STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
   1.143 +    const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress)
   1.144 +{
   1.145 +  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
   1.146 +  catch(const CInBufferException &e) { return e.ErrorCode; }
   1.147 +  catch(const COutBufferException &e) { return e.ErrorCode; }
   1.148 +  catch(...) { return S_FALSE; }
   1.149 +}
   1.150 +
   1.151 +}}