Beispiel #1
0
        /// <summary>
        /// Class constructor
        /// </summary>
        /// <param name="baseFile"></param>
        /// <param name="list"></param>
        /// <param name="bytesPerLine"Number of bytes to display per line.></param>
        public BinaryDiffLines(Stream baseFile, AddCopyCollection list, int bytesPerLine)
        {
            this.bytesPerLine = bytesPerLine;

            baseFile.Seek(0, SeekOrigin.Begin);

            foreach (IAddCopy entry in list)
            {
                if (entry.IsAdd)
                {
                    // Add A's bytes to VerLines
                    Addition add    = (Addition)entry;
                    byte[]   bytes  = add.GetBytes();
                    int      length = bytes.Length;
                    using (MemoryStream stream = new MemoryStream(bytes, false))
                    {
                        this.AddBytesFromStream(stream, 0, length, false, true);
                    }

                    // Move the ver position.
                    this.versionPosition += length;
                }
                else
                {
                    Copy copy = (Copy)entry;

                    if (this.basePosition < copy.BaseOffset)
                    {
                        // Add bytes to BaseLines from this.iBasePos to C.iBaseOffset-1
                        int length = copy.BaseOffset - this.basePosition;
                        this.AddBytesFromStream(baseFile, this.basePosition, length, true, false);
                        this.basePosition += length;
                    }

                    // Add copied bytes to both sets of lines.
                    this.AddBytesFromStream(baseFile, copy.BaseOffset, copy.Length, true, true);

                    // Move the base and version positions.
                    this.basePosition     = copy.BaseOffset + copy.Length;
                    this.versionPosition += copy.Length;
                }
            }

            int baseLength = (int)baseFile.Length;

            if (this.basePosition < baseLength)
            {
                // Add bytes to BaseLines from this.iBasePos to this.Base.Length
                this.AddBytesFromStream(baseFile, this.basePosition, baseLength - this.basePosition, true, false);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Does a binary diff on the two streams and returns an <see cref="AddCopyCollection"/>
        /// of the differences.
        /// </summary>
        /// <param name="baseFile">The base file.</param>
        /// <param name="versionFile">The version file.</param>
        /// <returns>An AddCopyCollection that can be used later to construct the version file from the base file.</returns>
        public AddCopyCollection Execute(Stream baseFile, Stream versionFile,
                                         IDiffProgress progress)
        {
            if (!baseFile.CanSeek || !versionFile.CanSeek)
            {
                throw new ArgumentException("The Base and Version streams must support seeking.");
            }

            TableEntry[]      table  = new TableEntry[this.tableSize];
            List <IAddCopy>   list   = new List <IAddCopy>();
            AddCopyCollection result = new AddCopyCollection(list);

            baseFile.Seek(0, SeekOrigin.Begin);
            versionFile.Seek(0, SeekOrigin.End);

            int  verPos          = 0;
            int  basePos         = 0;
            int  verStart        = 0;
            bool isBaseActive    = true;
            uint verHash         = 0;
            uint baseHash        = 0;
            int  lastVerHashPos  = 0;
            int  lastBaseHashPos = 0;

            while (verPos <= (versionFile.Length - this.footprintLength))
            {
                progress.Token.ThrowIfCancellationRequested();

                // The GetTableEntry procedure will add the entry if it isn't already there.
                // This gives us a default behavior of favoring the first match.
                verHash = this.Footprint(versionFile, verPos, verHash, ref lastVerHashPos);
                TableEntry verEntry = GetTableEntry(table, verHash, versionFile, verPos);

                TableEntry baseEntry = null;
                if (isBaseActive)
                {
                    baseHash  = this.Footprint(baseFile, basePos, baseHash, ref lastBaseHashPos);
                    baseEntry = GetTableEntry(table, baseHash, baseFile, basePos);
                }

                if (baseFile == verEntry.File && Verify(baseFile, verEntry.Offset, versionFile, verPos))
                {
                    int length = this.EmitCodes(verEntry.Offset, verPos, verStart, baseFile, versionFile, list);
                    basePos  = verEntry.Offset + length;
                    verPos  += length;
                    verStart = verPos;
                    FlushTable(table);
                    continue;
                }
                else if (this.favorLastMatch)
                {
                    verEntry.Offset = verPos;
                    verEntry.File   = versionFile;
                }

                isBaseActive = isBaseActive && (basePos <= (baseFile.Length - this.footprintLength));
                if (isBaseActive)
                {
                    if (versionFile == baseEntry.File && Verify(versionFile, baseEntry.Offset, baseFile, basePos) &&
                        verStart <= baseEntry.Offset)
                    {
                        int length = this.EmitCodes(basePos, baseEntry.Offset, verStart, baseFile, versionFile, list);
                        verPos   = baseEntry.Offset + length;
                        basePos += length;
                        verStart = verPos;
                        FlushTable(table);
                        continue;
                    }
                    else if (this.favorLastMatch)
                    {
                        baseEntry.Offset = basePos;
                        baseEntry.File   = baseFile;
                    }
                }

                verPos++;
                basePos++;
            }

            this.EmitCodes((int)baseFile.Length, (int)versionFile.Length, verStart, baseFile, versionFile, list);

            Debug.Assert(
                result.TotalByteLength == (int)versionFile.Length,
                "The total byte length of the AddCopyCollection MUST equal the length of the version file!");
            return(result);
        }