mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-13 05:25:00 +00:00
174 lines
6.6 KiB
C#
174 lines
6.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using SharpCompress.Common.SevenZip;
|
|
using SharpCompress.Compressor.LZMA.Utilites;
|
|
|
|
namespace SharpCompress.Compressor.LZMA
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
|
|
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.");
|
|
|
|
// We have multiple views into the same stream which will be used by several threads - need to sync those.
|
|
object sync = new object();
|
|
Stream[] inStreams = new Stream[folderInfo.PackStreams.Count];
|
|
for(int j = 0; j < folderInfo.PackStreams.Count; j++)
|
|
{
|
|
inStreams[j] = new SyncStreamView(sync, 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);
|
|
}
|
|
}
|
|
}
|