public void Apply(string oldFileName, string newFileName, bool validate)
{
if (m_type == "COPY")
{
using (var fs = File.OpenWrite(newFileName))
{
m_compressedDiffStream.CopyTo(fs);
}
return;
}
var oldFileStream = File.OpenRead(oldFileName);
if (validate) // pre-validate
{
Debug.Assert(oldFileStream.Length == m_PTCH.m_sizeBefore);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(oldFileStream);
Debug.Assert(hash.Compare(m_MD5.m_md5Before), "Input MD5 mismatch!");
oldFileStream.Position = 0;
}
string dir = Path.GetDirectoryName(newFileName);
if (!Directory.Exists(dir) && !String.IsNullOrWhiteSpace(dir))
Directory.CreateDirectory(dir);
var newFileStream = File.Open(newFileName, FileMode.Create);
int newFileOffset = 0, oldFileOffset = 0;
while (newFileOffset < m_PTCH.m_sizeAfter)
{
var diffChunkSize = m_ctrlBlock.ReadInt32();
var extraChunkSize = m_ctrlBlock.ReadInt32();
var extraOffset = m_ctrlBlock.ReadUInt32();
Debug.Assert(newFileOffset + diffChunkSize <= m_PTCH.m_sizeAfter);
byte[] newChunk = new byte[diffChunkSize];
m_diffBlock.Read(newChunk, 0, diffChunkSize);
newFileStream.Write(newChunk, 0, diffChunkSize);
byte[] oldChunk = new byte[diffChunkSize];
oldFileStream.Position = oldFileOffset;
oldFileStream.Read(oldChunk, 0, diffChunkSize);
newFileStream.Position = newFileOffset;
for (int i = 0; i < diffChunkSize; ++i)
{
if ((oldFileOffset + i >= 0) && (oldFileOffset + i < m_PTCH.m_sizeBefore))
{
var nb = newChunk[i];
var ob = oldChunk[i];
newFileStream.WriteByte((byte)((nb + ob) % 256));
}
}
newFileOffset += diffChunkSize;
oldFileOffset += diffChunkSize;
Debug.Assert(newFileOffset + extraChunkSize <= m_PTCH.m_sizeAfter);
byte[] extraChunk = new byte[extraChunkSize];
m_extraBlock.Read(extraChunk, 0, extraChunkSize);
newFileStream.Write(extraChunk, 0, extraChunkSize);
newFileOffset += extraChunkSize;
oldFileOffset += (int)xsign(extraOffset);
}
if (validate) // post-validate
{
newFileStream.Position = 0;
Debug.Assert(newFileStream.Length == m_PTCH.m_sizeAfter);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(newFileStream);
Debug.Assert(hash.Compare(m_MD5.m_md5After), "Output MD5 mismatch!");
}
oldFileStream.Close();
newFileStream.Close();
}