mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-12 05:25:03 +00:00
176 lines
6.7 KiB
C#
176 lines
6.7 KiB
C#
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);
|
|
}
|
|
}
|
|
} |