Example #1
0
        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.");
        }
Example #4
0
        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.");
        }
Example #5
0
        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();
            }
        }
Example #6
0
        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(); }
        }
Example #7
0
        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));
        }
Example #8
0
        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);
        }
Example #10
0
        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);
        }