Unpack.unpackinline_cpp.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #if !Rar2017_64bit
  2. using nint = System.Int32;
  3. using nuint = System.UInt32;
  4. using size_t = System.UInt32;
  5. #else
  6. using nint = System.Int64;
  7. using nuint = System.UInt64;
  8. using size_t = System.UInt64;
  9. #endif
  10. using int64 = System.Int64;
  11. using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
  12. namespace SharpCompress.Compressors.Rar.UnpackV2017
  13. {
  14. internal partial class Unpack
  15. {
  16. private void InsertOldDist(uint Distance)
  17. {
  18. OldDist[3]=OldDist[2];
  19. OldDist[2]=OldDist[1];
  20. OldDist[1]=OldDist[0];
  21. OldDist[0]=Distance;
  22. }
  23. //#ifdef _MSC_VER
  24. //#define FAST_MEMCPY
  25. //#endif
  26. private void CopyString(uint Length,uint Distance)
  27. {
  28. size_t SrcPtr=UnpPtr-Distance;
  29. if (SrcPtr<MaxWinSize-MAX_LZ_MATCH && UnpPtr<MaxWinSize-MAX_LZ_MATCH)
  30. {
  31. // If we are not close to end of window, we do not need to waste time
  32. // to "& MaxWinMask" pointer protection.
  33. // TODO: sharpcompress: non-optimized loop, we may be able to unroll and speed up
  34. var Window = this.Window;
  35. while (Length-- > 0)
  36. {
  37. Window[UnpPtr++] = Window[SrcPtr++];
  38. }
  39. // byte *Src=Window+SrcPtr;
  40. // byte *Dest=Window+UnpPtr;
  41. // UnpPtr+=Length;
  42. //
  43. //#if FAST_MEMCPY
  44. // if (Distance<Length) // Overlapping strings
  45. //#endif
  46. // while (Length>=8)
  47. // {
  48. // Dest[0]=Src[0];
  49. // Dest[1]=Src[1];
  50. // Dest[2]=Src[2];
  51. // Dest[3]=Src[3];
  52. // Dest[4]=Src[4];
  53. // Dest[5]=Src[5];
  54. // Dest[6]=Src[6];
  55. // Dest[7]=Src[7];
  56. //
  57. // Src+=8;
  58. // Dest+=8;
  59. // Length-=8;
  60. // }
  61. //#if FAST_MEMCPY
  62. // else
  63. // while (Length>=8)
  64. // {
  65. // // In theory we still could overlap here.
  66. // // Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8).
  67. // // But for real RAR archives Distance <= MaxWinSize - MAX_LZ_MATCH
  68. // // always, so overlap here is impossible.
  69. //
  70. // // This memcpy expanded inline by MSVC. We could also use uint64
  71. // // assignment, which seems to provide about the same speed.
  72. // memcpy(Dest,Src,8);
  73. //
  74. // Src+=8;
  75. // Dest+=8;
  76. // Length-=8;
  77. // }
  78. //#endif
  79. //
  80. // // Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
  81. // if (Length>0) { Dest[0]=Src[0];
  82. // if (Length>1) { Dest[1]=Src[1];
  83. // if (Length>2) { Dest[2]=Src[2];
  84. // if (Length>3) { Dest[3]=Src[3];
  85. // if (Length>4) { Dest[4]=Src[4];
  86. // if (Length>5) { Dest[5]=Src[5];
  87. // if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
  88. }
  89. else
  90. while (Length-- > 0) // Slow copying with all possible precautions.
  91. {
  92. Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
  93. // We need to have masked UnpPtr after quit from loop, so it must not
  94. // be replaced with 'Window[UnpPtr++ & MaxWinMask]'
  95. UnpPtr=(UnpPtr+1) & MaxWinMask;
  96. }
  97. }
  98. private uint DecodeNumber(BitInput Inp,DecodeTable Dec)
  99. {
  100. // Left aligned 15 bit length raw bit field.
  101. uint BitField=Inp.getbits() & 0xfffe;
  102. if (BitField<Dec.DecodeLen[Dec.QuickBits])
  103. {
  104. uint Code=BitField>>(int)(16-Dec.QuickBits);
  105. Inp.addbits(Dec.QuickLen[Code]);
  106. return Dec.QuickNum[Code];
  107. }
  108. // Detect the real bit length for current code.
  109. uint Bits=15;
  110. for (uint I=Dec.QuickBits+1;I<15;I++)
  111. if (BitField<Dec.DecodeLen[I])
  112. {
  113. Bits=I;
  114. break;
  115. }
  116. Inp.addbits(Bits);
  117. // Calculate the distance from the start code for current bit length.
  118. uint Dist=BitField-Dec.DecodeLen[Bits-1];
  119. // Start codes are left aligned, but we need the normal right aligned
  120. // number. So we shift the distance to the right.
  121. Dist>>=(int)(16-Bits);
  122. // Now we can calculate the position in the code list. It is the sum
  123. // of first position for current bit length and right aligned distance
  124. // between our bit field and start code for current bit length.
  125. uint Pos=Dec.DecodePos[Bits]+Dist;
  126. // Out of bounds safety check required for damaged archives.
  127. if (Pos>=Dec.MaxNum)
  128. Pos=0;
  129. // Convert the position in the code list to position in alphabet
  130. // and return it.
  131. return Dec.DecodeNum[Pos];
  132. }
  133. private uint SlotToLength(BitInput Inp,uint Slot)
  134. {
  135. uint LBits,Length=2;
  136. if (Slot<8)
  137. {
  138. LBits=0;
  139. Length+=Slot;
  140. }
  141. else
  142. {
  143. LBits=Slot/4-1;
  144. Length+=(4 | (Slot & 3)) << (int)LBits;
  145. }
  146. if (LBits>0)
  147. {
  148. Length+=Inp.getbits()>>(int)(16-LBits);
  149. Inp.addbits(LBits);
  150. }
  151. return Length;
  152. }
  153. }
  154. }