FragmentedWindow.unpack50frag_cpp.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 System;
  12. namespace SharpCompress.Compressors.Rar.UnpackV2017
  13. {
  14. internal partial class FragmentedWindow
  15. {
  16. public FragmentedWindow()
  17. {
  18. //memset(Mem,0,sizeof(Mem));
  19. //memset(MemSize,0,sizeof(MemSize));
  20. }
  21. //FragmentedWindow::~FragmentedWindow()
  22. //{
  23. // Reset();
  24. //}
  25. private void Reset()
  26. {
  27. for (uint I=0;I<Mem.Length;I++)
  28. if (Mem[I]!=null)
  29. {
  30. //free(Mem[I]);
  31. Mem[I]=null;
  32. }
  33. }
  34. public void Init(size_t WinSize)
  35. {
  36. Reset();
  37. uint BlockNum=0;
  38. size_t TotalSize=0; // Already allocated.
  39. while (TotalSize<WinSize && BlockNum<Mem.Length)
  40. {
  41. size_t Size=WinSize-TotalSize; // Size needed to allocate.
  42. // Minimum still acceptable block size. Next allocations cannot be larger
  43. // than current, so we do not need blocks if they are smaller than
  44. // "size left / attempts left". Also we do not waste time to blocks
  45. // smaller than some arbitrary constant.
  46. size_t MinSize=Math.Max(Size/(size_t)(Mem.Length-BlockNum), 0x400000);
  47. byte[] NewMem=null;
  48. while (Size>=MinSize)
  49. {
  50. NewMem=new byte[Size];
  51. if (NewMem!=null)
  52. break;
  53. Size-=Size/32;
  54. }
  55. if (NewMem==null)
  56. //throw std::bad_alloc();
  57. throw new InvalidOperationException();
  58. // Clean the window to generate the same output when unpacking corrupt
  59. // RAR files, which may access to unused areas of sliding dictionary.
  60. // sharpcompress: don't need this, freshly allocated above
  61. //Utility.Memset(NewMem,0,Size);
  62. Mem[BlockNum]=NewMem;
  63. TotalSize+=Size;
  64. MemSize[BlockNum]=TotalSize;
  65. BlockNum++;
  66. }
  67. if (TotalSize<WinSize) // Not found enough free blocks.
  68. //throw std::bad_alloc();
  69. throw new InvalidOperationException();
  70. }
  71. public byte this[size_t Item] {
  72. get {
  73. if (Item<MemSize[0])
  74. return Mem[0][Item];
  75. for (uint I=1;I<MemSize.Length;I++)
  76. if (Item<MemSize[I])
  77. return Mem[I][Item-MemSize[I-1]];
  78. return Mem[0][0]; // Must never happen;
  79. }
  80. set {
  81. if (Item<MemSize[0]) {
  82. Mem[0][Item] = value;
  83. return;
  84. }
  85. for (uint I=1;I<MemSize.Length;I++)
  86. if (Item<MemSize[I]) {
  87. Mem[I][Item-MemSize[I-1]] = value;
  88. return;
  89. }
  90. Mem[0][0] = value; // Must never happen;
  91. }
  92. }
  93. // sharpcompress: added the following code
  94. public void GetBuffer(size_t Item, out byte[] buf, out uint offset) {
  95. if (Item<MemSize[0]) {
  96. //return Mem[0][Item];
  97. buf = Mem[0]; offset = Item; return;
  98. }
  99. for (uint I=1;I<MemSize.Length;I++) {
  100. if (Item<MemSize[I]) {
  101. //return Mem[I][Item-MemSize[I-1]];
  102. buf = Mem[I]; offset = Item-MemSize[I-1]; return;
  103. }
  104. }
  105. //return Mem[0][0]; // Must never happen;
  106. buf = Mem[0]; offset = 0; return; // Must never happen;
  107. }
  108. public void CopyString(uint Length,uint Distance,ref size_t UnpPtr,size_t MaxWinMask)
  109. {
  110. size_t SrcPtr=UnpPtr-Distance;
  111. while (Length-- > 0)
  112. {
  113. this[UnpPtr]=this[SrcPtr++ & MaxWinMask];
  114. // We need to have masked UnpPtr after quit from loop, so it must not
  115. // be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
  116. UnpPtr=(UnpPtr+1) & MaxWinMask;
  117. }
  118. }
  119. public void CopyData(byte[] Dest, size_t destOffset, size_t WinPos,size_t Size)
  120. {
  121. for (size_t I=0;I<Size;I++)
  122. Dest[destOffset+I]=this[WinPos+I];
  123. }
  124. public size_t GetBlockSize(size_t StartPos,size_t RequiredSize)
  125. {
  126. for (uint I=0;I<MemSize.Length;I++)
  127. if (StartPos<MemSize[I])
  128. return Math.Min(MemSize[I]-StartPos,RequiredSize);
  129. return 0; // Must never be here.
  130. }
  131. }
  132. }