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 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 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 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 void GetNextFolderItem(CFolder folder) { Log.WriteLine("-- GetNextFolderItem --"); Log.PushIndent(); try { int numCoders = ReadNum(); Log.WriteLine("NumCoders: " + numCoders); folder.Coders = new List<CCoderInfo>(numCoders); int numInStreams = 0; int numOutStreams = 0; for (int i = 0; i < numCoders; i++) { Log.WriteLine("-- Coder --"); Log.PushIndent(); try { CCoderInfo coder = new CCoderInfo(); folder.Coders.Add(coder); byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); byte[] longID = new byte[idSize]; ReadBytes(longID, 0, idSize); Log.WriteLine("MethodId: " + String.Join("", Enumerable.Range(0, idSize).Select(x => longID[x].ToString("x2")))); if (idSize > 8) throw new NotSupportedException(); ulong id = 0; for (int j = 0; j < idSize; j++) id |= (ulong)longID[idSize - 1 - j] << (8 * j); coder.MethodId = new CMethodId(id); if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); Log.WriteLine("Complex Stream (In: " + coder.NumInStreams + " - Out: " + coder.NumOutStreams + ")"); } else { Log.WriteLine("Simple Stream (In: 1 - Out: 1)"); coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { int propsSize = ReadNum(); coder.Props = new byte[propsSize]; ReadBytes(coder.Props, 0, propsSize); Log.WriteLine("Settings: " + String.Join("", coder.Props.Select(bt => bt.ToString("x2")))); } if ((mainByte & 0x80) != 0) throw new NotSupportedException(); numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } finally { Log.PopIndent(); } } int numBindPairs = numOutStreams - 1; folder.BindPairs = new List<CBindPair>(numBindPairs); Log.WriteLine("BindPairs: " + numBindPairs); Log.PushIndent(); for (int i = 0; i < numBindPairs; i++) { CBindPair bp = new CBindPair(); bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); Log.WriteLine("#" + i + " - In: " + bp.InIndex + " - Out: " + bp.OutIndex); } Log.PopIndent(); if (numInStreams < numBindPairs) throw new NotSupportedException(); int numPackStreams = numInStreams - numBindPairs; //folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (int i = 0; i < numInStreams; i++) { if (folder.FindBindPairForInStream(i) < 0) { Log.WriteLine("Single PackStream: #" + i); folder.PackStreams.Add(i); break; } } if (folder.PackStreams.Count != 1) throw new NotSupportedException(); } else { Log.WriteLine("Multiple PackStreams ..."); Log.PushIndent(); for (int i = 0; i < numPackStreams; i++) { var num = ReadNum(); Log.WriteLine("#" + i + " - " + num); folder.PackStreams.Add(num); } Log.PopIndent(); } } finally { Log.PopIndent(); } }
private void ReadUnpackInfo(List<byte[]> dataVector, out List<CFolder> folders) { Log.WriteLine("-- ReadUnpackInfo --"); Log.PushIndent(); try { WaitAttribute(BlockType.Folder); int numFolders = ReadNum(); Log.WriteLine("NumFolders: {0}", numFolders); using (CStreamSwitch streamSwitch = new CStreamSwitch()) { streamSwitch.Set(this, dataVector); //folders.Clear(); //folders.Reserve(numFolders); folders = new List<CFolder>(numFolders); int index = 0; for (int i = 0; i < numFolders; i++) { var f = new CFolder { FirstPackStreamId = index }; folders.Add(f); GetNextFolderItem(f); index += f.PackStreams.Count; } } WaitAttribute(BlockType.CodersUnpackSize); Log.WriteLine("UnpackSizes:"); for (int i = 0; i < numFolders; i++) { CFolder folder = folders[i]; Log.Write(" #" + i + ":"); int numOutStreams = folder.GetNumOutStreams(); for (int j = 0; j < numOutStreams; j++) { long size = checked((long)ReadNumber()); Log.Write(" " + size); folder.UnpackSizes.Add(size); } Log.WriteLine(); } for (;;) { BlockType? type = ReadId(); if (type == BlockType.End) return; if (type == BlockType.CRC) { List<uint?> crcs = ReadHashDigests(numFolders); for (int i = 0; i < numFolders; i++) folders[i].UnpackCRC = crcs[i]; continue; } SkipData(); } } finally { Log.PopIndent(); } }
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)); }
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); }
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); }