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); }
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); }
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); } }
/// <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); }
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); }