2019-02-21 13:45:24 -08:00

92 lines
2.8 KiB
Java

// Copyright 2003-2005 Colin Percival. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.util;
import java.io.*;
import java.util.zip.GZIPInputStream;
/**
* This is a Java port of algorithm from Flutter framework bsdiff.dart.
* Note that this port uses 32-bit ints, which limits data size to 2GB.
**/
public abstract class BSDiff {
public static byte[] bspatch(byte[] olddata, byte[] diffdata) throws IOException {
InputStream in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
DataInputStream header = new DataInputStream(in);
byte[] magic = new byte[8];
header.read(magic);
if (!new String(magic).equals("BZDIFF40")) {
throw new IOException("Invalid magic");
}
int ctrllen = (int) header.readLong();
int datalen = (int) header.readLong();
int newsize = (int) header.readLong();
header.close();
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32);
DataInputStream cpf = new DataInputStream(new GZIPInputStream(in));
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32 + ctrllen);
InputStream dpf = new GZIPInputStream(in);
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32 + ctrllen + datalen);
InputStream epf = new GZIPInputStream(in);
byte[] newdata = new byte[newsize];
int oldpos = 0;
int newpos = 0;
while (newpos < newsize) {
int[] ctrl = new int[3];
for (int i = 0; i <= 2; i++) {
ctrl[i] = (int) cpf.readLong();
}
if (newpos + ctrl[0] > newsize) {
throw new IOException("Invalid ctrl[0]");
}
read(dpf, newdata, newpos, ctrl[0]);
for (int i = 0; i < ctrl[0]; i++) {
if ((oldpos + i >= 0) && (oldpos + i < olddata.length)) {
newdata[newpos + i] += olddata[oldpos + i];
}
}
newpos += ctrl[0];
oldpos += ctrl[0];
if (newpos + ctrl[1] > newsize) {
throw new IOException("Invalid ctrl[0]");
}
read(epf, newdata, newpos, ctrl[1]);
newpos += ctrl[1];
oldpos += ctrl[2];
}
cpf.close();
dpf.close();
epf.close();
return newdata;
}
private static void read(InputStream in, byte[] buf, int off, int len) throws IOException {
for (int i, n = 0; n < len; n += i) {
if ((i = in.read(buf, off + n, len - n)) < 0) {
throw new IOException("Unexpected EOF");
}
}
}
}