Пример #1
0
        public static byte[] Apply(byte[] origin, byte[] delta)
        {
            uint   limit, total = 0;
            uint   lenSrc   = (uint)origin.Length;
            uint   lenDelta = (uint)delta.Length;
            Reader zDelta   = new Reader(delta);

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

            Writer zOut = new Writer();

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

                switch (zDelta.GetChar())
                {
                case '@':
                    ofst = zDelta.GetInt();
                    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.a, (int)zDelta.pos, (int)(zDelta.pos + cnt));
                    zDelta.pos += cnt;
                    break;

                case ';':
                    byte[] output = zOut.ToArray();
                    //
                    // Checksum is optional (2017-10-05)
                    // http://fossil-scm.org/xfer/info/d3a46b2a45b92bbc
                    //
                    //if (cnt != Checksum (output))
                    //	throw new Exception("bad checksum");
                    if (total != limit)
                    {
                        throw new Exception("generated size does not match predicted size");
                    }
                    return(output);

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