diff src/win32/7zip/7z/CPP/7zip/Compress/Rar2Decoder.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/Rar2Decoder.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,389 @@
     1.4 +// Rar2Decoder.cpp
     1.5 +// According to unRAR license, this code may not be used to develop
     1.6 +// a program that creates RAR archives
     1.7 + 
     1.8 +#include "StdAfx.h"
     1.9 +
    1.10 +#include "Rar2Decoder.h"
    1.11 +
    1.12 +namespace NCompress {
    1.13 +namespace NRar2 {
    1.14 +
    1.15 +namespace NMultimedia {
    1.16 +
    1.17 +Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
    1.18 +{
    1.19 +  D4 = D3;
    1.20 +  D3 = D2;
    1.21 +  D2 = LastDelta - D1;
    1.22 +  D1 = LastDelta;
    1.23 +  int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);
    1.24 +
    1.25 +  Byte realValue = (Byte)(predictedValue - deltaByte);
    1.26 +  int i = ((int)(signed char)deltaByte) << 3;
    1.27 +
    1.28 +  Dif[0] += abs(i);
    1.29 +  Dif[1] += abs(i - D1);
    1.30 +  Dif[2] += abs(i + D1);
    1.31 +  Dif[3] += abs(i - D2);
    1.32 +  Dif[4] += abs(i + D2);
    1.33 +  Dif[5] += abs(i - D3);
    1.34 +  Dif[6] += abs(i + D3);
    1.35 +  Dif[7] += abs(i - D4);
    1.36 +  Dif[8] += abs(i + D4);
    1.37 +  Dif[9] += abs(i - channelDelta);
    1.38 +  Dif[10] += abs(i + channelDelta);
    1.39 +
    1.40 +  channelDelta = LastDelta = (signed char)(realValue - LastChar);
    1.41 +  LastChar = realValue;
    1.42 +
    1.43 +  if (((++ByteCount) & 0x1F) == 0)
    1.44 +  {
    1.45 +    UInt32 minDif = Dif[0];
    1.46 +    UInt32 numMinDif = 0;
    1.47 +    Dif[0] = 0;
    1.48 +    for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++)
    1.49 +    {
    1.50 +      if (Dif[i] < minDif)
    1.51 +      {
    1.52 +        minDif = Dif[i];
    1.53 +        numMinDif = i;
    1.54 +      }
    1.55 +      Dif[i] = 0;
    1.56 +    }
    1.57 +    switch(numMinDif)
    1.58 +    {
    1.59 +      case 1: if (K1 >= -16) K1--; break;
    1.60 +      case 2: if (K1 <   16) K1++; break;
    1.61 +      case 3: if (K2 >= -16) K2--; break;
    1.62 +      case 4: if (K2 <   16) K2++; break;
    1.63 +      case 5: if (K3 >= -16) K3--; break;
    1.64 +      case 6: if (K3 <   16) K3++; break;
    1.65 +      case 7: if (K4 >= -16) K4--; break;
    1.66 +      case 8: if (K4 <   16) K4++; break;
    1.67 +      case 9: if (K5 >= -16) K5--; break;
    1.68 +      case 10:if (K5 <   16) K5++; break;
    1.69 +    }
    1.70 +  }
    1.71 +  return realValue;
    1.72 +}
    1.73 +}
    1.74 +
    1.75 +static const char *kNumberErrorMessage = "Number error";
    1.76 +
    1.77 +static const UInt32 kHistorySize = 1 << 20;
    1.78 +
    1.79 +static const int kNumStats = 11;
    1.80 +
    1.81 +static const UInt32 kWindowReservSize = (1 << 22) + 256;
    1.82 +
    1.83 +CDecoder::CDecoder():
    1.84 +  m_IsSolid(false)
    1.85 +{
    1.86 +}
    1.87 +
    1.88 +void CDecoder::InitStructures()
    1.89 +{
    1.90 +  m_MmFilter.Init();
    1.91 +  for(int i = 0; i < kNumRepDists; i++)
    1.92 +    m_RepDists[i] = 0;
    1.93 +  m_RepDistPtr = 0;
    1.94 +  m_LastLength = 0;
    1.95 +  memset(m_LastLevels, 0, kMaxTableSize);
    1.96 +}
    1.97 +
    1.98 +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
    1.99 +
   1.100 +#define RIF(x) { if (!(x)) return false; }
   1.101 +
   1.102 +bool CDecoder::ReadTables(void)
   1.103 +{
   1.104 +  Byte levelLevels[kLevelTableSize];
   1.105 +  Byte newLevels[kMaxTableSize];
   1.106 +  m_AudioMode = (ReadBits(1) == 1);
   1.107 +
   1.108 +  if (ReadBits(1) == 0)
   1.109 +    memset(m_LastLevels, 0, kMaxTableSize);
   1.110 +  int numLevels;
   1.111 +  if (m_AudioMode)
   1.112 +  {
   1.113 +    m_NumChannels = ReadBits(2) + 1;
   1.114 +    if (m_MmFilter.CurrentChannel >= m_NumChannels)
   1.115 +      m_MmFilter.CurrentChannel = 0;
   1.116 +    numLevels = m_NumChannels * kMMTableSize;
   1.117 +  }
   1.118 +  else
   1.119 +    numLevels = kHeapTablesSizesSum;
   1.120 + 
   1.121 +  int i;
   1.122 +  for (i = 0; i < kLevelTableSize; i++)
   1.123 +    levelLevels[i] = (Byte)ReadBits(4);
   1.124 +  RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
   1.125 +  i = 0;
   1.126 +  while (i < numLevels)
   1.127 +  {
   1.128 +    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
   1.129 +    if (number < kTableDirectLevels)
   1.130 +    {
   1.131 +      newLevels[i] = (Byte)((number + m_LastLevels[i]) & kLevelMask);
   1.132 +      i++;
   1.133 +    }
   1.134 +    else
   1.135 +    {
   1.136 +      if (number == kTableLevelRepNumber)
   1.137 +      {
   1.138 +        int t = ReadBits(2) + 3;
   1.139 +        for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)
   1.140 +          newLevels[i] = newLevels[i - 1];
   1.141 +      }
   1.142 +      else
   1.143 +      {
   1.144 +        int num;
   1.145 +        if (number == kTableLevel0Number)
   1.146 +          num = ReadBits(3) + 3;
   1.147 +        else if (number == kTableLevel0Number2)
   1.148 +          num = ReadBits(7) + 11;
   1.149 +        else
   1.150 +          return false;
   1.151 +        for (;num > 0 && i < numLevels; num--)
   1.152 +          newLevels[i++] = 0;
   1.153 +      }
   1.154 +    }
   1.155 +  }
   1.156 +  if (m_AudioMode)
   1.157 +    for (i = 0; i < m_NumChannels; i++)
   1.158 +    {
   1.159 +      RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize]));
   1.160 +    }
   1.161 +  else
   1.162 +  {
   1.163 +    RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));
   1.164 +    RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));
   1.165 +    RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));
   1.166 +  }
   1.167 +  memcpy(m_LastLevels, newLevels, kMaxTableSize);
   1.168 +  return true;
   1.169 +}
   1.170 +
   1.171 +bool CDecoder::ReadLastTables()
   1.172 +{
   1.173 +  // it differs a little from pure RAR sources;
   1.174 +  // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2;
   1.175 +  // + 2 works for: return 0xFF; in CInBuffer::ReadByte.
   1.176 +  if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect;
   1.177 +  // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
   1.178 +    if (m_AudioMode)
   1.179 +    {
   1.180 +      UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream);
   1.181 +      if (symbol == 256)
   1.182 +        return ReadTables();
   1.183 +      if (symbol >= kMMTableSize)
   1.184 +        return false;
   1.185 +    }
   1.186 +    else
   1.187 +    {
   1.188 +      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
   1.189 +      if (number == kReadTableNumber)
   1.190 +        return ReadTables();
   1.191 +      if (number >= kMainTableSize)
   1.192 +        return false;
   1.193 +    }
   1.194 +  return true;
   1.195 +}
   1.196 +
   1.197 +class CCoderReleaser
   1.198 +{
   1.199 +  CDecoder *m_Coder;
   1.200 +public:
   1.201 +  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
   1.202 +  ~CCoderReleaser()
   1.203 +  {
   1.204 +    m_Coder->ReleaseStreams();
   1.205 +  }
   1.206 +};
   1.207 +
   1.208 +bool CDecoder::DecodeMm(UInt32 pos)
   1.209 +{
   1.210 +  while (pos-- > 0)
   1.211 +  {
   1.212 +    UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream);
   1.213 +    if (symbol == 256)
   1.214 +      return true;
   1.215 +    if (symbol >= kMMTableSize)
   1.216 +      return false;
   1.217 +    /*
   1.218 +    Byte byPredict = m_Predictor.Predict();
   1.219 +    Byte byReal = (Byte)(byPredict - (Byte)symbol);
   1.220 +    m_Predictor.Update(byReal, byPredict);
   1.221 +    */
   1.222 +    Byte byReal = m_MmFilter.Decode((Byte)symbol);
   1.223 +    m_OutWindowStream.PutByte(byReal);
   1.224 +    if (++m_MmFilter.CurrentChannel == m_NumChannels)
   1.225 +      m_MmFilter.CurrentChannel = 0;
   1.226 +  }
   1.227 +  return true;
   1.228 +}
   1.229 +
   1.230 +bool CDecoder::DecodeLz(Int32 pos)
   1.231 +{
   1.232 +  while (pos > 0)
   1.233 +  {
   1.234 +    UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
   1.235 +    UInt32 length, distance;
   1.236 +    if (number < 256)
   1.237 +    {
   1.238 +      m_OutWindowStream.PutByte(Byte(number));
   1.239 +      pos--;
   1.240 +      continue;
   1.241 +    }
   1.242 +    else if (number >= kMatchNumber)
   1.243 +    {
   1.244 +      number -= kMatchNumber;
   1.245 +      length = kNormalMatchMinLen + UInt32(kLenStart[number]) +
   1.246 +        m_InBitStream.ReadBits(kLenDirectBits[number]);
   1.247 +      number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
   1.248 +      if (number >= kDistTableSize)
   1.249 +        return false;
   1.250 +      distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
   1.251 +      if (distance >= kDistLimit3)
   1.252 +      {
   1.253 +        length += 2 - ((distance - kDistLimit4) >> 31);
   1.254 +        // length++;
   1.255 +        // if (distance >= kDistLimit4)
   1.256 +        //  length++;
   1.257 +      }
   1.258 +    }
   1.259 +    else if (number == kRepBothNumber)
   1.260 +    {
   1.261 +      length = m_LastLength;
   1.262 +      distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];
   1.263 +    }
   1.264 +    else if (number < kLen2Number)
   1.265 +    {
   1.266 +      distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3];
   1.267 +      number = m_LenDecoder.DecodeSymbol(&m_InBitStream);
   1.268 +      if (number >= kLenTableSize)
   1.269 +        return false;
   1.270 +      length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);
   1.271 +      if (distance >= kDistLimit2)
   1.272 +      {
   1.273 +        length++;
   1.274 +        if (distance >= kDistLimit3)
   1.275 +        {
   1.276 +          length += 2 - ((distance - kDistLimit4) >> 31);
   1.277 +          // length++;
   1.278 +          // if (distance >= kDistLimit4)
   1.279 +          //   length++;
   1.280 +        }
   1.281 +      }
   1.282 +    }
   1.283 +    else if (number < kReadTableNumber)
   1.284 +    {
   1.285 +      number -= kLen2Number;
   1.286 +      distance = kLen2DistStarts[number] +
   1.287 +        m_InBitStream.ReadBits(kLen2DistDirectBits[number]);
   1.288 +      length = 2;
   1.289 +    }
   1.290 +    else if (number == kReadTableNumber)
   1.291 +      return true;
   1.292 +    else
   1.293 +      return false;
   1.294 +    m_RepDists[m_RepDistPtr++ & 3] = distance;
   1.295 +    m_LastLength = length;
   1.296 +    if (!m_OutWindowStream.CopyBlock(distance, length))
   1.297 +      return false;
   1.298 +    pos -= length;
   1.299 +  }
   1.300 +  return true;
   1.301 +}
   1.302 +
   1.303 +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
   1.304 +    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
   1.305 +{
   1.306 +  if (inSize == NULL || outSize == NULL)
   1.307 +    return E_INVALIDARG;
   1.308 +
   1.309 +  if (!m_OutWindowStream.Create(kHistorySize))
   1.310 +    return E_OUTOFMEMORY;
   1.311 +  if (!m_InBitStream.Create(1 << 20))
   1.312 +    return E_OUTOFMEMORY;
   1.313 +
   1.314 +  m_PackSize = *inSize;
   1.315 +
   1.316 +  UInt64 pos = 0, unPackSize = *outSize;
   1.317 +  
   1.318 +  m_OutWindowStream.SetStream(outStream);
   1.319 +  m_OutWindowStream.Init(m_IsSolid);
   1.320 +  m_InBitStream.SetStream(inStream);
   1.321 +  m_InBitStream.Init();
   1.322 +
   1.323 +  CCoderReleaser coderReleaser(this);
   1.324 +  if (!m_IsSolid)
   1.325 +  {
   1.326 +    InitStructures();
   1.327 +    if (unPackSize == 0)
   1.328 +    {
   1.329 +      if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
   1.330 +        if (!ReadTables())
   1.331 +          return S_FALSE;
   1.332 +      return S_OK;
   1.333 +    }
   1.334 +    if (!ReadTables())
   1.335 +      return S_FALSE;
   1.336 +  }
   1.337 +
   1.338 +  UInt64 startPos = m_OutWindowStream.GetProcessedSize();
   1.339 +  while(pos < unPackSize)
   1.340 +  {
   1.341 +    UInt32 blockSize = 1 << 20;
   1.342 +    if (blockSize > unPackSize - pos)
   1.343 +      blockSize = (UInt32)(unPackSize - pos);
   1.344 +    UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize();
   1.345 +    if (m_AudioMode)
   1.346 +    {
   1.347 +      if (!DecodeMm(blockSize))
   1.348 +        return S_FALSE;
   1.349 +    }
   1.350 +    else
   1.351 +    {
   1.352 +      if (!DecodeLz((Int32)blockSize))
   1.353 +        return S_FALSE;
   1.354 +    }
   1.355 +    UInt64 globalPos = m_OutWindowStream.GetProcessedSize();
   1.356 +    pos = globalPos - blockStartPos;
   1.357 +    if (pos < blockSize)
   1.358 +      if (!ReadTables())
   1.359 +        return S_FALSE;
   1.360 +    pos = globalPos - startPos;
   1.361 +    if (progress != 0)
   1.362 +    {
   1.363 +      UInt64 packSize = m_InBitStream.GetProcessedSize();
   1.364 +      RINOK(progress->SetRatioInfo(&packSize, &pos));
   1.365 +    }
   1.366 +  }
   1.367 +  if (pos > unPackSize)
   1.368 +    return S_FALSE;
   1.369 +
   1.370 +  if (!ReadLastTables())
   1.371 +    return S_FALSE;
   1.372 +  return m_OutWindowStream.Flush();
   1.373 +}
   1.374 +
   1.375 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
   1.376 +    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
   1.377 +{
   1.378 +  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
   1.379 +  catch(const CInBufferException &e) { return e.ErrorCode; }
   1.380 +  catch(const CLzOutWindowException &e) { return e.ErrorCode; }
   1.381 +  catch(...) { return S_FALSE; }
   1.382 +}
   1.383 +
   1.384 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
   1.385 +{
   1.386 +  if (size < 1)
   1.387 +    return E_INVALIDARG;
   1.388 +  m_IsSolid = (data[0] != 0);
   1.389 +  return S_OK;
   1.390 +}
   1.391 +
   1.392 +}}