diff src/win32/7zip/7z/CPP/7zip/Compress/LzhDecoder.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/LzhDecoder.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,220 @@
     1.4 +// LzhDecoder.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +#include "LzhDecoder.h"
     1.9 +
    1.10 +#include "Windows/Defs.h"
    1.11 +
    1.12 +namespace NCompress{
    1.13 +namespace NLzh {
    1.14 +namespace NDecoder {
    1.15 +
    1.16 +static const UInt32 kHistorySize = (1 << 16);
    1.17 +
    1.18 +static const int kBlockSizeBits = 16;
    1.19 +static const int kNumCBits = 9;
    1.20 +static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/
    1.21 +
    1.22 +UInt32 CCoder::ReadBits(int numBits) {  return m_InBitStream.ReadBits(numBits); }
    1.23 +
    1.24 +HRESULT CCoder::ReadLevelTable()
    1.25 +{
    1.26 +  int n = ReadBits(kNumLevelBits);
    1.27 +  if (n == 0)
    1.28 +  {
    1.29 +    m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);
    1.30 +    if (m_LevelHuffman.Symbol >= kNumLevelSymbols)
    1.31 +      return S_FALSE;
    1.32 +  }
    1.33 +  else
    1.34 +  {
    1.35 +    if (n > kNumLevelSymbols)
    1.36 +      return S_FALSE;
    1.37 +    m_LevelHuffman.Symbol = -1;
    1.38 +    Byte lens[kNumLevelSymbols];
    1.39 +    int i = 0;
    1.40 +    while (i < n)
    1.41 +    {
    1.42 +      int c = m_InBitStream.ReadBits(3);
    1.43 +      if (c == 7)
    1.44 +        while (ReadBits(1))
    1.45 +          if (c++ > kMaxHuffmanLen)
    1.46 +            return S_FALSE;
    1.47 +      lens[i++] = (Byte)c;
    1.48 +      if (i == kNumSpecLevelSymbols)
    1.49 +      {
    1.50 +        c = ReadBits(2);
    1.51 +        while (--c >= 0)
    1.52 +          lens[i++] = 0;
    1.53 +      }
    1.54 +    }
    1.55 +    while (i < kNumLevelSymbols)
    1.56 +      lens[i++] = 0;
    1.57 +    m_LevelHuffman.SetCodeLengths(lens);
    1.58 +  }
    1.59 +  return S_OK;
    1.60 +}
    1.61 +
    1.62 +HRESULT CCoder::ReadPTable(int numBits)
    1.63 +{
    1.64 +  int n = ReadBits(numBits);
    1.65 +  if (n == 0)
    1.66 +  {
    1.67 +    m_PHuffmanDecoder.Symbol = ReadBits(numBits);
    1.68 +    if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)
    1.69 +      return S_FALSE;
    1.70 +  }
    1.71 +  else
    1.72 +  {
    1.73 +    if (n > kNumDistanceSymbols)
    1.74 +      return S_FALSE;
    1.75 +    m_PHuffmanDecoder.Symbol = -1;
    1.76 +    Byte lens[kNumDistanceSymbols];
    1.77 +    int i = 0;
    1.78 +    while (i < n)
    1.79 +    {
    1.80 +      int c = m_InBitStream.ReadBits(3);
    1.81 +      if (c == 7)
    1.82 +        while (ReadBits(1))
    1.83 +        {
    1.84 +          if (c > kMaxHuffmanLen)
    1.85 +            return S_FALSE;
    1.86 +          c++;
    1.87 +        }
    1.88 +      lens[i++] = (Byte)c;
    1.89 +    }
    1.90 +    while (i < kNumDistanceSymbols)
    1.91 +      lens[i++] = 0;
    1.92 +    m_PHuffmanDecoder.SetCodeLengths(lens);
    1.93 +  }
    1.94 +  return S_OK;
    1.95 +}
    1.96 +
    1.97 +HRESULT CCoder::ReadCTable()
    1.98 +{
    1.99 +  int n = ReadBits(kNumCBits);
   1.100 +  if (n == 0)
   1.101 +  {
   1.102 +    m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);
   1.103 +    if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)
   1.104 +      return S_FALSE;
   1.105 +  }
   1.106 +  else
   1.107 +  {
   1.108 +    if (n > kNumCSymbols)
   1.109 +      return S_FALSE;
   1.110 +    m_CHuffmanDecoder.Symbol = -1;
   1.111 +    Byte lens[kNumCSymbols];
   1.112 +    int i = 0;
   1.113 +    while (i < n)
   1.114 +    {
   1.115 +      int c = m_LevelHuffman.Decode(&m_InBitStream);
   1.116 +      if (c < kNumSpecLevelSymbols)
   1.117 +      {
   1.118 +        if (c == 0)
   1.119 +          c = 1;
   1.120 +        else if (c == 1)
   1.121 +          c = ReadBits(4) + 3;
   1.122 +        else
   1.123 +          c = ReadBits(kNumCBits) + 20;
   1.124 +        while (--c >= 0)
   1.125 +        {
   1.126 +          if (i > kNumCSymbols)
   1.127 +            return S_FALSE;
   1.128 +          lens[i++] = 0;
   1.129 +        }
   1.130 +      }
   1.131 +      else
   1.132 +        lens[i++] = (Byte)(c - 2);
   1.133 +    }
   1.134 +    while (i < kNumCSymbols)
   1.135 +      lens[i++] = 0;
   1.136 +    m_CHuffmanDecoder.SetCodeLengths(lens);
   1.137 +  }
   1.138 +  return S_OK;
   1.139 +}
   1.140 +
   1.141 +STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
   1.142 +    ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
   1.143 +    ICompressProgressInfo *progress)
   1.144 +{
   1.145 +  if (outSize == NULL)
   1.146 +    return E_INVALIDARG;
   1.147 +
   1.148 +  if (!m_OutWindowStream.Create(kHistorySize))
   1.149 +    return E_OUTOFMEMORY;
   1.150 +  if (!m_InBitStream.Create(1 << 20))
   1.151 +    return E_OUTOFMEMORY;
   1.152 +
   1.153 +  UInt64 pos = 0;
   1.154 +  m_OutWindowStream.SetStream(outStream);
   1.155 +  m_OutWindowStream.Init(false);
   1.156 +  m_InBitStream.SetStream(inStream);
   1.157 +  m_InBitStream.Init();
   1.158 +  
   1.159 +  CCoderReleaser coderReleaser(this);
   1.160 +
   1.161 +  int pbit;
   1.162 +  if (m_NumDictBits <= 13)
   1.163 +    pbit = 4;
   1.164 +  else
   1.165 +    pbit = 5;
   1.166 +
   1.167 +  UInt32 blockSize = 0;
   1.168 +
   1.169 +  while(pos < *outSize)
   1.170 +  {
   1.171 +    // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;
   1.172 +    
   1.173 +    if (blockSize == 0)
   1.174 +    {
   1.175 +      if (progress != NULL)
   1.176 +      {
   1.177 +        UInt64 packSize = m_InBitStream.GetProcessedSize();
   1.178 +        RINOK(progress->SetRatioInfo(&packSize, &pos));
   1.179 +      }
   1.180 +      blockSize = ReadBits(kBlockSizeBits);
   1.181 +      ReadLevelTable();
   1.182 +      ReadCTable();
   1.183 +      RINOK(ReadPTable(pbit));
   1.184 +    }
   1.185 +    blockSize--;
   1.186 +    UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);
   1.187 +    if (c < 256)
   1.188 +    {
   1.189 +      m_OutWindowStream.PutByte((Byte)c);
   1.190 +      pos++;
   1.191 +    }
   1.192 +    else if (c >= kNumCSymbols)
   1.193 +      return S_FALSE;
   1.194 +    else
   1.195 +    {
   1.196 +      // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;
   1.197 +      UInt32 len  = c - 256 + kMinMatch;
   1.198 +      UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);
   1.199 +      if (distance != 0)
   1.200 +        distance = (1 << (distance - 1)) + ReadBits(distance - 1);
   1.201 +      if (distance >= pos)
   1.202 +        return S_FALSE;
   1.203 +      if (pos + len > *outSize)
   1.204 +        len = (UInt32)(*outSize - pos);
   1.205 +      pos += len;
   1.206 +      m_OutWindowStream.CopyBlock(distance, len);
   1.207 +    }
   1.208 +  }
   1.209 +  coderReleaser.NeedFlush = false;
   1.210 +  return m_OutWindowStream.Flush();
   1.211 +}
   1.212 +
   1.213 +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,
   1.214 +    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
   1.215 +    ICompressProgressInfo *progress)
   1.216 +{
   1.217 +  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
   1.218 +  catch(const CInBufferException &e) { return e.ErrorCode; }
   1.219 +  catch(const CLzOutWindowException &e) { return e.ErrorCode; }
   1.220 +  catch(...) { return S_FALSE; }
   1.221 +}
   1.222 +
   1.223 +}}}