コード例 #1
0
ファイル: Delta.cs プロジェクト: Qlala/CoreDump
        public static byte[] RA_ApplyStream(long pos, long size, Stream origin, Stream delta)
        {
            uint origin_ofst = (uint)origin.Position;
            uint base_delta_ofst = (uint)delta.Position;
            uint limit, total = 0;
            uint lenSrc   = (uint)origin.Length;
            uint lenDelta = (uint)delta.Length;

            Fossil.StreamReader zDelta = new Fossil.StreamReader(delta);

            limit = zDelta.GetInt();
            if (zDelta.GetChar() != '\n')
            {
                throw new Exception("size integer not terminated by \'\\n\'");
            }

            //Fossil.StreamWriter zOut = new Fossil.StreamWriter();
            List <byte> zOut = new List <byte>();

            while (zDelta.HaveBytes())
            {
                uint cnt, ofst, real_ofst, delta_ofst;
                cnt = zDelta.GetInt();

                switch (zDelta.GetChar())
                {
                case '@':
                    real_ofst = zDelta.GetInt();
                    ofst      = real_ofst + origin_ofst;

                    if (zDelta.HaveBytes() && zDelta.GetChar() != ',')
                    {
                        throw new Exception("copy command not terminated by \',\'");
                    }
                    total += cnt;
                    if (total > limit)
                    {
                        throw new Exception("copy exceeds output file size");
                    }
                    if (ofst + cnt > lenSrc)
                    {
                        throw new Exception("copy extends past end of input");
                    }
                    if ((pos <= real_ofst && real_ofst < pos + size) || pos <= +cnt && real_ofst < pos + cnt + size)
                    {
                        origin.Seek(Math.Max((int)ofst, (int)pos + origin_ofst), SeekOrigin.Begin);
                        for (int i = Math.Max((int)real_ofst, (int)pos); i < Math.Min((int)(real_ofst + cnt), pos + size); i++)
                        {
                            zOut.Add((byte)origin.ReadByte());
                        }
                    }
                    break;

                case ':':
                    total += cnt;
                    if (total > limit)
                    {
                        throw new Exception("insert command gives an output larger than predicted");
                    }
                    if (cnt > lenDelta)
                    {
                        throw new Exception("insert count exceeds size of delta");
                    }
                    delta_ofst = (uint)zDelta.BaseStream.Position - base_delta_ofst;
                    if ((pos <= delta_ofst && delta_ofst < pos + size) || pos <= +cnt && delta_ofst < pos + cnt + size)
                    {
                        zDelta.BaseStream.Seek(Math.Max((int)pos - delta_ofst, 0), SeekOrigin.Current);
                        for (int i = Math.Max((int)delta_ofst, (int)pos); i < Math.Min((int)(delta_ofst + cnt), pos + size); i++)
                        {
                            zOut.Add((byte)origin.ReadByte());
                        }
                    }
                    //zOut.PutArray(zDelta.BaseStream, (int)zDelta.BaseStream.Position, (int)(zDelta.BaseStream.Position + cnt));
                    //zDelta.BaseStream.Position += cnt;
                    break;

                case ';':
                    /*byte[] output = zOut.ToArray();
                     * if (cnt != Checksum(output))
                     * throw new Exception("bad checksum");
                     * if (total != limit)
                     * throw new Exception("generated size does not match predicted size");*/

                    return(zOut.ToArray());

                default:
                    throw new Exception("unknown delta operator");
                }
            }
            throw new Exception("unterminated delta");
        }
コード例 #2
0
ファイル: Delta.cs プロジェクト: Qlala/CoreDump
        public static MemoryStream ApplyStream(Stream origin, Stream delta)
        {
            uint origin_ofst = (uint)origin.Position;
            uint limit, total = 0;
            uint lenSrc   = (uint)origin.Length;
            uint lenDelta = (uint)delta.Length;

            Fossil.StreamReader zDelta = new Fossil.StreamReader(delta);

            limit = zDelta.GetInt();
            if (zDelta.GetChar() != '\n')
            {
                throw new Exception("size integer not terminated by \'\\n\'");
            }

            Fossil.StreamWriter zOut = new Fossil.StreamWriter();
            while (zDelta.HaveBytes())
            {
                uint cnt, ofst;
                cnt = zDelta.GetInt();

                switch (zDelta.GetChar())
                {
                case '@':
                    ofst = zDelta.GetInt() + origin_ofst;
                    if (zDelta.HaveBytes() && zDelta.GetChar() != ',')
                    {
                        throw new Exception("copy command not terminated by \',\'");
                    }
                    total += cnt;
                    if (total > limit)
                    {
                        throw new Exception("copy exceeds output file size");
                    }
                    if (ofst + cnt > lenSrc)
                    {
                        throw new Exception("copy extends past end of input");
                    }
                    zOut.PutArray(origin, (int)ofst, (int)(ofst + cnt));
                    break;

                case ':':
                    total += cnt;
                    if (total > limit)
                    {
                        throw new Exception("insert command gives an output larger than predicted");
                    }
                    if (cnt > lenDelta)
                    {
                        throw new Exception("insert count exceeds size of delta");
                    }
                    zOut.PutArray(zDelta.BaseStream, (int)zDelta.BaseStream.Position, (int)(zDelta.BaseStream.Position + cnt));
                    //zDelta.BaseStream.Position += cnt;
                    break;

                case ';':
                    byte[] output = zOut.ToArray();
                    if (cnt != Checksum(output))
                    {
                        throw new Exception("bad checksum");
                    }
                    if (total != limit)
                    {
                        throw new Exception("generated size does not match predicted size");
                    }
                    return(zOut.BaseStream);

                default:
                    throw new Exception("unknown delta operator");
                }
            }
            throw new Exception("unterminated delta");
        }