unpackinline.cpp 3.7 KB

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