#if !Rar2017_64bit using nint = System.Int32; using nuint = System.UInt32; using size_t = System.UInt32; #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif using int64 = System.Int64; using System; using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; namespace SharpCompress.Compressors.Rar.UnpackV2017 { internal partial class Unpack { private void CopyString20(uint Length,uint Distance) { LastDist=OldDist[OldDistPtr++ & 3]=Distance; LastLength=Length; DestUnpSize-=Length; CopyString(Length,Distance); } internal static class Unpack20Local { public static readonly byte[] LDecode={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; public static readonly byte[] LBits= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; public static readonly uint[] DDecode={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; public static readonly byte[] DBits= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; public static readonly byte[] SDDecode={0,4,8,16,32,64,128,192}; public static readonly byte[] SDBits= {2,2,3, 4, 5, 6, 6, 6}; } private void Unpack20(bool Solid) { uint Bits; if (Suspended) UnpPtr=WrPtr; else { UnpInitData(Solid); if (!UnpReadBuf()) return; if ((!Solid || !TablesRead2) && !ReadTables20()) return; --DestUnpSize; } while (DestUnpSize>=0) { UnpPtr&=MaxWinMask; if (Inp.InAddr>ReadTop-30) if (!UnpReadBuf()) break; if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr) { UnpWriteBuf20(); if (Suspended) return; } if (UnpAudioBlock) { uint AudioNumber=DecodeNumber(Inp,MD[UnpCurChannel]); if (AudioNumber==256) { if (!ReadTables20()) break; continue; } Window[UnpPtr++]=DecodeAudio((int)AudioNumber); if (++UnpCurChannel==UnpChannels) UnpCurChannel=0; --DestUnpSize; continue; } uint Number=DecodeNumber(Inp,BlockTables.LD); if (Number<256) { Window[UnpPtr++]=(byte)Number; --DestUnpSize; continue; } if (Number>269) { uint Length=(uint)(LDecode[Number-=270]+3); if ((Bits=LBits[Number])>0) { Length+=Inp.getbits()>>(int)(16-Bits); Inp.addbits(Bits); } uint DistNumber=DecodeNumber(Inp,BlockTables.DD); uint Distance=DDecode[DistNumber]+1; if ((Bits=DBits[DistNumber])>0) { Distance+=Inp.getbits()>>(int)(16-Bits); Inp.addbits(Bits); } if (Distance>=0x2000) { Length++; if (Distance>=0x40000L) Length++; } CopyString20(Length,Distance); continue; } if (Number==269) { if (!ReadTables20()) break; continue; } if (Number==256) { CopyString20(LastLength,LastDist); continue; } if (Number<261) { uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; uint LengthNumber=DecodeNumber(Inp,BlockTables.RD); uint Length=(uint)(LDecode[LengthNumber]+2); if ((Bits=LBits[LengthNumber])>0) { Length+=Inp.getbits()>>(int)(16-Bits); Inp.addbits(Bits); } if (Distance>=0x101) { Length++; if (Distance>=0x2000) { Length++; if (Distance>=0x40000) Length++; } } CopyString20(Length,Distance); continue; } if (Number<270) { uint Distance=(uint)(SDDecode[Number-=261]+1); if ((Bits=SDBits[Number])>0) { Distance+=Inp.getbits()>>(int)(16-Bits); Inp.addbits(Bits); } CopyString20(2,Distance); continue; } } ReadLastTables(); UnpWriteBuf20(); } private void UnpWriteBuf20() { if (UnpPtr!=WrPtr) UnpSomeRead=true; if (UnpPtrReadTop-25) if (!UnpReadBuf()) return false; uint BitField=Inp.getbits(); UnpAudioBlock=(BitField & 0x8000)!=0; if ((BitField & 0x4000) != 0) Utility.Memset(UnpOldTable20,0,UnpOldTable20.Length); Inp.addbits(2); uint TableSize; if (UnpAudioBlock) { UnpChannels=((BitField>>12) & 3)+1; if (UnpCurChannel>=UnpChannels) UnpCurChannel=0; Inp.addbits(2); TableSize=MC20*UnpChannels; } else TableSize=NC20+DC20+RC20; for (uint I=0;I> 12); Inp.addbits(4); } MakeDecodeTables(BitLength,0,BlockTables.BD,BC20); for (uint I=0;IReadTop-5) if (!UnpReadBuf()) return false; uint Number=DecodeNumber(Inp,BlockTables.BD); if (Number<16) { Table[I]=(byte)((Number+UnpOldTable20[I]) & 0xf); I++; } else if (Number==16) { uint N=(Inp.getbits() >> 14)+3; Inp.addbits(2); if (I==0) return false; // We cannot have "repeat previous" code at the first position. else while (N-- > 0 && I> 13)+3; Inp.addbits(3); } else { N=(Inp.getbits() >> 9)+11; Inp.addbits(7); } while (N-- > 0 && IReadTop) return true; if (UnpAudioBlock) for (uint I=0;I=Inp.InAddr+5) if (UnpAudioBlock) { if (DecodeNumber(Inp,MD[UnpCurChannel])==256) ReadTables20(); } else if (DecodeNumber(Inp,BlockTables.LD)==269) ReadTables20(); } private void UnpInitData20(bool Solid) { if (!Solid) { TablesRead2=false; UnpAudioBlock=false; UnpChannelDelta=0; UnpCurChannel=0; UnpChannels=1; //memset(AudV,0,sizeof(AudV)); AudV = new AudioVariables[4]; Utility.Memset(UnpOldTable20, 0, UnpOldTable20.Length); //memset(MD,0,sizeof(MD)); MD = new DecodeTable[4]; } } private byte DecodeAudio(int Delta) { AudioVariables V=AudV[UnpCurChannel]; V.ByteCount++; V.D4=V.D3; V.D3=V.D2; V.D2=V.LastDelta-V.D1; V.D1=V.LastDelta; int PCh=8*V.LastChar+V.K1*V.D1+V.K2*V.D2+V.K3*V.D3+V.K4*V.D4+V.K5*UnpChannelDelta; PCh=(PCh>>3) & 0xFF; uint Ch=(uint)(PCh-Delta); int D=(sbyte)Delta; // Left shift of negative value is undefined behavior in C++, // so we cast it to unsigned to follow the standard. D=(int)((uint)D<<3); V.Dif[0]+=(uint)Math.Abs(D); V.Dif[1]+=(uint)Math.Abs(D-V.D1); V.Dif[2]+=(uint)Math.Abs(D+V.D1); V.Dif[3]+=(uint)Math.Abs(D-V.D2); V.Dif[4]+=(uint)Math.Abs(D+V.D2); V.Dif[5]+=(uint)Math.Abs(D-V.D3); V.Dif[6]+=(uint)Math.Abs(D+V.D3); V.Dif[7]+=(uint)Math.Abs(D-V.D4); V.Dif[8]+=(uint)Math.Abs(D+V.D4); V.Dif[9]+=(uint)Math.Abs(D-UnpChannelDelta); V.Dif[10]+=(uint)Math.Abs(D+UnpChannelDelta); UnpChannelDelta=V.LastDelta=(sbyte)(Ch-V.LastChar); V.LastChar=(int)Ch; if ((V.ByteCount & 0x1F)==0) { uint MinDif=V.Dif[0],NumMinDif=0; V.Dif[0]=0; for (uint I=1;I=-16) V.K1--; break; case 2: if (V.K1<16) V.K1++; break; case 3: if (V.K2>=-16) V.K2--; break; case 4: if (V.K2<16) V.K2++; break; case 5: if (V.K3>=-16) V.K3--; break; case 6: if (V.K3<16) V.K3++; break; case 7: if (V.K4>=-16) V.K4--; break; case 8: if (V.K4<16) V.K4++; break; case 9: if (V.K5>=-16) V.K5--; break; case 10: if (V.K5<16) V.K5++; break; } } return (byte)Ch; } } }