예제 #1
0
        private void ReadUnpackInfo(DataReader mReader, out FolderInfo[] folders)
        {
            WaitAttribute(mReader, BlockType.Folder);
            {
                int numFolders = mReader.ReadPackedUInt31();
                folders = new FolderInfo[numFolders];
                for(int i = 0; i < folders.Length; i++)
                    folders[i] = GetNextFolderItem(mReader);
            }

            WaitAttribute(mReader, BlockType.CodersUnpackSize);
            {
                for(int i = 0; i < folders.Length; i++)
                {
                    var folder = folders[i];
                    folder.UnpackSizes = new ulong[folder.GetNumOutStreams()];
                    for(int j = 0; j < folder.UnpackSizes.Length; j++)
                        folder.UnpackSizes[j] = mReader.ReadPackedUInt64();
                }
            }

            for(; ; )
            {
                var type = ReadBlockType(mReader);
                if(type == BlockType.End)
                    break;

                if(type == BlockType.CRC)
                {
                    BitVector defined;
                    uint[] crcs;
                    ReadHashDigests(mReader, folders.Length, out defined, out crcs);
                    for(int i = 0; i < folders.Length; i++)
                        if(defined[i])
                            folders[i].UnpackCRC = crcs[i];
                    continue;
                }

                SkipAttribute(mReader);
            }
        }
예제 #2
0
        private void ReadSubStreamsInfo(DataReader mReader, FolderInfo[] folders, out int[] numUnpackStreamsInFolders, out List<ulong> unpackSizes, out BitVector crcDefined, out uint[] crcs)
        {
            numUnpackStreamsInFolders = new int[folders.Length];
            for(int i = 0; i < numUnpackStreamsInFolders.Length; i++)
                numUnpackStreamsInFolders[i] = 1;

            BlockType? type;
            for(; ; )
            {
                type = ReadBlockType(mReader);

                if(type == BlockType.NumUnpackStream)
                {
                    for(int i = 0; i < numUnpackStreamsInFolders.Length; i++)
                        numUnpackStreamsInFolders[i] = mReader.ReadPackedUInt31();
                    continue;
                }

                if(type == BlockType.End || type == BlockType.CRC || type == BlockType.Size)
                    break;

                SkipAttribute(mReader);
            }

            for(int i = 0; i < numUnpackStreamsInFolders.Length; i++)
            {
                int numSubstreams = numUnpackStreamsInFolders[i];
                if(numSubstreams == 0)
                    continue;

                ulong sum = 0;
                if(type == BlockType.Size)
                {
                    for(int j = 1; j < numSubstreams; j++)
                    {
                        ulong size = mReader.ReadPackedUInt64();
                        unpackSizes.Add(size);
                        sum += size;
                    }
                }

                unpackSizes.Add(folders[i].GetUnpackSize() - sum);
            }

            if(type == BlockType.Size)
                type = ReadBlockType(mReader);

            int numCRCs = 0;
            int numCRCsTotal = 0;
            for(int i = 0; i < folders.Length; i++)
            {
                int numSubstreams = numUnpackStreamsInFolders[i];
                if(numSubstreams != 1 || folders[i].UnpackCRC == null)
                    numCRCs += numSubstreams;
                numCRCsTotal += numSubstreams;
            }

            for(; ; )
            {
                if(type == BlockType.CRC)
                {
                    BitVector defined2;
                    uint[] crcs2;
                    ReadHashDigests(mReader, numCRCs, out defined2, out crcs2);

                }
                else if(type == BlockType.End)
                    break;
                else
                    SkipAttribute(mReader);

                type = ReadBlockType(mReader);
            }

            if(crcDefined == null)
            {
                throw new NotImplementedException();
            }
        }
예제 #3
0
        private FolderInfo GetNextFolderItem(DataReader mReader)
        {
            FolderInfo folder = new FolderInfo();
            int numInStreams = 0;
            int numOutStreams = 0;
            int numCoders = mReader.ReadPackedUInt31();
            folder.Coders = new CoderInfo[numCoders];
            for(int i = 0; i < numCoders; i++)
            {
                CoderInfo coder = new CoderInfo();
                folder.Coders[i] = coder;

                byte mainByte = mReader.ReadByte();

                int idSize = mainByte & 15;
                if(idSize > 8) // standard 7z also is limited to 8 byte coder ids
                    throw new InvalidDataException();

                ulong id = 0;
                for(int j = idSize - 1; j >= 0; j--)
                    id += (ulong)mReader.ReadByte() << (j * 8);

                coder.MethodId = id;

                if((mainByte & 0x10) != 0)
                {
                    coder.NumInStreams = mReader.ReadPackedUInt31();
                    coder.NumOutStreams = mReader.ReadPackedUInt31();
                }
                else
                {
                    coder.NumInStreams = 1;
                    coder.NumOutStreams = 1;
                }

                if((mainByte & 0x20) != 0)
                {
                    int propsSize = mReader.ReadPackedUInt31();
                    coder.Props = mReader.ReadBytes(propsSize);
                }

                // TODO: Warn if 0x40 is set, since it is not defined in the supported versions of the format.

                if((mainByte & 0x80) != 0)
                    throw new InvalidDataException();

                numInStreams += coder.NumInStreams;
                numOutStreams += coder.NumOutStreams;
            }

            int numBindPairs = mReader.ReadPackedUInt31();
            folder.BindPairs = new BindPair[numBindPairs];
            for(int i = 0; i < numBindPairs; i++)
            {
                int inIndex = mReader.ReadPackedUInt31();
                int outIndex = mReader.ReadPackedUInt31();
                folder.BindPairs[i] = new BindPair(inIndex, outIndex);
            }

            if(numInStreams < numBindPairs)
                throw new InvalidDataException();

            int numPackStreams = numInStreams - numBindPairs;
            folder.PackStreams = new int[numPackStreams];
            if(numPackStreams == 1)
            {
                bool found = false;
                for(int i = 0; i < numInStreams; i++)
                {
                    if(folder.FindBindPairForInStream(i) < 0)
                    {
                        folder.PackStreams[0] = i;
                        found = true;
                        break;
                    }
                }
                if(!found)
                    throw new InvalidDataException();
            }
            else
            {
                for(int i = 0; i < numPackStreams; i++)
                    folder.PackStreams[i] = mReader.ReadPackedUInt31();
            }

            return folder;
        }
예제 #4
0
 private void ReadStreamsInfo(DataReader mReader, out ulong[] packSizes, out BitVector packCRCsDefined, out uint[] packCRCs, out FolderInfo[] folders,
     out int[] numUnpackStreamsInFolders, out List<ulong> unpackSizes, out BitVector crcDefined, out uint[] crcs)
 {
     packSizes = null;
     packCRCsDefined = null;
     packCRCs = null;
     folders = null;
     numUnpackStreamsInFolders = null;
     unpackSizes = null;
     crcDefined = null;
     crcs = null;
     for(; ; )
     {
         var type = ReadBlockType(mReader);
         switch(type)
         {
         case BlockType.End:
             return;
         case BlockType.PackInfo:
             ReadPackInfo(mReader, out packSizes, out packCRCsDefined, out packCRCs);
             break;
         case BlockType.UnpackInfo:
             ReadUnpackInfo(mReader, out folders);
             break;
         case BlockType.SubStreamsInfo:
             ReadSubStreamsInfo(mReader, folders, out numUnpackStreamsInFolders, out unpackSizes, out crcDefined, out crcs);
             break;
         default:
             throw new InvalidDataException();
         }
     }
 }