RarStream.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using System;
  2. using System.IO;
  3. using SharpCompress.Common.Rar.Headers;
  4. namespace SharpCompress.Compressors.Rar
  5. {
  6. internal class RarStream : Stream
  7. {
  8. private readonly IRarUnpack unpack;
  9. private readonly FileHeader fileHeader;
  10. private readonly Stream readStream;
  11. private bool fetch;
  12. private byte[] tmpBuffer = new byte[65536];
  13. private int tmpOffset;
  14. private int tmpCount;
  15. private byte[] outBuffer;
  16. private int outOffset;
  17. private int outCount;
  18. private int outTotal;
  19. private bool isDisposed;
  20. public RarStream(IRarUnpack unpack, FileHeader fileHeader, Stream readStream)
  21. {
  22. this.unpack = unpack;
  23. this.fileHeader = fileHeader;
  24. this.readStream = readStream;
  25. fetch = true;
  26. unpack.DoUnpack(fileHeader, readStream, this);
  27. fetch = false;
  28. }
  29. protected override void Dispose(bool disposing)
  30. {
  31. if (!isDisposed) {
  32. isDisposed = true;
  33. base.Dispose(disposing);
  34. readStream.Dispose();
  35. }
  36. }
  37. public override bool CanRead => true;
  38. public override bool CanSeek => false;
  39. public override bool CanWrite => false;
  40. public override void Flush()
  41. {
  42. }
  43. public override long Length => fileHeader.UncompressedSize;
  44. public override long Position { get => fileHeader.UncompressedSize - unpack.DestSize; set => throw new NotSupportedException(); }
  45. public override int Read(byte[] buffer, int offset, int count)
  46. {
  47. outTotal = 0;
  48. if (tmpCount > 0)
  49. {
  50. int toCopy = tmpCount < count ? tmpCount : count;
  51. Buffer.BlockCopy(tmpBuffer, tmpOffset, buffer, offset, toCopy);
  52. tmpOffset += toCopy;
  53. tmpCount -= toCopy;
  54. offset += toCopy;
  55. count -= toCopy;
  56. outTotal += toCopy;
  57. }
  58. if (count > 0 && unpack.DestSize > 0)
  59. {
  60. outBuffer = buffer;
  61. outOffset = offset;
  62. outCount = count;
  63. fetch = true;
  64. unpack.DoUnpack();
  65. fetch = false;
  66. }
  67. return outTotal;
  68. }
  69. public override long Seek(long offset, SeekOrigin origin)
  70. {
  71. throw new NotSupportedException();
  72. }
  73. public override void SetLength(long value)
  74. {
  75. throw new NotSupportedException();
  76. }
  77. public override void Write(byte[] buffer, int offset, int count)
  78. {
  79. if (!fetch)
  80. {
  81. throw new NotSupportedException();
  82. }
  83. if (outCount > 0)
  84. {
  85. int toCopy = outCount < count ? outCount : count;
  86. Buffer.BlockCopy(buffer, offset, outBuffer, outOffset, toCopy);
  87. outOffset += toCopy;
  88. outCount -= toCopy;
  89. offset += toCopy;
  90. count -= toCopy;
  91. outTotal += toCopy;
  92. }
  93. if (count > 0)
  94. {
  95. if (tmpBuffer.Length < tmpCount + count)
  96. {
  97. byte[] newBuffer =
  98. new byte[tmpBuffer.Length * 2 > tmpCount + count ? tmpBuffer.Length * 2 : tmpCount + count];
  99. Buffer.BlockCopy(tmpBuffer, 0, newBuffer, 0, tmpCount);
  100. tmpBuffer = newBuffer;
  101. }
  102. Buffer.BlockCopy(buffer, offset, tmpBuffer, tmpCount, count);
  103. tmpCount += count;
  104. tmpOffset = 0;
  105. unpack.Suspended = true;
  106. }
  107. else
  108. {
  109. unpack.Suspended = false;
  110. }
  111. }
  112. }
  113. }