DecoderStream.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using System;
  2. using System.IO;
  3. using SharpCompress.Common.SevenZip;
  4. using SharpCompress.Compressors.LZMA.Utilites;
  5. using SharpCompress.IO;
  6. namespace SharpCompress.Compressors.LZMA
  7. {
  8. internal abstract class DecoderStream2 : Stream
  9. {
  10. public override bool CanRead => true;
  11. public override bool CanSeek => false;
  12. public override bool CanWrite => false;
  13. public override void Flush()
  14. {
  15. throw new NotSupportedException();
  16. }
  17. public override long Length => throw new NotSupportedException();
  18. public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
  19. public override long Seek(long offset, SeekOrigin origin)
  20. {
  21. throw new NotSupportedException();
  22. }
  23. public override void SetLength(long value)
  24. {
  25. throw new NotSupportedException();
  26. }
  27. public override void Write(byte[] buffer, int offset, int count)
  28. {
  29. throw new NotSupportedException();
  30. }
  31. }
  32. internal static class DecoderStreamHelper
  33. {
  34. private static int FindCoderIndexForOutStreamIndex(CFolder folderInfo, int outStreamIndex)
  35. {
  36. for (int coderIndex = 0; coderIndex < folderInfo._coders.Count; coderIndex++)
  37. {
  38. var coderInfo = folderInfo._coders[coderIndex];
  39. outStreamIndex -= coderInfo._numOutStreams;
  40. if (outStreamIndex < 0)
  41. {
  42. return coderIndex;
  43. }
  44. }
  45. throw new InvalidOperationException("Could not link output stream to coder.");
  46. }
  47. private static void FindPrimaryOutStreamIndex(CFolder folderInfo, out int primaryCoderIndex,
  48. out int primaryOutStreamIndex)
  49. {
  50. bool foundPrimaryOutStream = false;
  51. primaryCoderIndex = -1;
  52. primaryOutStreamIndex = -1;
  53. for (int outStreamIndex = 0, coderIndex = 0;
  54. coderIndex < folderInfo._coders.Count;
  55. coderIndex++)
  56. {
  57. for (int coderOutStreamIndex = 0;
  58. coderOutStreamIndex < folderInfo._coders[coderIndex]._numOutStreams;
  59. coderOutStreamIndex++, outStreamIndex++)
  60. {
  61. if (folderInfo.FindBindPairForOutStream(outStreamIndex) < 0)
  62. {
  63. if (foundPrimaryOutStream)
  64. {
  65. throw new NotSupportedException("Multiple output streams.");
  66. }
  67. foundPrimaryOutStream = true;
  68. primaryCoderIndex = coderIndex;
  69. primaryOutStreamIndex = outStreamIndex;
  70. }
  71. }
  72. }
  73. if (!foundPrimaryOutStream)
  74. {
  75. throw new NotSupportedException("No output stream.");
  76. }
  77. }
  78. private static Stream CreateDecoderStream(Stream[] packStreams, long[] packSizes, Stream[] outStreams,
  79. CFolder folderInfo, int coderIndex, IPasswordProvider pass)
  80. {
  81. var coderInfo = folderInfo._coders[coderIndex];
  82. if (coderInfo._numOutStreams != 1)
  83. {
  84. throw new NotSupportedException("Multiple output streams are not supported.");
  85. }
  86. int inStreamId = 0;
  87. for (int i = 0; i < coderIndex; i++)
  88. {
  89. inStreamId += folderInfo._coders[i]._numInStreams;
  90. }
  91. int outStreamId = 0;
  92. for (int i = 0; i < coderIndex; i++)
  93. {
  94. outStreamId += folderInfo._coders[i]._numOutStreams;
  95. }
  96. Stream[] inStreams = new Stream[coderInfo._numInStreams];
  97. for (int i = 0; i < inStreams.Length; i++, inStreamId++)
  98. {
  99. int bindPairIndex = folderInfo.FindBindPairForInStream(inStreamId);
  100. if (bindPairIndex >= 0)
  101. {
  102. int pairedOutIndex = folderInfo._bindPairs[bindPairIndex]._outIndex;
  103. if (outStreams[pairedOutIndex] != null)
  104. {
  105. throw new NotSupportedException("Overlapping stream bindings are not supported.");
  106. }
  107. int otherCoderIndex = FindCoderIndexForOutStreamIndex(folderInfo, pairedOutIndex);
  108. inStreams[i] = CreateDecoderStream(packStreams, packSizes, outStreams, folderInfo, otherCoderIndex,
  109. pass);
  110. //inStreamSizes[i] = folderInfo.UnpackSizes[pairedOutIndex];
  111. if (outStreams[pairedOutIndex] != null)
  112. {
  113. throw new NotSupportedException("Overlapping stream bindings are not supported.");
  114. }
  115. outStreams[pairedOutIndex] = inStreams[i];
  116. }
  117. else
  118. {
  119. int index = folderInfo.FindPackStreamArrayIndex(inStreamId);
  120. if (index < 0)
  121. {
  122. throw new NotSupportedException("Could not find input stream binding.");
  123. }
  124. inStreams[i] = packStreams[index];
  125. //inStreamSizes[i] = packSizes[index];
  126. }
  127. }
  128. long unpackSize = folderInfo._unpackSizes[outStreamId];
  129. return DecoderRegistry.CreateDecoderStream(coderInfo._methodId, inStreams, coderInfo._props, pass, unpackSize);
  130. }
  131. internal static Stream CreateDecoderStream(Stream inStream, long startPos, long[] packSizes, CFolder folderInfo,
  132. IPasswordProvider pass)
  133. {
  134. if (!folderInfo.CheckStructure())
  135. {
  136. throw new NotSupportedException("Unsupported stream binding structure.");
  137. }
  138. Stream[] inStreams = new Stream[folderInfo._packStreams.Count];
  139. for (int j = 0; j < folderInfo._packStreams.Count; j++)
  140. {
  141. inStreams[j] = new BufferedSubStream(inStream, startPos, packSizes[j]);
  142. startPos += packSizes[j];
  143. }
  144. Stream[] outStreams = new Stream[folderInfo._unpackSizes.Count];
  145. int primaryCoderIndex, primaryOutStreamIndex;
  146. FindPrimaryOutStreamIndex(folderInfo, out primaryCoderIndex, out primaryOutStreamIndex);
  147. return CreateDecoderStream(inStreams, packSizes, outStreams, folderInfo, primaryCoderIndex, pass);
  148. }
  149. }
  150. }