LzInWindow.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // LzInWindow.cs
  2. using System;
  3. namespace SevenZip.Compression.LZ
  4. {
  5. public class InWindow
  6. {
  7. public Byte[] _bufferBase = null; // pointer to buffer with data
  8. System.IO.Stream _stream;
  9. UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
  10. bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
  11. UInt32 _pointerToLastSafePosition;
  12. public UInt32 _bufferOffset;
  13. public UInt32 _blockSize; // Size of Allocated memory block
  14. public UInt32 _pos; // offset (from _buffer) of curent byte
  15. UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
  16. UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
  17. public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
  18. public void MoveBlock()
  19. {
  20. UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
  21. // we need one additional byte, since MovePos moves on 1 byte.
  22. if (offset > 0)
  23. offset--;
  24. UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
  25. // check negative offset ????
  26. for (UInt32 i = 0; i < numBytes; i++)
  27. _bufferBase[i] = _bufferBase[offset + i];
  28. _bufferOffset -= offset;
  29. }
  30. public virtual void ReadBlock()
  31. {
  32. if (_streamEndWasReached)
  33. return;
  34. while (true)
  35. {
  36. int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
  37. if (size == 0)
  38. return;
  39. int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
  40. if (numReadBytes == 0)
  41. {
  42. _posLimit = _streamPos;
  43. UInt32 pointerToPostion = _bufferOffset + _posLimit;
  44. if (pointerToPostion > _pointerToLastSafePosition)
  45. _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
  46. _streamEndWasReached = true;
  47. return;
  48. }
  49. _streamPos += (UInt32)numReadBytes;
  50. if (_streamPos >= _pos + _keepSizeAfter)
  51. _posLimit = _streamPos - _keepSizeAfter;
  52. }
  53. }
  54. void Free() { _bufferBase = null; }
  55. public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
  56. {
  57. _keepSizeBefore = keepSizeBefore;
  58. _keepSizeAfter = keepSizeAfter;
  59. UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
  60. if (_bufferBase == null || _blockSize != blockSize)
  61. {
  62. Free();
  63. _blockSize = blockSize;
  64. _bufferBase = new Byte[_blockSize];
  65. }
  66. _pointerToLastSafePosition = _blockSize - keepSizeAfter;
  67. }
  68. public void SetStream(System.IO.Stream stream) { _stream = stream; }
  69. public void ReleaseStream() { _stream = null; }
  70. public void Init()
  71. {
  72. _bufferOffset = 0;
  73. _pos = 0;
  74. _streamPos = 0;
  75. _streamEndWasReached = false;
  76. ReadBlock();
  77. }
  78. public void MovePos()
  79. {
  80. _pos++;
  81. if (_pos > _posLimit)
  82. {
  83. UInt32 pointerToPostion = _bufferOffset + _pos;
  84. if (pointerToPostion > _pointerToLastSafePosition)
  85. MoveBlock();
  86. ReadBlock();
  87. }
  88. }
  89. public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
  90. // index + limit have not to exceed _keepSizeAfter;
  91. public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
  92. {
  93. if (_streamEndWasReached)
  94. if ((_pos + index) + limit > _streamPos)
  95. limit = _streamPos - (UInt32)(_pos + index);
  96. distance++;
  97. // Byte *pby = _buffer + (size_t)_pos + index;
  98. UInt32 pby = _bufferOffset + _pos + (UInt32)index;
  99. UInt32 i;
  100. for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
  101. return i;
  102. }
  103. public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
  104. public void ReduceOffsets(Int32 subValue)
  105. {
  106. _bufferOffset += (UInt32)subValue;
  107. _posLimit -= (UInt32)subValue;
  108. _pos -= (UInt32)subValue;
  109. _streamPos -= (UInt32)subValue;
  110. }
  111. }
  112. }