Beispiel #1
0
        public BinaryDiffLines(Stream BaseFile, AddCopyList List, int iBytesPerLine)
        {
            m_iBytesPerLine = iBytesPerLine;

            BaseFile.Seek(0, SeekOrigin.Begin);

            int iEntries = List.Count;
            for (int i = 0; i < iEntries; i++)
            {
                object oEntry = List[i];
                Addition A = oEntry as Addition;
                if (A != null)
                {
                    //Add A.arBytes to VerLines
                    int iLength = A.arBytes.Length;
                    using (MemoryStream M = new MemoryStream(A.arBytes, false))
                    {
                        AddBytesFromStream(M, 0, iLength, false, true);
                    }

                    //Move the ver position.
                    m_iVerPos += iLength;
                }
                else
                {
                    Copy C = (Copy)oEntry;

                    if (m_iBasePos < C.iBaseOffset)
                    {
                        //Add bytes to BaseLines from m_iBasePos to C.iBaseOffset-1
                        int iLength = C.iBaseOffset - m_iBasePos;
                        AddBytesFromStream(BaseFile, m_iBasePos, iLength, true, false);
                        m_iBasePos += iLength;
                    }

                    //Add copied bytes to both sets of lines.
                    AddBytesFromStream(BaseFile, C.iBaseOffset, C.iLength, true, true);

                    //Move the base and version positions.
                    m_iBasePos = C.iBaseOffset + C.iLength;
                    m_iVerPos += C.iLength;
                }
            }

            int iBaseLength = (int)BaseFile.Length;
            if (m_iBasePos < iBaseLength)
            {
                //Add bytes to BaseLines from m_iBasePos to m_Base.Length
                AddBytesFromStream(BaseFile, m_iBasePos, iBaseLength - m_iBasePos, true, false);
            }
        }
Beispiel #2
0
        private int EmitCodes(int iBasePos, int iVerPos, int iVerStart, Stream BaseFile, Stream VerFile, AddCopyList List)
        {
            if (iVerPos > iVerStart)
            {
                EmitAdd(iVerStart, iVerPos - iVerStart, VerFile, List);
            }

            int iCopyLength = ExtendMatch(BaseFile, iBasePos, VerFile, iVerPos);
            if (iCopyLength > 0)
            {
                EmitCopy(iBasePos, iCopyLength, BaseFile, List);
            }

            return iCopyLength;
        }
Beispiel #3
0
 protected virtual void EmitAdd(int iVerStart, int iLength, Stream VerFile, AddCopyList List)
 {
     Addition Add = new Addition();
     VerFile.Seek(iVerStart, SeekOrigin.Begin);
     Add.arBytes = new byte[iLength];
     VerFile.Read(Add.arBytes, 0, iLength);
     List.Add(Add);
 }
Beispiel #4
0
 protected virtual int EmitCopy(int iBasePos, int iLength, Stream BaseFile, AddCopyList List)
 {
     Copy C = new Copy();
     C.iBaseOffset = iBasePos;
     C.iLength = iLength;
     List.Add(C);
     return iLength;
 }
Beispiel #5
0
        /// <summary>
        /// Does a binary diff on the two streams and returns an <see cref="AddCopyList"/>
        /// of the differences.
        /// </summary>
        /// <param name="BaseFile">The base file.</param>
        /// <param name="VerFile">The version file.</param>
        /// <returns>An AddCopyList that can be used later to construct the version file from the base file.</returns>
        public AddCopyList Execute(Stream BaseFile, Stream VerFile)
        {
            if (!BaseFile.CanSeek || !VerFile.CanSeek)
            {
                throw new ArgumentException("The Base and Version streams must support seeking.");
            }

            TableEntry[] arTable = new TableEntry[m_iTableSize];
            AddCopyList List = new AddCopyList();

            BaseFile.Seek(0, SeekOrigin.Begin);
            VerFile.Seek(0, SeekOrigin.End);

            int iVerPos = 0;
            int iBasePos = 0;
            int iVerStart = 0;
            bool bBaseActive = true;
            uint uiVerHash = 0;
            uint uiBaseHash = 0;
            int iLastVerHashPos = 0;
            int iLastBaseHashPos = 0;

            while (iVerPos <= (VerFile.Length - m_iFootprintLength))
            {
                //The GetTableEntry procedure will add the entry if it isn't already there.
                //This gives us a default behavior of favoring the first match.
                uiVerHash = Footprint(VerFile, iVerPos, ref iLastVerHashPos, uiVerHash);
                TableEntry VerEntry = GetTableEntry(arTable, uiVerHash, VerFile, iVerPos);

                TableEntry BaseEntry = null;
                if (bBaseActive)
                {
                    uiBaseHash = Footprint(BaseFile, iBasePos, ref iLastBaseHashPos, uiBaseHash);
                    BaseEntry = GetTableEntry(arTable, uiBaseHash, BaseFile, iBasePos);
                }

                if (BaseFile == VerEntry.File && Verify(BaseFile, VerEntry.Offset, VerFile, iVerPos))
                {
                    int iLength = EmitCodes(VerEntry.Offset, iVerPos, iVerStart, BaseFile, VerFile, List);
                    iBasePos = VerEntry.Offset + iLength;
                    iVerPos += iLength;
                    iVerStart = iVerPos;
                    FlushTable(arTable);
                    continue;
                }
                else if (m_bFavorLastMatch)
                {
                    VerEntry.Offset = iVerPos;
                    VerEntry.File = VerFile;
                }

                bBaseActive = bBaseActive && (iBasePos <= (BaseFile.Length - m_iFootprintLength));
                if (bBaseActive)
                {
                    if (VerFile == BaseEntry.File && Verify(VerFile, BaseEntry.Offset, BaseFile, iBasePos)
                        && iVerStart <= BaseEntry.Offset)
                    {
                        int iLength = EmitCodes(iBasePos, BaseEntry.Offset, iVerStart, BaseFile, VerFile, List);
                        iVerPos = BaseEntry.Offset + iLength;
                        iBasePos += iLength;
                        iVerStart = iVerPos;
                        FlushTable(arTable);
                        continue;
                    }
                    else if (m_bFavorLastMatch)
                    {
                        BaseEntry.Offset = iBasePos;
                        BaseEntry.File = BaseFile;
                    }
                }

                iVerPos++;
                iBasePos++;
            }

            EmitCodes((int)BaseFile.Length, (int)VerFile.Length, iVerStart, BaseFile, VerFile, List);

            Debug.Assert(List.TotalByteLength == (int)VerFile.Length, "The total byte length of the AddCopyList MUST equal the length of the version file!");

            return List;
        }