static void CreateInternal(byte[] oldData, byte[] newData, Stream output) { // check arguments if (oldData == null) { throw new ArgumentNullException("oldData"); } if (newData == null) { throw new ArgumentNullException("newData"); } if (output == null) { throw new ArgumentNullException("output"); } if (!output.CanSeek) { throw new ArgumentException("Output stream must be seekable.", "output"); } if (!output.CanWrite) { throw new ArgumentException("Output stream must be writable.", "output"); } /* Header is * 0 8 "BSDIFF40" * 8 8 length of bzip2ed ctrl block * 16 8 length of bzip2ed diff block * 24 8 length of new file */ /* File is * 0 32 Header * 32 ?? Bzip2ed ctrl block * ?? ?? Bzip2ed diff block * ?? ?? Bzip2ed extra block */ byte[] header = new byte[c_headerSize]; WriteInt64(c_fileSignature, header, 0); // "BSDIFF40" WriteInt64(0, header, 8); WriteInt64(0, header, 16); WriteInt64(newData.Length, header, 24); long startPosition = output.Position; output.Write(header, 0, header.Length); int[] I = SuffixSort(oldData); byte[] db = new byte[newData.Length]; byte[] eb = new byte[newData.Length]; int dblen = 0; int eblen = 0; using (WrappingStream wrappingStream = new WrappingStream(output, Ownership.None)) using (var bz2Stream = new BZip2Stream(wrappingStream, CompressionMode.Compress)) { // compute the differences, writing ctrl as we go int scan = 0; int pos = 0; int len = 0; int lastscan = 0; int lastpos = 0; int lastoffset = 0; while (scan < newData.Length) { int oldscore = 0; for (int scsc = scan += len; scan < newData.Length; scan++) { len = Search(I, oldData, newData, scan, 0, oldData.Length, out pos); for (; scsc < scan + len; scsc++) { if ((scsc + lastoffset < oldData.Length) && (oldData[scsc + lastoffset] == newData[scsc])) { oldscore++; } } if ((len == oldscore && len != 0) || (len > oldscore + 8)) { break; } if ((scan + lastoffset < oldData.Length) && (oldData[scan + lastoffset] == newData[scan])) { oldscore--; } } if (len != oldscore || scan == newData.Length) { int s = 0; int sf = 0; int lenf = 0; for (int i = 0; (lastscan + i < scan) && (lastpos + i < oldData.Length);) { if (oldData[lastpos + i] == newData[lastscan + i]) { s++; } i++; if (s * 2 - i > sf * 2 - lenf) { sf = s; lenf = i; } } int lenb = 0; if (scan < newData.Length) { s = 0; int sb = 0; for (int i = 1; (scan >= lastscan + i) && (pos >= i); i++) { if (oldData[pos - i] == newData[scan - i]) { s++; } if (s * 2 - i > sb * 2 - lenb) { sb = s; lenb = i; } } } if (lastscan + lenf > scan - lenb) { int overlap = (lastscan + lenf) - (scan - lenb); s = 0; int ss = 0; int lens = 0; for (int i = 0; i < overlap; i++) { if (newData[lastscan + lenf - overlap + i] == oldData[lastpos + lenf - overlap + i]) { s++; } if (newData[scan - lenb + i] == oldData[pos - lenb + i]) { s--; } if (s > ss) { ss = s; lens = i + 1; } } lenf += lens - overlap; lenb -= lens; } for (int i = 0; i < lenf; i++) { db[dblen + i] = (byte)(newData[lastscan + i] - oldData[lastpos + i]); } for (int i = 0; i < (scan - lenb) - (lastscan + lenf); i++) { eb[eblen + i] = newData[lastscan + lenf + i]; } dblen += lenf; eblen += (scan - lenb) - (lastscan + lenf); byte[] buf = new byte[8]; WriteInt64(lenf, buf, 0); bz2Stream.Write(buf, 0, 8); WriteInt64((scan - lenb) - (lastscan + lenf), buf, 0); bz2Stream.Write(buf, 0, 8); WriteInt64((pos - lenb) - (lastpos + lenf), buf, 0); bz2Stream.Write(buf, 0, 8); lastscan = scan - lenb; lastpos = pos - lenb; lastoffset = pos - scan; } } } // compute size of compressed ctrl data long controlEndPosition = output.Position; WriteInt64(controlEndPosition - startPosition - c_headerSize, header, 8); // write compressed diff data using (WrappingStream wrappingStream = new WrappingStream(output, Ownership.None)) using (var bz2Stream = new BZip2Stream(wrappingStream, CompressionMode.Compress)) { bz2Stream.Write(db, 0, dblen); } // compute size of compressed diff data long diffEndPosition = output.Position; WriteInt64(diffEndPosition - controlEndPosition, header, 16); // write compressed extra data, if any if (eblen > 0) { using (WrappingStream wrappingStream = new WrappingStream(output, Ownership.None)) using (var bz2Stream = new BZip2Stream(wrappingStream, CompressionMode.Compress)) { bz2Stream.Write(eb, 0, eblen); } } // seek to the beginning, write the header, then seek back to end long endPosition = output.Position; output.Position = startPosition; output.Write(header, 0, header.Length); output.Position = endPosition; }
private static void CreateInternal(byte[] oldData, byte[] newData, Stream output) { long num4; if (oldData == null) { throw new ArgumentNullException("oldData"); } if (newData == null) { throw new ArgumentNullException("newData"); } if (output == null) { throw new ArgumentNullException("output"); } if (!output.CanSeek) { throw new ArgumentException("Output stream must be seekable.", "output"); } if (!output.CanWrite) { throw new ArgumentException("Output stream must be writable.", "output"); } byte[] buf = new byte[0x20]; WriteInt64(0x3034464649445342L, buf, 0); WriteInt64(0L, buf, 8); WriteInt64(0L, buf, 0x10); WriteInt64((long)newData.Length, buf, 0x18); long position = output.Position; output.Write(buf, 0, buf.Length); int[] i = SuffixSort(oldData); byte[] buffer = new byte[newData.Length]; byte[] buffer3 = new byte[newData.Length]; int count = 0; int num3 = 0; using (WrappingStream stream = new WrappingStream(output, Ownership.None)) { using (BZip2OutputStream stream2 = new BZip2OutputStream(stream)) { int num12; int newOffset = 0; int pos = 0; int num8 = 0; int num9 = 0; int num10 = 0; int num11 = 0; goto TR_0059; TR_0049: if ((num8 != num12) || (newOffset == newData.Length)) { int num14 = 0; int num15 = 0; int num16 = 0; int num18 = 0; while (true) { if (((num9 + num18) >= newOffset) || ((num10 + num18) >= oldData.Length)) { int num17 = 0; if (newOffset < newData.Length) { num14 = 0; int num19 = 0; for (int j = 1; (newOffset >= (num9 + j)) && (pos >= j); j++) { if (oldData[pos - j] == newData[newOffset - j]) { num14++; } if (((num14 * 2) - j) > ((num19 * 2) - num17)) { num19 = num14; num17 = j; } } } if ((num9 + num16) > (newOffset - num17)) { int num21 = (num9 + num16) - (newOffset - num17); num14 = 0; int num22 = 0; int num23 = 0; int num24 = 0; while (true) { if (num24 >= num21) { num16 += num23 - num21; num17 -= num23; break; } if (newData[((num9 + num16) - num21) + num24] == oldData[((num10 + num16) - num21) + num24]) { num14++; } if (newData[(newOffset - num17) + num24] == oldData[(pos - num17) + num24]) { num14--; } if (num14 > num22) { num22 = num14; num23 = num24 + 1; } num24++; } } int num25 = 0; while (true) { if (num25 >= num16) { int num26 = 0; while (true) { if (num26 >= ((newOffset - num17) - (num9 + num16))) { count += num16; num3 += (newOffset - num17) - (num9 + num16); byte[] buffer4 = new byte[8]; WriteInt64((long)num16, buffer4, 0); stream2.Write(buffer4, 0, 8); WriteInt64((long)((newOffset - num17) - (num9 + num16)), buffer4, 0); stream2.Write(buffer4, 0, 8); WriteInt64((long)((pos - num17) - (num10 + num16)), buffer4, 0); stream2.Write(buffer4, 0, 8); num9 = newOffset - num17; num10 = pos - num17; num11 = pos - newOffset; break; } buffer3[num3 + num26] = newData[(num9 + num16) + num26]; num26++; } break; } buffer[count + num25] = (byte)(newData[num9 + num25] - oldData[num10 + num25]); num25++; } break; } if (oldData[num10 + num18] == newData[num9 + num18]) { num14++; } num18++; if (((num14 * 2) - num18) > ((num15 * 2) - num16)) { num15 = num14; num16 = num18; } } } TR_0059: while (true) { if (newOffset < newData.Length) { num12 = 0; int num1 = newOffset + num8; int index = newOffset = num1; while (true) { if (newOffset >= newData.Length) { break; } num8 = Search(i, oldData, newData, newOffset, 0, oldData.Length, out pos); while (true) { if (index < (newOffset + num8)) { if (((index + num11) < oldData.Length) && (oldData[index + num11] == newData[index])) { num12++; } index++; continue; } if (((num8 != num12) || (num8 == 0)) && (num8 <= (num12 + 8))) { if (((newOffset + num11) < oldData.Length) && (oldData[newOffset + num11] == newData[newOffset])) { num12--; } newOffset++; break; } break; } } } else { goto TR_0021; } break; } goto TR_0049; } } TR_0021: num4 = output.Position; WriteInt64((num4 - position) - 0x20, buf, 8); using (WrappingStream stream3 = new WrappingStream(output, Ownership.None)) { using (BZip2OutputStream stream4 = new BZip2OutputStream(stream3)) { stream4.Write(buffer, 0, count); } } WriteInt64(output.Position - num4, buf, 0x10); using (WrappingStream stream5 = new WrappingStream(output, Ownership.None)) { using (BZip2OutputStream stream6 = new BZip2OutputStream(stream5)) { stream6.Write(buffer3, 0, num3); } } long num5 = output.Position; output.Position = position; output.Write(buf, 0, buf.Length); output.Position = num5; }