using System; using System.IO; using SharpCompress.Common.SevenZip; using SharpCompress.Compressor.LZMA.Utilites; using SharpCompress.IO; namespace SharpCompress.Compressor.LZMA { internal abstract class DecoderStream2 : Stream { public override bool CanRead { get { return true; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } public override void Flush() { throw new NotImplementedException(); } public override long Length { get { throw new NotImplementedException(); } } public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } } internal static class DecoderStreamHelper { private static int FindCoderIndexForOutStreamIndex(CFolder folderInfo, int outStreamIndex) { for (int coderIndex = 0; coderIndex < folderInfo.Coders.Count; coderIndex++) { var coderInfo = folderInfo.Coders[coderIndex]; outStreamIndex -= coderInfo.NumOutStreams; if (outStreamIndex < 0) return coderIndex; } throw new InvalidOperationException("Could not link output stream to coder."); } private static void FindPrimaryOutStreamIndex(CFolder folderInfo, out int primaryCoderIndex, out int primaryOutStreamIndex) { bool foundPrimaryOutStream = false; primaryCoderIndex = -1; primaryOutStreamIndex = -1; for (int outStreamIndex = 0, coderIndex = 0; coderIndex < folderInfo.Coders.Count; coderIndex++) { for (int coderOutStreamIndex = 0; coderOutStreamIndex < folderInfo.Coders[coderIndex].NumOutStreams; coderOutStreamIndex++, outStreamIndex++) { if (folderInfo.FindBindPairForOutStream(outStreamIndex) < 0) { if (foundPrimaryOutStream) throw new NotSupportedException("Multiple output streams."); foundPrimaryOutStream = true; primaryCoderIndex = coderIndex; primaryOutStreamIndex = outStreamIndex; } } } if (!foundPrimaryOutStream) throw new NotSupportedException("No output stream."); } private static Stream CreateDecoderStream(Stream[] packStreams, long[] packSizes, Stream[] outStreams, CFolder folderInfo, int coderIndex, IPasswordProvider pass) { var coderInfo = folderInfo.Coders[coderIndex]; if (coderInfo.NumOutStreams != 1) throw new NotSupportedException("Multiple output streams are not supported."); int inStreamId = 0; for (int i = 0; i < coderIndex; i++) inStreamId += folderInfo.Coders[i].NumInStreams; int outStreamId = 0; for (int i = 0; i < coderIndex; i++) outStreamId += folderInfo.Coders[i].NumOutStreams; Stream[] inStreams = new Stream[coderInfo.NumInStreams]; for (int i = 0; i < inStreams.Length; i++, inStreamId++) { int bindPairIndex = folderInfo.FindBindPairForInStream(inStreamId); if (bindPairIndex >= 0) { int pairedOutIndex = folderInfo.BindPairs[bindPairIndex].OutIndex; if (outStreams[pairedOutIndex] != null) throw new NotSupportedException("Overlapping stream bindings are not supported."); int otherCoderIndex = FindCoderIndexForOutStreamIndex(folderInfo, pairedOutIndex); inStreams[i] = CreateDecoderStream(packStreams, packSizes, outStreams, folderInfo, otherCoderIndex, pass); //inStreamSizes[i] = folderInfo.UnpackSizes[pairedOutIndex]; if (outStreams[pairedOutIndex] != null) throw new NotSupportedException("Overlapping stream bindings are not supported."); outStreams[pairedOutIndex] = inStreams[i]; } else { int index = folderInfo.FindPackStreamArrayIndex(inStreamId); if (index < 0) throw new NotSupportedException("Could not find input stream binding."); inStreams[i] = packStreams[index]; //inStreamSizes[i] = packSizes[index]; } } long unpackSize = folderInfo.UnpackSizes[outStreamId]; return DecoderRegistry.CreateDecoderStream(coderInfo.MethodId, inStreams, coderInfo.Props, pass, unpackSize); } internal static Stream CreateDecoderStream(Stream inStream, long startPos, long[] packSizes, CFolder folderInfo, IPasswordProvider pass) { if (!folderInfo.CheckStructure()) throw new NotSupportedException("Unsupported stream binding structure."); Stream[] inStreams = new Stream[folderInfo.PackStreams.Count]; for (int j = 0; j < folderInfo.PackStreams.Count; j++) { inStreams[j] = new ReadOnlySubStream(inStream, startPos, packSizes[j]); startPos += packSizes[j]; } Stream[] outStreams = new Stream[folderInfo.UnpackSizes.Count]; int primaryCoderIndex, primaryOutStreamIndex; FindPrimaryOutStreamIndex(folderInfo, out primaryCoderIndex, out primaryOutStreamIndex); return CreateDecoderStream(inStreams, packSizes, outStreams, folderInfo, primaryCoderIndex, pass); } } }