mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
92 lines
2.8 KiB
Java
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");
|
|
}
|
|
}
|
|
}
|
|
}
|