Files
sharpcompress/SharpCompress/Compressor/LZMA/DecoderStream.cs

176 lines
6.7 KiB
C#
Raw Normal View History

2013-04-28 11:25:37 +01:00
using System;
using System.IO;
using SharpCompress.Common.SevenZip;
using SharpCompress.Compressor.LZMA.Utilites;
2013-08-11 09:45:46 +01:00
using SharpCompress.IO;
2013-04-28 11:25:37 +01:00
namespace SharpCompress.Compressor.LZMA
{
2013-04-28 12:32:55 +01:00
internal abstract class DecoderStream2 : Stream
2013-04-28 11:25:37 +01:00
{
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();
}
}
2013-04-28 12:32:55 +01:00
internal static class DecoderStreamHelper
2013-04-28 11:25:37 +01:00
{
private static int FindCoderIndexForOutStreamIndex(CFolder folderInfo, int outStreamIndex)
{
2013-04-28 12:32:55 +01:00
for (int coderIndex = 0; coderIndex < folderInfo.Coders.Count; coderIndex++)
2013-04-28 11:25:37 +01:00
{
var coderInfo = folderInfo.Coders[coderIndex];
outStreamIndex -= coderInfo.NumOutStreams;
2013-04-28 12:32:55 +01:00
if (outStreamIndex < 0)
2013-04-28 11:25:37 +01:00
return coderIndex;
}
throw new InvalidOperationException("Could not link output stream to coder.");
}
2013-04-28 12:32:55 +01:00
private static void FindPrimaryOutStreamIndex(CFolder folderInfo, out int primaryCoderIndex,
out int primaryOutStreamIndex)
2013-04-28 11:25:37 +01:00
{
bool foundPrimaryOutStream = false;
primaryCoderIndex = -1;
primaryOutStreamIndex = -1;
2013-04-28 12:32:55 +01:00
for (int outStreamIndex = 0, coderIndex = 0;
coderIndex < folderInfo.Coders.Count;
coderIndex++)
2013-04-28 11:25:37 +01:00
{
2013-04-28 12:32:55 +01:00
for (int coderOutStreamIndex = 0;
coderOutStreamIndex < folderInfo.Coders[coderIndex].NumOutStreams;
coderOutStreamIndex++, outStreamIndex++)
2013-04-28 11:25:37 +01:00
{
2013-04-28 12:32:55 +01:00
if (folderInfo.FindBindPairForOutStream(outStreamIndex) < 0)
2013-04-28 11:25:37 +01:00
{
2013-04-28 12:32:55 +01:00
if (foundPrimaryOutStream)
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("Multiple output streams.");
foundPrimaryOutStream = true;
primaryCoderIndex = coderIndex;
primaryOutStreamIndex = outStreamIndex;
}
}
}
2013-04-28 12:32:55 +01:00
if (!foundPrimaryOutStream)
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("No output stream.");
}
2013-04-28 12:32:55 +01:00
private static Stream CreateDecoderStream(Stream[] packStreams, long[] packSizes, Stream[] outStreams,
CFolder folderInfo, int coderIndex, IPasswordProvider pass)
2013-04-28 11:25:37 +01:00
{
var coderInfo = folderInfo.Coders[coderIndex];
2013-04-28 12:32:55 +01:00
if (coderInfo.NumOutStreams != 1)
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("Multiple output streams are not supported.");
int inStreamId = 0;
2013-04-28 12:32:55 +01:00
for (int i = 0; i < coderIndex; i++)
2013-04-28 11:25:37 +01:00
inStreamId += folderInfo.Coders[i].NumInStreams;
int outStreamId = 0;
2013-04-28 12:32:55 +01:00
for (int i = 0; i < coderIndex; i++)
2013-04-28 11:25:37 +01:00
outStreamId += folderInfo.Coders[i].NumOutStreams;
Stream[] inStreams = new Stream[coderInfo.NumInStreams];
2013-04-28 12:32:55 +01:00
for (int i = 0; i < inStreams.Length; i++, inStreamId++)
2013-04-28 11:25:37 +01:00
{
int bindPairIndex = folderInfo.FindBindPairForInStream(inStreamId);
2013-04-28 12:32:55 +01:00
if (bindPairIndex >= 0)
2013-04-28 11:25:37 +01:00
{
int pairedOutIndex = folderInfo.BindPairs[bindPairIndex].OutIndex;
2013-04-28 12:32:55 +01:00
if (outStreams[pairedOutIndex] != null)
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("Overlapping stream bindings are not supported.");
int otherCoderIndex = FindCoderIndexForOutStreamIndex(folderInfo, pairedOutIndex);
2013-04-28 12:32:55 +01:00
inStreams[i] = CreateDecoderStream(packStreams, packSizes, outStreams, folderInfo, otherCoderIndex,
pass);
2013-04-28 11:25:37 +01:00
//inStreamSizes[i] = folderInfo.UnpackSizes[pairedOutIndex];
2013-04-28 12:32:55 +01:00
if (outStreams[pairedOutIndex] != null)
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("Overlapping stream bindings are not supported.");
outStreams[pairedOutIndex] = inStreams[i];
}
else
{
int index = folderInfo.FindPackStreamArrayIndex(inStreamId);
2013-04-28 12:32:55 +01:00
if (index < 0)
2013-04-28 11:25:37 +01:00
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);
}
2013-04-28 12:32:55 +01:00
internal static Stream CreateDecoderStream(Stream inStream, long startPos, long[] packSizes, CFolder folderInfo,
IPasswordProvider pass)
2013-04-28 11:25:37 +01:00
{
2013-04-28 12:32:55 +01:00
if (!folderInfo.CheckStructure())
2013-04-28 11:25:37 +01:00
throw new NotSupportedException("Unsupported stream binding structure.");
Stream[] inStreams = new Stream[folderInfo.PackStreams.Count];
2013-04-28 12:32:55 +01:00
for (int j = 0; j < folderInfo.PackStreams.Count; j++)
2013-04-28 11:25:37 +01:00
{
2013-08-11 09:45:46 +01:00
inStreams[j] = new ReadOnlySubStream(inStream, startPos, packSizes[j]);
2013-04-28 11:25:37 +01:00
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);
}
}
2013-04-28 12:32:55 +01:00
}